From 2982dee5e2f0ebd1dca8b51e9751952fa89f20bf Mon Sep 17 00:00:00 2001 From: asonix Date: Fri, 9 Jan 2026 22:59:59 -0600 Subject: [PATCH 1/4] Add Guard::into_inner_if_some Allows passing the Key slice to the predicate and receiving a parsed value, returning that parsed value as the first element of the returned tuple. This can avoid double-parsing of keys that might happen with just Guard::into_inner_if --- src/blob_tree/mod.rs | 21 +++++++++++++++++++++ src/iter_guard.rs | 13 +++++++++++++ src/tree/mod.rs | 13 +++++++++++++ 3 files changed, 47 insertions(+) diff --git a/src/blob_tree/mod.rs b/src/blob_tree/mod.rs index 3058ef556..e389ae42e 100644 --- a/src/blob_tree/mod.rs +++ b/src/blob_tree/mod.rs @@ -58,6 +58,27 @@ impl IterGuard for Guard { } } + fn into_inner_if_some( + self, + pred: impl Fn(&UserKey) -> Option, + ) -> crate::Result> { + let kv = self.kv?; + + if let Some(t) = pred(&kv.key.user_key) { + resolve_value_handle( + self.tree.id(), + self.tree.blobs_folder.as_path(), + &self.tree.index.config.cache, + &self.tree.index.config.descriptor_table, + &self.version, + kv, + ) + .map(|(_, v)| Some((t, v))) + } else { + Ok(None) + } + } + fn key(self) -> crate::Result { self.kv.map(|kv| kv.key.user_key) } diff --git a/src/iter_guard.rs b/src/iter_guard.rs index 63fb9312e..93081c6e0 100644 --- a/src/iter_guard.rs +++ b/src/iter_guard.rs @@ -19,6 +19,19 @@ pub trait IterGuard { pred: impl Fn(&UserKey) -> bool, ) -> crate::Result<(UserKey, Option)>; + /// Accesses the key-value pair if the predicate returns `Some(T)`. + /// + /// The predicate receives the key - if returning None, the value + /// may not be loaded if the tree is key-value separated. + /// + /// # Errors + /// + /// Will return `Err` if an IO error occurs. + fn into_inner_if_some( + self, + pred: impl Fn(&UserKey) -> Option, + ) -> crate::Result>; + /// Accesses the key-value pair. /// /// # Errors diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 4c804083a..518c613d0 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -49,6 +49,19 @@ impl IterGuard for Guard { } } + fn into_inner_if_some( + self, + pred: impl Fn(&UserKey) -> Option, + ) -> crate::Result> { + let (k, v) = self.0?; + + if let Some(t) = pred(&k) { + Ok(Some((t, v))) + } else { + Ok(None) + } + } + fn key(self) -> crate::Result { self.0.map(|(k, _)| k) } From d62f2cc0067fd67dcaaf6f308a562e9bca1a1a73 Mon Sep 17 00:00:00 2001 From: asonix Date: Fri, 9 Jan 2026 23:08:23 -0600 Subject: [PATCH 2/4] Add tests for into_inner_if_some --- tests/guard_if.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/tests/guard_if.rs b/tests/guard_if.rs index 6072d5d0f..5b9eb74f1 100644 --- a/tests/guard_if.rs +++ b/tests/guard_if.rs @@ -69,3 +69,68 @@ fn guard_into_inner_if_blob() -> lsm_tree::Result<()> { Ok(()) } + +#[test] +fn guard_into_inner_if_some() -> lsm_tree::Result<()> { + let folder = get_tmp_folder(); + + { + let tree = Config::new( + &folder, + SequenceNumberCounter::default(), + SequenceNumberCounter::default(), + ) + .open()?; + + tree.insert("earth#name", "earth", 0); + tree.insert("earth#color", "BLUE", 0); + + assert_eq!(2, tree.iter(SeqNo::MAX, None).count()); + + assert_eq!( + 1, + tree.iter(SeqNo::MAX, None) + .filter_map(|guard| { + guard + .into_inner_if_some(|key| if key.ends_with(b"#name") { Some(()) } else { None }) + .unwrap() + }) + .count(), + ); + } + + Ok(()) +} + +#[test] +fn guard_into_inner_if_some_blob() -> lsm_tree::Result<()> { + let folder = get_tmp_folder(); + + { + let tree = Config::new( + &folder, + SequenceNumberCounter::default(), + SequenceNumberCounter::default(), + ) + .with_kv_separation(Some(KvSeparationOptions::default().separation_threshold(1))) + .open()?; + + tree.insert("earth#name", "earth", 0); + tree.insert("earth#color", "BLUE", 0); + + assert_eq!(2, tree.iter(SeqNo::MAX, None).count()); + + assert_eq!( + 1, + tree.iter(SeqNo::MAX, None) + .filter_map(|guard| { + guard + .into_inner_if_some(|key| if key.ends_with(b"#name") { Some(()) } else { None }) + .unwrap() + }) + .count(), + ); + } + + Ok(()) +} From 3eb007742af1ecd13b90fd24bbcd537a56736197 Mon Sep 17 00:00:00 2001 From: asonix Date: Sat, 10 Jan 2026 10:38:42 -0600 Subject: [PATCH 3/4] cargo fmt --- tests/guard_if.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/guard_if.rs b/tests/guard_if.rs index 5b9eb74f1..ad654e47e 100644 --- a/tests/guard_if.rs +++ b/tests/guard_if.rs @@ -92,7 +92,13 @@ fn guard_into_inner_if_some() -> lsm_tree::Result<()> { tree.iter(SeqNo::MAX, None) .filter_map(|guard| { guard - .into_inner_if_some(|key| if key.ends_with(b"#name") { Some(()) } else { None }) + .into_inner_if_some(|key| { + if key.ends_with(b"#name") { + Some(()) + } else { + None + } + }) .unwrap() }) .count(), @@ -125,7 +131,13 @@ fn guard_into_inner_if_some_blob() -> lsm_tree::Result<()> { tree.iter(SeqNo::MAX, None) .filter_map(|guard| { guard - .into_inner_if_some(|key| if key.ends_with(b"#name") { Some(()) } else { None }) + .into_inner_if_some(|key| { + if key.ends_with(b"#name") { + Some(()) + } else { + None + } + }) .unwrap() }) .count(), From 85b9f79f72144fd878f0627b291f434b4d2eb8a2 Mon Sep 17 00:00:00 2001 From: asonix Date: Sat, 17 Jan 2026 15:06:38 -0600 Subject: [PATCH 4/4] Return unparsed UserKey if predicate returns None --- src/blob_tree/mod.rs | 6 +++--- src/iter_guard.rs | 2 +- src/tree/mod.rs | 6 +++--- tests/guard_if.rs | 2 ++ 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/blob_tree/mod.rs b/src/blob_tree/mod.rs index e389ae42e..cafde4373 100644 --- a/src/blob_tree/mod.rs +++ b/src/blob_tree/mod.rs @@ -61,7 +61,7 @@ impl IterGuard for Guard { fn into_inner_if_some( self, pred: impl Fn(&UserKey) -> Option, - ) -> crate::Result> { + ) -> crate::Result> { let kv = self.kv?; if let Some(t) = pred(&kv.key.user_key) { @@ -73,9 +73,9 @@ impl IterGuard for Guard { &self.version, kv, ) - .map(|(_, v)| Some((t, v))) + .map(|(_, v)| Ok((t, v))) } else { - Ok(None) + Ok(Err(kv.key.user_key)) } } diff --git a/src/iter_guard.rs b/src/iter_guard.rs index 93081c6e0..9e858d6dd 100644 --- a/src/iter_guard.rs +++ b/src/iter_guard.rs @@ -30,7 +30,7 @@ pub trait IterGuard { fn into_inner_if_some( self, pred: impl Fn(&UserKey) -> Option, - ) -> crate::Result>; + ) -> crate::Result>; /// Accesses the key-value pair. /// diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 518c613d0..9d2ba4f48 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -52,13 +52,13 @@ impl IterGuard for Guard { fn into_inner_if_some( self, pred: impl Fn(&UserKey) -> Option, - ) -> crate::Result> { + ) -> crate::Result> { let (k, v) = self.0?; if let Some(t) = pred(&k) { - Ok(Some((t, v))) + Ok(Ok((t, v))) } else { - Ok(None) + Ok(Err(k)) } } diff --git a/tests/guard_if.rs b/tests/guard_if.rs index ad654e47e..b2b486232 100644 --- a/tests/guard_if.rs +++ b/tests/guard_if.rs @@ -100,6 +100,7 @@ fn guard_into_inner_if_some() -> lsm_tree::Result<()> { } }) .unwrap() + .ok() }) .count(), ); @@ -139,6 +140,7 @@ fn guard_into_inner_if_some_blob() -> lsm_tree::Result<()> { } }) .unwrap() + .ok() }) .count(), );