77//! involved. Fetching and removing a value is, on the other hand, linear time in the size of the
88//! map.
99
10+ use crate :: span:: SpanText ;
1011use serde:: ser:: { Serialize , Serializer } ;
1112use std:: borrow:: Borrow ;
1213use std:: collections:: HashMap ;
@@ -33,6 +34,15 @@ use std::hash::Hash;
3334#[ derive( Clone , Debug , PartialEq , Default ) ]
3435pub struct VecMap < K , V > ( Vec < ( K , V ) > ) ;
3536
37+ /// Values that can be replaced by a special tombstone value that makes them to be ignored later in
38+ /// the pipeline. This makes their removal from a [VecMap] a bit more efficient (still a linear
39+ /// scan, but no shifting involved). Technically equivalent to [Default], but of course having a
40+ /// default value doesn't mean it's suitable as a `None`-like value (typically for a `f64` metrics,
41+ /// being `0` and being absent are entirely different)
42+ pub trait Tombstone {
43+ fn tombstone ( ) -> Self ;
44+ }
45+
3646impl < K , V > VecMap < K , V > {
3747 #[ must_use]
3848 #[ inline]
@@ -87,9 +97,9 @@ impl<K, V> VecMap<K, V> {
8797 }
8898
8999 /// Remove all entries matching this key from the map. This method uses [Vec::retain], and is
90- /// thus potentially costly (like any removal in a vector-like datastructure).
91- // Note: we might implement a tombstone or option-based deletion later, if removal is a bit too
92- // costly .
100+ /// thus potentially costly (like any removal in a vector-like datastructure). When applicable,
101+ /// prefer [Self::remove_unset], which replaces the entry with a special value (typically an
102+ /// empty string) that is treated as similar to being empty .
93103 #[ inline]
94104 pub fn remove_slow < Q > ( & mut self , key : & Q )
95105 where
@@ -128,6 +138,19 @@ impl<K, V> VecMap<K, V> {
128138 }
129139}
130140
141+ impl < K , V : Tombstone > VecMap < K , V > {
142+ #[ inline]
143+ pub fn remove_unset < Q > ( & mut self , key : & Q )
144+ where
145+ K : Borrow < Q > ,
146+ Q : ?Sized + PartialEq ,
147+ {
148+ self . iter_mut ( )
149+ . filter_map ( |( k, v) | ( ( * k) . borrow ( ) == key) . then_some ( v) )
150+ . for_each ( |v| * v = V :: tombstone ( ) )
151+ }
152+ }
153+
131154impl < K , V > From < Vec < ( K , V ) > > for VecMap < K , V > {
132155 fn from ( vec : Vec < ( K , V ) > ) -> Self {
133156 VecMap ( vec)
@@ -188,6 +211,12 @@ impl<K: Serialize + Eq + Hash, V: Serialize> Serialize for VecMap<K, V> {
188211 }
189212}
190213
214+ impl < T : SpanText > Tombstone for T {
215+ fn tombstone ( ) -> Self {
216+ Self :: default ( )
217+ }
218+ }
219+
191220#[ macro_export]
192221macro_rules! vec_map {
193222 ( ) => { $crate:: span:: vec_map:: VecMap :: new( ) } ;
@@ -272,4 +301,11 @@ mod tests {
272301 assert_eq ! ( obj. get( "a" ) . unwrap( ) , 3 ) ;
273302 assert_eq ! ( obj. get( "b" ) . unwrap( ) , 2 ) ;
274303 }
304+
305+ #[ test]
306+ fn macro_construction ( ) {
307+ let m: VecMap < & str , i32 > = vec_map ! [ ( "a" , 1 ) , ( "b" , 2 ) ] ;
308+ assert_eq ! ( m. get( "a" ) , Some ( & 1 ) ) ;
309+ assert_eq ! ( m. get( "b" ) , Some ( & 2 ) ) ;
310+ }
275311}
0 commit comments