Relax MatchList to support slices of references

It must not consume `self`.

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2020-05-29 13:22:19 +02:00
parent 909586e6ad
commit 92591b0073

View File

@ -325,6 +325,24 @@ impl MatchListEntry for &'_ MatchEntry {
} }
} }
impl MatchListEntry for &'_ &'_ MatchEntry {
fn entry_matches(&self, path: &[u8], file_mode: Option<u32>) -> Option<MatchType> {
if self.matches(path, file_mode) {
Some(self.match_type())
} else {
None
}
}
fn entry_matches_exact(&self, path: &[u8], file_mode: Option<u32>) -> Option<MatchType> {
if self.matches_exact(path, file_mode) {
Some(self.match_type())
} else {
None
}
}
}
/// This provides `matches` and `matches_exact` methods to lists of `MatchEntry`s. /// This provides `matches` and `matches_exact` methods to lists of `MatchEntry`s.
/// ///
/// Technically this is implemented for anything you can turn into a `DoubleEndedIterator` over /// Technically this is implemented for anything you can turn into a `DoubleEndedIterator` over
@ -332,35 +350,39 @@ impl MatchListEntry for &'_ MatchEntry {
/// ///
/// In practice this means you can use it with slices or references to `Vec` or `VecDeque` etc. /// In practice this means you can use it with slices or references to `Vec` or `VecDeque` etc.
/// This makes it easier to use slices over entries or references to entries. /// This makes it easier to use slices over entries or references to entries.
pub trait MatchList: Sized { pub trait MatchList {
/// Check whether this list contains anything matching a prefix of the specified path, and the /// Check whether this list contains anything matching a prefix of the specified path, and the
/// specified file mode. /// specified file mode.
fn matches<T: AsRef<[u8]>>(self, path: T, file_mode: Option<u32>) -> Option<MatchType> { fn matches<T: AsRef<[u8]>>(&self, path: T, file_mode: Option<u32>) -> Option<MatchType> {
self.matches_do(path.as_ref(), file_mode) self.matches_do(path.as_ref(), file_mode)
} }
fn matches_do(self, path: &[u8], file_mode: Option<u32>) -> Option<MatchType>; fn matches_do(&self, path: &[u8], file_mode: Option<u32>) -> Option<MatchType>;
/// Check whether this list contains anything exactly matching the path and mode. /// Check whether this list contains anything exactly matching the path and mode.
fn matches_exact<T: AsRef<[u8]>>( fn matches_exact<T: AsRef<[u8]>>(
self, &self,
path: T, path: T,
file_mode: Option<u32>, file_mode: Option<u32>,
) -> Option<MatchType> { ) -> Option<MatchType> {
self.matches_exact_do(path.as_ref(), file_mode) self.matches_exact_do(path.as_ref(), file_mode)
} }
fn matches_exact_do(self, path: &[u8], file_mode: Option<u32>) -> Option<MatchType>; fn matches_exact_do(&self, path: &[u8], file_mode: Option<u32>) -> Option<MatchType>;
} }
impl<T> MatchList for T impl<'a, T> MatchList for T
where where
T: IntoIterator, T: 'a + ?Sized,
<T as IntoIterator>::IntoIter: DoubleEndedIterator, &'a T: IntoIterator,
<T as IntoIterator>::Item: MatchListEntry, <&'a T as IntoIterator>::IntoIter: DoubleEndedIterator,
<&'a T as IntoIterator>::Item: MatchListEntry,
{ {
fn matches_do(self, path: &[u8], file_mode: Option<u32>) -> Option<MatchType> { fn matches_do(&self, path: &[u8], file_mode: Option<u32>) -> Option<MatchType> {
for m in self.into_iter().rev() { // This is an &self method on a `T where T: 'a`.
let this: &'a Self = unsafe { std::mem::transmute(self) };
for m in this.into_iter().rev() {
if let Some(mt) = m.entry_matches(path, file_mode) { if let Some(mt) = m.entry_matches(path, file_mode) {
return Some(mt); return Some(mt);
} }
@ -369,8 +391,11 @@ where
None None
} }
fn matches_exact_do(self, path: &[u8], file_mode: Option<u32>) -> Option<MatchType> { fn matches_exact_do(&self, path: &[u8], file_mode: Option<u32>) -> Option<MatchType> {
for m in self.into_iter().rev() { // This is an &self method on a `T where T: 'a`.
let this: &'a Self = unsafe { std::mem::transmute(self) };
for m in this.into_iter().rev() {
if let Some(mt) = m.entry_matches_exact(path, file_mode) { if let Some(mt) = m.entry_matches_exact(path, file_mode) {
return Some(mt); return Some(mt);
} }
@ -396,6 +421,9 @@ fn assert_containers_implement_match_list() {
let list: Vec<&MatchEntry> = vec.iter().collect(); let list: Vec<&MatchEntry> = vec.iter().collect();
assert_eq!(list.matches("asdf", None), Some(MatchType::Include)); assert_eq!(list.matches("asdf", None), Some(MatchType::Include));
let list: &[&MatchEntry] = &list[..];
assert_eq!(list.matches("asdf", None), Some(MatchType::Include));
} }
#[test] #[test]