D6773: rust-hgpath: add HgPath and HgPathBuf structs to encapsulate handling of paths

yuja (Yuya Nishihara) phabricator at mercurial-scm.org
Sat Sep 21 23:15:35 EDT 2019


yuja added a comment.


  The series looks good as a start. Queued, thanks!
  
  > +impl ToString for HgPathError {
  
  Nit: `std::fmt::Display` can be implemented instead, and the `HgPathError`
  can be a `std::error::Error`.
  
  > +impl From<HgPathError> for std::io::Error {
  > +    fn from(e: HgPathError) -> Self {
  > +        std::io::Error::new(std::io::ErrorKind::InvalidData, e.to_string())
  > +    }
  
  Then, the `e` itself can be embedded in `io::Error`.
  
  > +impl HgPath {
  > +    pub fn new<S: AsRef<[u8]> + ?Sized>(s: &S) -> &Self {
  > +        unsafe { &*(s.as_ref() as *const [u8] as *const Self) }
  > +    }
  
  I moved the declaration of the `struct HgPath` close to this because it's
  so important that `HgPath` is basically a newtype of `[u8]`.
  
  > +    pub fn is_empty(&self) -> bool {
  > +        self.inner.len() == 0
  > +    }
  
  s/.len() == 0/.is_empty()/ in flight.
  
  > +    pub fn join<T: ?Sized + AsRef<HgPath>>(&self, other: &T) -> HgPathBuf {
  > +        let mut inner = self.inner.to_owned();
  > +        if inner.len() != 0 && inner.last() != Some(&b'/') {
  > +            inner.push(b'/');
  > +        }
  > +        inner.extend(other.as_ref().bytes());
  > +        HgPathBuf::from_bytes(&inner)
  > +    }
  
  Perhaps, it's simpler to branch by self.is_empty() first.
  
    if is_empty() {
        other.as_ref().to_owned()
    } else {
        # concatenate
    }
  
  
  
  > +    /// Checks for errors in the path, short-circuiting at the first one.
  > +    /// This generates fine-grained errors useful for debugging.
  > +    /// To simply check if the path is valid during tests, use `is_valid`.
  > +    pub fn check_state(&self) -> Result<(), HgPathError> {
  
  Nit: the word `state` seems confusing. I don't have a good naming skill,
  but I feel `validate()` or `validate_canonical_form()` is better.
  
  > +                b'/' => {
  > +                    if previous_byte.is_some() && previous_byte == Some(b'/') {
  > +                        return Err(HgPathError::ConsecutiveSlashes(
  > +                            bytes.to_vec(),
  > +                            index,
  > +                        ));
  > +                    }
  > +                }
  
  Nit: useless check for previous_byte.is_some()
  
  > +    pub fn push(&mut self, byte: u8) {
  > +        self.inner.push(byte);
  > +    }
  
  
  
  > +impl Extend<u8> for HgPathBuf {
  > +    fn extend<T: IntoIterator<Item = u8>>(&mut self, iter: T) {
  > +        self.inner.extend(iter);
  > +    }
  > +}
  
  `path.push()` and `path.extend(data)` seem weird since they don't care
  the path separator. Can we remove them?

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6773/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6773

To: Alphare, #hg-reviewers, kevincox
Cc: mjpieters, yuja, durin42, kevincox, mercurial-devel


More information about the Mercurial-devel mailing list