# HG changeset patch # User Georges Racinet <georges.racinet@octobus.net> # Date 1693434811 -7200 # Thu Aug 31 00:33:31 2023 +0200 # Branch stable # Node ID b4465e96862f36d6ecb401c4421b4ccc8a274630 # Parent 831f85fc375aaee165c6e9ac6e1811bf9eda831a rhgitaly::util::common_subpath_split This utility method finds the greatest common denominator of two paths, and helps using the remainder in one of them. It takes care of the various edge cases (strict equality, trailing slashes) and will be used several times in the `GetTreeEntries` implementation. diff --git a/rust/rhgitaly/src/util.rs b/rust/rhgitaly/src/util.rs --- a/rust/rhgitaly/src/util.rs +++ b/rust/rhgitaly/src/util.rs @@ -21,3 +21,89 @@ } } } + +/// Return the common subpath as a subslice of `first` and the index after which the remainder +/// starts in `second`. +pub fn common_subpath_split<'a, 'b>(first: &'a [u8], second: &'b [u8]) -> (&'a [u8], usize) { + // position of the latest slash in `first` after the common subpath, if any. + let mut latest_slash: Option<usize> = None; + + let mut fit = first.iter(); + let mut sit = second.iter(); + let mut i: usize = 0; + + loop { + match fit.next() { + Some(fc) => match sit.next() { + None => { + if *fc == b'/' { + latest_slash = Some(i); + } + else{ break;} + } + Some(sc) => { + if *fc != *sc { + break; + } + if *fc == b'/' { + latest_slash = Some(i); + } + i += 1; + } + }, + None => match sit.next() { + None => { + return (first, first.len()); + } + Some(sc) => { + if *sc == b'/' { + return (first, first.len() + 1); + } else { + break; + } + } + }, + } + } + + match latest_slash { + None => (&[], 0), + Some(ls) => (&first[..ls], ls + 1), + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn test_common_subpath_split() { + assert_eq!(common_subpath_split(b"foo/a", b"bar"), (b"".as_ref(), 0)); + assert_eq!(common_subpath_split(b"bar", b"foo/a"), (b"".as_ref(), 0)); + assert_eq!( + common_subpath_split(b"foo/a", b"foo/b"), + (b"foo".as_ref(), 4) + ); + assert_eq!(common_subpath_split(b"foo/a", b"foox/a"), (b"".as_ref(), 0)); + assert_eq!(common_subpath_split(b"foox/a", b"foo/a"), (b"".as_ref(), 0)); + assert_eq!( + common_subpath_split(b"foo/a/", b"foo/a/b"), + (b"foo/a".as_ref(), 6) + ); + assert_eq!( + common_subpath_split(b"foo/a", b"foo/a/b"), + (b"foo/a".as_ref(), 6) + ); + assert_eq!( + common_subpath_split(b"foo/a/b", b"foo/a"), + (b"foo/a".as_ref(), 6) + ); + assert_eq!( + common_subpath_split(b"foo/a/b/c", b"foo/a/d/e"), + (b"foo/a".as_ref(), 6) + ); + assert_eq!(common_subpath_split(b"", b"foo/a"), (b"".as_ref(), 0)); + assert_eq!(common_subpath_split(b"foo/a", b""), (b"".as_ref(), 0)); + } +}