datex_core/values/core_values/
object.rs1use super::super::core_value_trait::CoreValueTrait;
2use crate::values::traits::structural_eq::StructuralEq;
3use crate::values::value_container::ValueContainer;
4use indexmap::IndexMap;
5use indexmap::map::{IntoIter, Iter};
6use std::collections::HashMap;
7use std::fmt;
8use std::hash::{Hash, Hasher};
9use std::iter::zip;
10
11#[derive(Clone, Debug, Default, Eq, PartialEq)]
12pub struct Object(pub IndexMap<String, ValueContainer>);
13impl Object {
14 pub fn new() -> Self {
15 Object(IndexMap::new())
16 }
17 pub fn size(&self) -> usize {
18 self.0.len()
19 }
20 pub fn get(&self, key: &str) -> &ValueContainer {
21 self.try_get(key)
22 .unwrap_or_else(|| panic!("Key '{key}' not found in Object"))
23 }
24 pub fn try_get(&self, key: &str) -> Option<&ValueContainer> {
25 self.0.get(key)
26 }
27 pub fn get_or_insert_with<F>(
28 &mut self,
29 key: &str,
30 default: F,
31 ) -> &mut ValueContainer
32 where
33 F: FnOnce() -> ValueContainer,
34 {
35 self.0.entry(key.to_string()).or_insert_with(default)
36 }
37 pub fn get_mut(&mut self, key: &str) -> Option<&mut ValueContainer> {
38 self.0.get_mut(key)
39 }
40 pub fn contains_key(&self, key: &str) -> bool {
41 self.0.contains_key(key)
42 }
43 pub fn keys(&self) -> impl Iterator<Item = &String> {
44 self.0.keys()
45 }
46 pub fn values(&self) -> impl Iterator<Item = &ValueContainer> {
47 self.0.values()
48 }
49 pub fn iter(&self) -> impl Iterator<Item = (&String, &ValueContainer)> {
50 self.0.iter()
51 }
52 pub fn iter_mut(
53 &mut self,
54 ) -> impl Iterator<Item = (&String, &mut ValueContainer)> {
55 self.0.iter_mut()
56 }
57 pub fn clear(&mut self) {
58 self.0.clear();
59 }
60 pub fn is_empty(&self) -> bool {
61 self.0.is_empty()
62 }
63
64 pub fn set<T: Into<ValueContainer>>(&mut self, key: &str, value: T) {
65 self.0.insert(key.to_string(), value.into());
66 }
67
68 pub fn remove(&mut self, key: &str) -> Option<ValueContainer> {
69 self.0.shift_remove(key)
70 }
71}
72
73impl StructuralEq for Object {
74 fn structural_eq(&self, other: &Self) -> bool {
75 if self.size() != other.size() {
76 return false;
77 }
78 for (key, value) in zip(self.0.iter(), other.0.iter()) {
80 if key.0 != value.0 || !key.1.structural_eq(value.1) {
81 return false;
82 }
83 }
84 true
85 }
86}
87
88impl Hash for Object {
89 fn hash<H: Hasher>(&self, state: &mut H) {
90 for (k, v) in &self.0 {
91 k.hash(state);
93 v.hash(state);
94 }
95 }
96}
97
98impl CoreValueTrait for Object {}
99
100impl fmt::Display for Object {
101 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
102 write!(f, "{{")?;
103 for (i, (key, value)) in self.0.iter().enumerate() {
104 if i > 0 {
105 write!(f, ", ")?;
106 }
107 write!(f, "\"{key}\": {value}")?;
108 }
109 write!(f, "}}")
110 }
111}
112
113impl<T> From<HashMap<String, T>> for Object
114where
115 T: Into<ValueContainer>,
116{
117 fn from(map: HashMap<String, T>) -> Self {
118 Object(map.into_iter().map(|(k, v)| (k, v.into())).collect())
119 }
120}
121
122impl<T> FromIterator<(String, T)> for Object
123where
124 T: Into<ValueContainer>,
125{
126 fn from_iter<I: IntoIterator<Item = (String, T)>>(iter: I) -> Self {
127 Object(iter.into_iter().map(|(k, v)| (k, v.into())).collect())
128 }
129}
130
131impl IntoIterator for Object {
132 type Item = (String, ValueContainer);
133 type IntoIter = IntoIter<String, ValueContainer>;
134
135 fn into_iter(self) -> Self::IntoIter {
136 self.0.into_iter()
137 }
138}
139
140impl<'a> IntoIterator for &'a Object {
141 type Item = (&'a String, &'a ValueContainer);
142 type IntoIter = Iter<'a, String, ValueContainer>;
143
144 fn into_iter(self) -> Self::IntoIter {
145 self.0.iter()
146 }
147}
148
149impl From<IndexMap<ValueContainer, ValueContainer>> for Object {
150 fn from(map: IndexMap<ValueContainer, ValueContainer>) -> Self {
151 Object(map.into_iter().map(|(k, v)| (k.to_string(), v)).collect())
152 }
153}