datex_core/values/core_values/
map.rs

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