Skip to main content

datex_core/values/core_values/
map.rs

1use crate::{
2    collections::HashMap,
3    prelude::*,
4    random::RandomState,
5    references::reference::KeyNotFoundError,
6    traits::structural_eq::StructuralEq,
7    values::{
8        core_value::CoreValue,
9        value::Value,
10        value_container::{ValueContainer, ValueKey},
11    },
12};
13
14use core::{
15    fmt::{self, Display},
16    hash::{Hash, Hasher},
17    result::Result,
18};
19use indexmap::IndexMap;
20
21#[derive(Clone, Debug, Eq, PartialEq)]
22pub enum Map {
23    // most general case, allows all types of keys and values, and dynamic size
24    Dynamic(IndexMap<ValueContainer, ValueContainer, RandomState>),
25    // for fixed-size maps with known keys and values on construction
26    Structural(Vec<(ValueContainer, ValueContainer)>),
27    // for maps with string keys
28    StructuralWithStringKeys(Vec<(String, ValueContainer)>), // for structural maps with string keys
29}
30
31#[derive(Debug, Clone, PartialEq)]
32pub enum MapAccessError {
33    KeyNotFound(KeyNotFoundError),
34    Immutable,
35}
36
37impl Display for MapAccessError {
38    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39        match self {
40            MapAccessError::KeyNotFound(err) => {
41                core::write!(f, "{}", err)
42            }
43            MapAccessError::Immutable => {
44                core::write!(f, "Map is immutable")
45            }
46        }
47    }
48}
49
50impl Default for Map {
51    fn default() -> Self {
52        Map::Dynamic(IndexMap::default())
53    }
54}
55
56impl Map {
57    pub fn new(
58        entries: IndexMap<ValueContainer, ValueContainer, RandomState>,
59    ) -> Self {
60        Map::Dynamic(entries)
61    }
62
63    pub fn is_structural(&self) -> bool {
64        core::matches!(
65            self,
66            Map::StructuralWithStringKeys(_) | Map::Structural(_)
67        )
68    }
69
70    pub fn size(&self) -> usize {
71        match self {
72            Map::Dynamic(map) => map.len(),
73            Map::Structural(vec) => vec.len(),
74            Map::StructuralWithStringKeys(vec) => vec.len(),
75        }
76    }
77
78    pub fn is_empty(&self) -> bool {
79        self.size() == 0
80    }
81
82    /// Gets a value in the map by reference.
83    /// Returns None if the key is not found.
84    pub fn get<'a>(
85        &self,
86        key: impl Into<ValueKey<'a>>,
87    ) -> Result<&ValueContainer, KeyNotFoundError> {
88        let key = key.into();
89        match self {
90            Map::Dynamic(map) => key.with_value_container(|key| map.get(key)),
91            Map::Structural(vec) => key.with_value_container(|key| {
92                vec.iter().find(|(k, _)| k == key).map(|(_, v)| v)
93            }),
94            Map::StructuralWithStringKeys(vec) => {
95                // only works if key is a string
96                if let Some(string) = key.try_as_text() {
97                    vec.iter().find(|(k, _)| k == string).map(|(_, v)| v)
98                } else {
99                    None
100                }
101            }
102        }
103        .ok_or_else(|| KeyNotFoundError { key: key.into() })
104    }
105
106    /// Checks if the map contains the given key.
107    pub fn has<'a>(&self, key: impl Into<ValueKey<'a>>) -> bool {
108        match self {
109            Map::Dynamic(map) => {
110                key.into().with_value_container(|key| map.contains_key(key))
111            }
112            Map::Structural(vec) => key
113                .into()
114                .with_value_container(|key| vec.iter().any(|(k, _)| k == key)),
115            Map::StructuralWithStringKeys(vec) => {
116                // only works if key is a string
117                if let Some(string) = key.into().try_as_text() {
118                    vec.iter().any(|(k, _)| k == string)
119                } else {
120                    false
121                }
122            }
123        }
124    }
125
126    /// Removes a key from the map, returning the value if it existed.
127    pub fn delete<'a>(
128        &mut self,
129        key: impl Into<ValueKey<'a>>,
130    ) -> Result<ValueContainer, MapAccessError> {
131        let key = key.into();
132        match self {
133            Map::Dynamic(map) => key.with_value_container(|key| {
134                map.shift_remove(key).ok_or_else(|| {
135                    MapAccessError::KeyNotFound(KeyNotFoundError {
136                        key: key.clone(),
137                    })
138                })
139            }),
140            Map::Structural(_) | Map::StructuralWithStringKeys(_) => {
141                Err(MapAccessError::Immutable)
142            }
143        }
144    }
145
146    /// Clears all entries in the map, returning an error if the map is not dynamic.
147    pub fn clear(&mut self) -> Result<(), MapAccessError> {
148        match self {
149            Map::Dynamic(map) => {
150                map.clear();
151                Ok(())
152            }
153            Map::Structural(_) | Map::StructuralWithStringKeys(_) => {
154                Err(MapAccessError::Immutable)
155            }
156        }
157    }
158
159    /// Sets a value in the map, panicking if it fails.
160    pub(crate) fn set<'a>(
161        &mut self,
162        key: impl Into<ValueKey<'a>>,
163        value: impl Into<ValueContainer>,
164    ) {
165        self.try_set(key, value)
166            .expect("Setting value in map failed");
167    }
168
169    /// Sets a value in the map, returning an error if it fails.
170    /// This is the preferred way to set values in the map.
171    pub(crate) fn try_set<'a>(
172        &mut self,
173        key: impl Into<ValueKey<'a>>,
174        value: impl Into<ValueContainer>,
175    ) -> Result<(), KeyNotFoundError> {
176        let key = key.into();
177        match self {
178            Map::Dynamic(map) => {
179                key.with_value_container(|key| {
180                    map.insert(key.clone(), value.into());
181                });
182                Ok(())
183            }
184            Map::Structural(vec) => key.with_value_container(|key| {
185                if let Some((_, v)) = vec.iter_mut().find(|(k, _)| k == key) {
186                    *v = value.into();
187                    Ok(())
188                } else {
189                    Err(KeyNotFoundError { key: key.clone() })
190                }
191            }),
192            Map::StructuralWithStringKeys(vec) => {
193                if let Some(string) = key.try_as_text() {
194                    if let Some((_, v)) =
195                        vec.iter_mut().find(|(k, _)| k == string)
196                    {
197                        *v = value.into();
198                        Ok(())
199                    } else {
200                        Err(KeyNotFoundError { key: key.into() })
201                    }
202                } else {
203                    Err(KeyNotFoundError { key: key.into() })
204                }
205            }
206        }
207    }
208
209    pub(crate) fn iter(&self) -> MapIterator<'_> {
210        MapIterator {
211            map: self,
212            index: 0,
213        }
214    }
215}
216
217#[derive(Clone)]
218pub enum BorrowedMapKey<'a> {
219    Text(&'a str),
220    Value(&'a ValueContainer),
221}
222
223impl<'a> From<&'a MapKey> for BorrowedMapKey<'a> {
224    fn from(key: &'a MapKey) -> Self {
225        match key {
226            MapKey::Text(text) => BorrowedMapKey::Text(text),
227            MapKey::Value(value) => BorrowedMapKey::Value(value),
228        }
229    }
230}
231
232impl<'a> From<BorrowedMapKey<'a>> for ValueContainer {
233    fn from(key: BorrowedMapKey) -> Self {
234        match key {
235            BorrowedMapKey::Text(text) => {
236                ValueContainer::Value(Value::from(text))
237            }
238            BorrowedMapKey::Value(value) => value.clone(),
239        }
240    }
241}
242
243impl Hash for BorrowedMapKey<'_> {
244    fn hash<H: Hasher>(&self, state: &mut H) {
245        match self {
246            BorrowedMapKey::Text(text) => text.hash(state),
247            BorrowedMapKey::Value(value) => value.hash(state),
248        }
249    }
250}
251
252impl StructuralEq for BorrowedMapKey<'_> {
253    fn structural_eq(&self, other: &Self) -> bool {
254        match (self, other) {
255            (BorrowedMapKey::Text(a), BorrowedMapKey::Text(b)) => a == b,
256            (BorrowedMapKey::Value(a), BorrowedMapKey::Value(b)) => {
257                a.structural_eq(b)
258            }
259            (BorrowedMapKey::Text(a), BorrowedMapKey::Value(b))
260            | (BorrowedMapKey::Value(b), BorrowedMapKey::Text(a)) => {
261                if let ValueContainer::Value(Value {
262                    inner: CoreValue::Text(text),
263                    ..
264                }) = b
265                {
266                    a == &text.0
267                } else {
268                    false
269                }
270            }
271        }
272    }
273}
274
275impl Display for BorrowedMapKey<'_> {
276    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
277        match self {
278            // TODO #331: escape string
279            BorrowedMapKey::Text(string) => core::write!(f, "\"{}\"", string),
280            BorrowedMapKey::Value(value) => core::write!(f, "{value}"),
281        }
282    }
283}
284
285#[derive(Debug)]
286pub enum MapKey {
287    Text(String),
288    Value(ValueContainer),
289}
290
291impl From<MapKey> for ValueContainer {
292    fn from(key: MapKey) -> Self {
293        match key {
294            MapKey::Text(text) => ValueContainer::Value(Value::from(text)),
295            MapKey::Value(value) => value,
296        }
297    }
298}
299
300impl<'a> From<&'a MapKey> for ValueKey<'a> {
301    fn from(key: &'a MapKey) -> Self {
302        match key {
303            MapKey::Text(text) => ValueKey::Text(Cow::Borrowed(text)),
304            MapKey::Value(value) => ValueKey::Value(Cow::Borrowed(value)),
305        }
306    }
307}
308
309impl Display for MapKey {
310    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
311        match self {
312            MapKey::Text(text) => core::write!(f, "{text}"),
313            MapKey::Value(value) => core::write!(f, "{value}"),
314        }
315    }
316}
317
318pub struct MapIterator<'a> {
319    map: &'a Map,
320    index: usize,
321}
322
323impl<'a> Iterator for MapIterator<'a> {
324    type Item = (BorrowedMapKey<'a>, &'a ValueContainer);
325
326    fn next(&mut self) -> Option<Self::Item> {
327        match self.map {
328            Map::Dynamic(map) => {
329                let item = map.iter().nth(self.index);
330                self.index += 1;
331                item.map(|(k, v)| {
332                    let key = match k {
333                        ValueContainer::Value(Value {
334                            inner: CoreValue::Text(text),
335                            ..
336                        }) => BorrowedMapKey::Text(&text.0),
337                        _ => BorrowedMapKey::Value(k),
338                    };
339                    (key, v)
340                })
341            }
342            Map::Structural(vec) => {
343                if self.index < vec.len() {
344                    let item = &vec[self.index];
345                    self.index += 1;
346                    let key = match &item.0 {
347                        ValueContainer::Value(Value {
348                            inner: CoreValue::Text(text),
349                            ..
350                        }) => BorrowedMapKey::Text(&text.0),
351                        _ => BorrowedMapKey::Value(&item.0),
352                    };
353                    Some((key, &item.1))
354                } else {
355                    None
356                }
357            }
358            Map::StructuralWithStringKeys(vec) => {
359                if self.index < vec.len() {
360                    let item = &vec[self.index];
361                    self.index += 1;
362                    Some((BorrowedMapKey::Text(&item.0), &item.1))
363                } else {
364                    None
365                }
366            }
367        }
368    }
369}
370
371pub enum MapMutIterator<'a> {
372    Dynamic(indexmap::map::IterMut<'a, ValueContainer, ValueContainer>),
373    Fixed(core::slice::IterMut<'a, (ValueContainer, ValueContainer)>),
374    Structural(core::slice::IterMut<'a, (String, ValueContainer)>),
375}
376
377impl<'a> Iterator for MapMutIterator<'a> {
378    type Item = (BorrowedMapKey<'a>, &'a mut ValueContainer);
379
380    fn next(&mut self) -> Option<Self::Item> {
381        match self {
382            MapMutIterator::Dynamic(iter) => iter.next().map(|(k, v)| {
383                let key = match k {
384                    ValueContainer::Value(Value {
385                        inner: CoreValue::Text(text),
386                        ..
387                    }) => BorrowedMapKey::Text(&text.0),
388                    _ => BorrowedMapKey::Value(k),
389                };
390                (key, v)
391            }),
392            MapMutIterator::Fixed(iter) => iter.next().map(|(k, v)| {
393                let key = match k {
394                    ValueContainer::Value(Value {
395                        inner: CoreValue::Text(text),
396                        ..
397                    }) => BorrowedMapKey::Text(&text.0),
398                    _ => BorrowedMapKey::Value(k),
399                };
400                (key, v)
401            }),
402            MapMutIterator::Structural(iter) => iter
403                .next()
404                .map(|(k, v)| (BorrowedMapKey::Text(k.as_str()), v)),
405        }
406    }
407}
408
409pub struct IntoMapIterator {
410    map: Map,
411    index: usize,
412}
413
414impl Iterator for IntoMapIterator {
415    type Item = (MapKey, ValueContainer);
416
417    fn next(&mut self) -> Option<Self::Item> {
418        // TODO #332: optimize to avoid cloning keys and values
419        match &self.map {
420            Map::Dynamic(map) => {
421                let item = map.iter().nth(self.index);
422                self.index += 1;
423                item.map(|(k, v)| {
424                    let key = match k {
425                        ValueContainer::Value(Value {
426                            inner: CoreValue::Text(text),
427                            ..
428                        }) => MapKey::Text(text.0.clone()),
429                        _ => MapKey::Value(k.clone()),
430                    };
431                    (key, v.clone())
432                })
433            }
434            Map::Structural(vec) => {
435                if self.index < vec.len() {
436                    let item = &vec[self.index];
437                    self.index += 1;
438                    let key = match &item.0 {
439                        ValueContainer::Value(Value {
440                            inner: CoreValue::Text(text),
441                            ..
442                        }) => MapKey::Text(text.0.clone()),
443                        _ => MapKey::Value(item.0.clone()),
444                    };
445                    Some((key, item.1.clone()))
446                } else {
447                    None
448                }
449            }
450            Map::StructuralWithStringKeys(vec) => {
451                if self.index < vec.len() {
452                    let item = &vec[self.index];
453                    self.index += 1;
454                    Some((MapKey::Text(item.0.clone()), item.1.clone()))
455                } else {
456                    None
457                }
458            }
459        }
460    }
461}
462
463impl StructuralEq for Map {
464    fn structural_eq(&self, other: &Self) -> bool {
465        if self.size() != other.size() {
466            return false;
467        }
468        for ((key, value), (other_key, other_value)) in
469            self.iter().zip(other.iter())
470        {
471            if !key.structural_eq(&other_key)
472                || !value.structural_eq(other_value)
473            {
474                return false;
475            }
476        }
477        true
478    }
479}
480
481impl Hash for Map {
482    fn hash<H: Hasher>(&self, state: &mut H) {
483        for (k, v) in self.iter() {
484            k.hash(state);
485            v.hash(state);
486        }
487    }
488}
489
490impl Display for Map {
491    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
492        core::write!(f, "{{")?;
493        for (i, (key, value)) in self.iter().enumerate() {
494            if i > 0 {
495                core::write!(f, ", ")?;
496            }
497            core::write!(f, "{key}: {value}")?;
498        }
499        core::write!(f, "}}")
500    }
501}
502
503impl<K, V> From<HashMap<K, V>> for Map
504where
505    K: Into<ValueContainer>,
506    V: Into<ValueContainer>,
507{
508    fn from(map: HashMap<K, V>) -> Self {
509        Map::new(map.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
510    }
511}
512
513impl IntoIterator for Map {
514    type Item = (MapKey, ValueContainer);
515    type IntoIter = IntoMapIterator;
516
517    fn into_iter(self) -> Self::IntoIter {
518        IntoMapIterator {
519            map: self,
520            index: 0,
521        }
522    }
523}
524
525impl<'a> IntoIterator for &'a mut Map {
526    type Item = (BorrowedMapKey<'a>, &'a mut ValueContainer);
527    type IntoIter = MapMutIterator<'a>;
528
529    fn into_iter(self) -> Self::IntoIter {
530        match self {
531            Map::Dynamic(map) => MapMutIterator::Dynamic(map.iter_mut()),
532            Map::Structural(vec) => MapMutIterator::Fixed(vec.iter_mut()),
533            Map::StructuralWithStringKeys(vec) => {
534                MapMutIterator::Structural(vec.iter_mut())
535            }
536        }
537    }
538}
539
540impl From<Vec<(ValueContainer, ValueContainer)>> for Map {
541    /// Create a dynamic map from a vector of value containers.
542    fn from(vec: Vec<(ValueContainer, ValueContainer)>) -> Self {
543        Map::new(vec.into_iter().collect())
544    }
545}
546
547impl From<Vec<(String, ValueContainer)>> for Map {
548    /// Create a dynamic map from a vector of string keys and value containers.
549    fn from(vec: Vec<(String, ValueContainer)>) -> Self {
550        Map::new(
551            vec.into_iter()
552                .map(|(k, v)| (k.into(), v))
553                .collect::<IndexMap<ValueContainer, ValueContainer, RandomState>>(),
554        )
555    }
556}
557
558impl From<Vec<(MapKey, ValueContainer)>> for Map {
559    fn from(vec: Vec<(MapKey, ValueContainer)>) -> Self {
560        let has_only_text_keys = vec.iter().all(|(k, _)| {
561            matches!(k, MapKey::Text(_))
562                || matches!(
563                    k,
564                    MapKey::Value(ValueContainer::Value(Value {
565                        inner: CoreValue::Text(_),
566                        ..
567                    }))
568                )
569        });
570        if has_only_text_keys {
571            let mut entries: Vec<(String, ValueContainer)> =
572                Vec::with_capacity(vec.len());
573            for (k, v) in vec {
574                match k {
575                    MapKey::Text(text) => {
576                        entries.push((text, v));
577                    }
578                    MapKey::Value(value) => {
579                        if let ValueContainer::Value(Value {
580                            inner: CoreValue::Text(text),
581                            ..
582                        }) = value
583                        {
584                            entries.push((text.0, v));
585                        } else {
586                            unreachable!(); // already checked above
587                        }
588                    }
589                }
590            }
591            Map::StructuralWithStringKeys(entries)
592        } else {
593            let mut map = Map::default();
594            for (k, v) in vec {
595                map.set(&k, v);
596            }
597            map
598        }
599    }
600}
601
602impl<K, V> FromIterator<(K, V)> for Map
603where
604    K: Into<ValueContainer>,
605    V: Into<ValueContainer>,
606{
607    fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
608        Map::Dynamic(
609            iter.into_iter()
610                .map(|(k, v)| (k.into(), v.into()))
611                .collect(),
612        )
613    }
614}
615
616impl<K, V> From<IndexMap<K, V, RandomState>> for Map
617where
618    K: Into<ValueContainer>,
619    V: Into<ValueContainer>,
620{
621    fn from(map: IndexMap<K, V, RandomState>) -> Self {
622        Map::new(
623            map.into_iter()
624                .map(|(k, v)| (k.into(), v.into()))
625                .collect::<IndexMap<ValueContainer, ValueContainer, RandomState>>(),
626        )
627    }
628}
629
630impl TryFrom<CoreValue> for Map {
631    type Error = String;
632
633    fn try_from(value: CoreValue) -> Result<Self, Self::Error> {
634        if let CoreValue::Map(map) = value {
635            Ok(map)
636        } else {
637            Err(format!("Expected CoreValue::Map, found {value:?}"))
638        }
639    }
640}
641
642#[cfg(test)]
643mod tests {
644    use crate::{
645        prelude::*,
646        values::{
647            core_values::{
648                decimal::{Decimal, typed_decimal::TypedDecimal},
649                map::Map,
650            },
651            value_container::ValueContainer,
652        },
653    };
654
655    #[test]
656    fn test_map() {
657        let mut map = Map::default();
658        map.set("key1", 42);
659        map.set("key2", "value2");
660        assert_eq!(map.size(), 2);
661        assert_eq!(map.get("key1").unwrap().to_string(), "42");
662        assert_eq!(map.get("key2").unwrap().to_string(), "\"value2\"");
663        assert_eq!(map.to_string(), r#"{"key1": 42, "key2": "value2"}"#);
664    }
665
666    #[test]
667    fn test_duplicate_keys() {
668        let mut map = Map::default();
669        map.set("key1", 42);
670        map.set("key1", "new_value");
671        assert_eq!(map.size(), 1);
672        assert_eq!(map.get("key1").unwrap().to_string(), "\"new_value\"");
673    }
674
675    #[test]
676    fn test_ref_keys() {
677        let mut map = Map::default();
678        let key = ValueContainer::new_reference(ValueContainer::from(42));
679        map.set(&key, "value");
680        // same reference should be found
681        assert_eq!(map.size(), 1);
682        assert!(map.has(&key));
683        assert_eq!(map.get(&key).unwrap().to_string(), "\"value\"");
684
685        // new reference with same value should not be found
686        let new_key = ValueContainer::new_reference(ValueContainer::from(42));
687        assert!(!map.has(&new_key));
688        assert!(map.get(&new_key).is_err());
689    }
690
691    #[test]
692    fn test_decimal_nan_value_key() {
693        let mut map = Map::default();
694        let nan_value = ValueContainer::from(Decimal::Nan);
695        map.set(&nan_value, "value");
696        // same NaN value should be found
697        assert_eq!(map.size(), 1);
698        assert!(map.has(&nan_value));
699
700        // new NaN value should also be found
701        let new_nan_value = ValueContainer::from(Decimal::Nan);
702        assert!(map.has(&new_nan_value));
703
704        // adding new_nan_value should not increase size
705        map.set(&new_nan_value, "new_value");
706        assert_eq!(map.size(), 1);
707    }
708
709    #[test]
710    fn test_float_nan_value_key() {
711        let mut map = Map::default();
712        let nan_value = ValueContainer::from(f64::NAN);
713        map.set(&nan_value, "value");
714        // same NaN value should be found
715        assert_eq!(map.size(), 1);
716        assert!(map.has(&nan_value));
717
718        // new f64 NaN value should also be found
719        let new_nan_value = ValueContainer::from(f64::NAN);
720        assert!(map.has(&new_nan_value));
721
722        // new f32 NaN should not be found
723        let float32_nan_value = ValueContainer::from(f32::NAN);
724        assert!(!map.has(&float32_nan_value));
725
726        // adding new_nan_value should not increase size
727        map.set(&new_nan_value, "new_value");
728        assert_eq!(map.size(), 1);
729    }
730
731    #[test]
732    fn test_decimal_zero_value_key() {
733        let mut map = Map::default();
734        let zero_value = ValueContainer::from(Decimal::Zero);
735        map.set(&zero_value, "value");
736        // same Zero value should be found
737        assert_eq!(map.size(), 1);
738        assert!(map.has(&zero_value));
739
740        // new Zero value should also be found
741        let new_zero_value = ValueContainer::from(Decimal::Zero);
742        assert!(map.has(&new_zero_value));
743
744        // new NegZero value should also be found
745        let neg_zero_value = ValueContainer::from(Decimal::NegZero);
746        assert!(map.has(&neg_zero_value));
747
748        // adding neg_zero_value should not increase size
749        map.set(&neg_zero_value, "new_value");
750        assert_eq!(map.size(), 1);
751    }
752
753    #[test]
754    fn test_float_zero_value_key() {
755        let mut map = Map::default();
756        let zero_value = ValueContainer::from(0.0f64);
757        map.set(&zero_value, "value");
758        // same 0.0 value should be found
759        assert_eq!(map.size(), 1);
760        assert!(map.has(&zero_value));
761        // new 0.0 value should also be found
762        let new_zero_value = ValueContainer::from(0.0f64);
763        assert!(map.has(&new_zero_value));
764        // new -0.0 value should also be found
765        let neg_zero_value = ValueContainer::from(-0.0f64);
766        assert!(map.has(&neg_zero_value));
767
768        // adding neg_zero_value should not increase size
769        map.set(&neg_zero_value, "new_value");
770        assert_eq!(map.size(), 1);
771
772        // new 0.0f32 value should not be found
773        let float32_zero_value = ValueContainer::from(0.0f32);
774        assert!(!map.has(&float32_zero_value));
775    }
776
777    #[test]
778    fn test_typed_big_decimal_key() {
779        let mut map = Map::default();
780        let zero_big_decimal =
781            ValueContainer::from(TypedDecimal::Decimal(Decimal::Zero));
782        map.set(&zero_big_decimal, "value");
783        // same Zero value should be found
784        assert_eq!(map.size(), 1);
785        assert!(map.has(&zero_big_decimal));
786        // new Zero value should also be found
787        let new_zero_big_decimal =
788            ValueContainer::from(TypedDecimal::Decimal(Decimal::Zero));
789        assert!(map.has(&new_zero_big_decimal));
790        // new NegZero value should also be found
791        let neg_zero_big_decimal =
792            ValueContainer::from(TypedDecimal::Decimal(Decimal::NegZero));
793        assert!(map.has(&neg_zero_big_decimal));
794
795        // adding neg_zero_big_decimal should not increase size
796        map.set(&neg_zero_big_decimal, "new_value");
797        assert_eq!(map.size(), 1);
798    }
799}