From 84135b1961bc2406a2c5f76cf3bf7da9d44be000 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 25 Aug 2019 13:46:08 +0200 Subject: [PATCH] Add Entries::{find_by_id_substr, find_by_id_startswith} This patch adds functions to the Entries type which can be used for filtering by id, either with `contains()` or `starts_with()`. This is useful for the end-user functionality where the user specifies the ID of an entry only partially. The implementation still iterates over all entries. This could be improved, of course, by implementing a `find`-like function on `Store` directly. But for now, this is good enough. Signed-off-by: Matthias Beyer --- lib/core/libimagstore/src/iter.rs | 61 +++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/lib/core/libimagstore/src/iter.rs b/lib/core/libimagstore/src/iter.rs index 1c80d160..3dfd2b2f 100644 --- a/lib/core/libimagstore/src/iter.rs +++ b/lib/core/libimagstore/src/iter.rs @@ -222,6 +222,31 @@ impl<'a> Entries<'a> { StoreRetrieveIterator::new(Box::new(self.0.map(|r| r.map(|id| id.without_base()))), self.1) } + /// Find entries where the id contains a substring + /// + /// This is useful for finding entries if the user supplied only a part of the ID, for example + /// if the ID contains a UUID where the user did not specify the full UUID, E.G.: + /// + /// ```ignore + /// imag foo show 827d8596-fad1-4 + /// ``` + /// + /// # Note + /// + /// The substring match is done with `contains()`. + /// + pub fn find_by_id_substr<'b>(self, id_substr: &'b str) -> FindContains<'a, 'b> { + FindContains(self, id_substr) + } + + /// Find entries where the id starts with a substring + /// + /// Same as `Entries::find_by_id_substr()`, but using `starts_with()` rather than `contains`. + /// + pub fn find_by_id_startswith<'b>(self, id_substr: &'b str) -> FindStartsWith<'a, 'b> { + FindStartsWith(self, id_substr) + } + } impl<'a> Iterator for Entries<'a> { @@ -232,6 +257,42 @@ impl<'a> Iterator for Entries<'a> { } } +pub struct FindContains<'a, 'b>(Entries<'a>, &'b str); + +impl<'a, 'b> Iterator for FindContains<'a, 'b> { + type Item = Result; + + fn next(&mut self) -> Option { + loop { + match self.0.next() { + None => return None, + Some(Err(e)) => return Some(Err(e)), + Some(Ok(next)) => if next.local().to_string_lossy().contains(self.1) { + return Some(Ok(next)) + }, // else loop + } + } + } +} + +pub struct FindStartsWith<'a, 'b>(Entries<'a>, &'b str); + +impl<'a, 'b> Iterator for FindStartsWith<'a, 'b> { + type Item = Result; + + fn next(&mut self) -> Option { + loop { + match self.0.next() { + None => return None, + Some(Err(e)) => return Some(Err(e)), + Some(Ok(next)) => if next.local().to_string_lossy().starts_with(self.1) { + return Some(Ok(next)) + }, // else loop + } + } + } +} + #[cfg(test)] mod tests { extern crate env_logger;