rust/hg-core/src/dirstate_tree/path_with_basename.rs
author Simon Sapin <simon.sapin@octobus.net>
Fri, 30 Apr 2021 20:21:56 +0200
changeset 47126 ecfe0819ada5
parent 47119 15395fd8ab28
child 47283 2a9ddc8094c7
permissions -rw-r--r--
dirstate-tree: Borrow paths from the "on disk" bytes Use std::borrow::Cow to avoid some memory allocations and copying. Differential Revision: https://phab.mercurial-scm.org/D10560
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
47096
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     1
use crate::utils::hg_path::HgPath;
47126
ecfe0819ada5 dirstate-tree: Borrow paths from the "on disk" bytes
Simon Sapin <simon.sapin@octobus.net>
parents: 47119
diff changeset
     2
use std::borrow::{Borrow, Cow};
47096
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     3
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     4
/// Wraps `HgPath` or `HgPathBuf` to make it behave "as" its last path
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     5
/// component, a.k.a. its base name (as in Python’s `os.path.basename`), but
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     6
/// also allow recovering the full path.
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     7
///
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     8
/// "Behaving as" means that equality and comparison consider only the base
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     9
/// name, and `std::borrow::Borrow` is implemented to return only the base
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    10
/// name. This allows using the base name as a map key while still being able
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    11
/// to recover the full path, in a single memory allocation.
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    12
#[derive(Debug)]
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    13
pub struct WithBasename<T> {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    14
    full_path: T,
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    15
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    16
    /// The position after the last slash separator in `full_path`, or `0`
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    17
    /// if there is no slash.
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    18
    base_name_start: usize,
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    19
}
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    20
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    21
impl<T> WithBasename<T> {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    22
    pub fn full_path(&self) -> &T {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    23
        &self.full_path
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    24
    }
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    25
}
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    26
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    27
impl<T: AsRef<HgPath>> WithBasename<T> {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    28
    pub fn new(full_path: T) -> Self {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    29
        let base_name_start = if let Some(last_slash_position) = full_path
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    30
            .as_ref()
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    31
            .as_bytes()
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    32
            .iter()
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    33
            .rposition(|&byte| byte == b'/')
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    34
        {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    35
            last_slash_position + 1
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    36
        } else {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    37
            0
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    38
        };
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    39
        Self {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    40
            base_name_start,
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    41
            full_path,
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    42
        }
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    43
    }
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    44
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    45
    pub fn base_name(&self) -> &HgPath {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    46
        HgPath::new(
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    47
            &self.full_path.as_ref().as_bytes()[self.base_name_start..],
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    48
        )
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    49
    }
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    50
}
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    51
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    52
impl<T: AsRef<HgPath>> Borrow<HgPath> for WithBasename<T> {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    53
    fn borrow(&self) -> &HgPath {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    54
        self.base_name()
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    55
    }
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    56
}
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    57
47119
15395fd8ab28 dirstate-tree: Use HashMap instead of BTreeMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47096
diff changeset
    58
impl<T: AsRef<HgPath>> std::hash::Hash for WithBasename<T> {
15395fd8ab28 dirstate-tree: Use HashMap instead of BTreeMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47096
diff changeset
    59
    fn hash<H: std::hash::Hasher>(&self, hasher: &mut H) {
15395fd8ab28 dirstate-tree: Use HashMap instead of BTreeMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47096
diff changeset
    60
        self.base_name().hash(hasher)
15395fd8ab28 dirstate-tree: Use HashMap instead of BTreeMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47096
diff changeset
    61
    }
15395fd8ab28 dirstate-tree: Use HashMap instead of BTreeMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47096
diff changeset
    62
}
15395fd8ab28 dirstate-tree: Use HashMap instead of BTreeMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47096
diff changeset
    63
47096
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    64
impl<T: AsRef<HgPath> + PartialEq> PartialEq for WithBasename<T> {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    65
    fn eq(&self, other: &Self) -> bool {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    66
        self.base_name() == other.base_name()
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    67
    }
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    68
}
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    69
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    70
impl<T: AsRef<HgPath> + Eq> Eq for WithBasename<T> {}
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    71
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    72
impl<T: AsRef<HgPath> + PartialOrd> PartialOrd for WithBasename<T> {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    73
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    74
        self.base_name().partial_cmp(other.base_name())
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    75
    }
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    76
}
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    77
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    78
impl<T: AsRef<HgPath> + Ord> Ord for WithBasename<T> {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    79
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    80
        self.base_name().cmp(other.base_name())
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    81
    }
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    82
}
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    83
47126
ecfe0819ada5 dirstate-tree: Borrow paths from the "on disk" bytes
Simon Sapin <simon.sapin@octobus.net>
parents: 47119
diff changeset
    84
impl<'a> WithBasename<&'a HgPath> {
ecfe0819ada5 dirstate-tree: Borrow paths from the "on disk" bytes
Simon Sapin <simon.sapin@octobus.net>
parents: 47119
diff changeset
    85
    pub fn to_cow_borrowed(self) -> WithBasename<Cow<'a, HgPath>> {
47096
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    86
        WithBasename {
47126
ecfe0819ada5 dirstate-tree: Borrow paths from the "on disk" bytes
Simon Sapin <simon.sapin@octobus.net>
parents: 47119
diff changeset
    87
            full_path: Cow::Borrowed(self.full_path),
ecfe0819ada5 dirstate-tree: Borrow paths from the "on disk" bytes
Simon Sapin <simon.sapin@octobus.net>
parents: 47119
diff changeset
    88
            base_name_start: self.base_name_start,
ecfe0819ada5 dirstate-tree: Borrow paths from the "on disk" bytes
Simon Sapin <simon.sapin@octobus.net>
parents: 47119
diff changeset
    89
        }
ecfe0819ada5 dirstate-tree: Borrow paths from the "on disk" bytes
Simon Sapin <simon.sapin@octobus.net>
parents: 47119
diff changeset
    90
    }
ecfe0819ada5 dirstate-tree: Borrow paths from the "on disk" bytes
Simon Sapin <simon.sapin@octobus.net>
parents: 47119
diff changeset
    91
ecfe0819ada5 dirstate-tree: Borrow paths from the "on disk" bytes
Simon Sapin <simon.sapin@octobus.net>
parents: 47119
diff changeset
    92
    pub fn to_cow_owned<'b>(self) -> WithBasename<Cow<'b, HgPath>> {
ecfe0819ada5 dirstate-tree: Borrow paths from the "on disk" bytes
Simon Sapin <simon.sapin@octobus.net>
parents: 47119
diff changeset
    93
        WithBasename {
ecfe0819ada5 dirstate-tree: Borrow paths from the "on disk" bytes
Simon Sapin <simon.sapin@octobus.net>
parents: 47119
diff changeset
    94
            full_path: Cow::Owned(self.full_path.to_owned()),
47096
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    95
            base_name_start: self.base_name_start,
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    96
        }
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    97
    }
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    98
}
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    99
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   100
impl<'a> WithBasename<&'a HgPath> {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   101
    /// Returns an iterator of `WithBasename<&HgPath>` for the ancestor
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   102
    /// directory paths of the given `path`, as well as `path` itself.
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   103
    ///
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   104
    /// For example, the full paths of inclusive ancestors of "a/b/c" are "a",
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   105
    /// "a/b", and "a/b/c" in that order.
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   106
    pub fn inclusive_ancestors_of(
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   107
        path: &'a HgPath,
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   108
    ) -> impl Iterator<Item = WithBasename<&'a HgPath>> {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   109
        let mut slash_positions =
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   110
            path.as_bytes().iter().enumerate().filter_map(|(i, &byte)| {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   111
                if byte == b'/' {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   112
                    Some(i)
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   113
                } else {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   114
                    None
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   115
                }
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   116
            });
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   117
        let mut opt_next_component_start = Some(0);
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   118
        std::iter::from_fn(move || {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   119
            opt_next_component_start.take().map(|next_component_start| {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   120
                if let Some(slash_pos) = slash_positions.next() {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   121
                    opt_next_component_start = Some(slash_pos + 1);
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   122
                    Self {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   123
                        full_path: HgPath::new(&path.as_bytes()[..slash_pos]),
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   124
                        base_name_start: next_component_start,
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   125
                    }
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   126
                } else {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   127
                    // Not setting `opt_next_component_start` here: there will
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   128
                    // be no iteration after this one because `.take()` set it
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   129
                    // to `None`.
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   130
                    Self {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   131
                        full_path: path,
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   132
                        base_name_start: next_component_start,
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   133
                    }
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   134
                }
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   135
            })
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   136
        })
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   137
    }
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   138
}
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   139
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   140
#[test]
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   141
fn test() {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   142
    let a = WithBasename::new(HgPath::new("a").to_owned());
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   143
    assert_eq!(&**a.full_path(), HgPath::new(b"a"));
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   144
    assert_eq!(a.base_name(), HgPath::new(b"a"));
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   145
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   146
    let cba = WithBasename::new(HgPath::new("c/b/a").to_owned());
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   147
    assert_eq!(&**cba.full_path(), HgPath::new(b"c/b/a"));
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   148
    assert_eq!(cba.base_name(), HgPath::new(b"a"));
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   149
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   150
    assert_eq!(a, cba);
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   151
    let borrowed: &HgPath = cba.borrow();
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   152
    assert_eq!(borrowed, HgPath::new("a"));
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   153
}
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   154
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   155
#[test]
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   156
fn test_inclusive_ancestors() {
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   157
    let mut iter = WithBasename::inclusive_ancestors_of(HgPath::new("a/bb/c"));
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   158
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   159
    let next = iter.next().unwrap();
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   160
    assert_eq!(*next.full_path(), HgPath::new("a"));
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   161
    assert_eq!(next.base_name(), HgPath::new("a"));
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   162
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   163
    let next = iter.next().unwrap();
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   164
    assert_eq!(*next.full_path(), HgPath::new("a/bb"));
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   165
    assert_eq!(next.base_name(), HgPath::new("bb"));
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   166
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   167
    let next = iter.next().unwrap();
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   168
    assert_eq!(*next.full_path(), HgPath::new("a/bb/c"));
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   169
    assert_eq!(next.base_name(), HgPath::new("c"));
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   170
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   171
    assert!(iter.next().is_none());
3c11c24b82b6 dirstate-tree: Add `WithBasename` wrapper for `HgPath`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   172
}