1use core::{borrow, fmt};
2use std::{
3 collections::HashMap,
4 hash::{self, BuildHasherDefault},
5 rc::Rc,
6};
7
8use super::{FromValue, Named, ToValue};
9use crate::Value;
10
11pub type Keys<'a> = std::collections::hash_map::Keys<'a, String, Value>;
12
13pub type Values<'a> = std::collections::hash_map::Values<'a, String, Value>;
14
15#[derive(Default, Clone)]
35pub struct Map {
36 inner: Rc<HashMap<String, Value, BuildHasherDefault<ahash::AHasher>>>,
37}
38
39impl Map {
40 pub fn new() -> Self {
42 Self {
43 inner: Rc::new(HashMap::default()),
44 }
45 }
46
47 pub fn with_capacity(cap: usize) -> Self {
49 Self {
50 inner: Rc::new(HashMap::with_capacity_and_hasher(
51 cap,
52 BuildHasherDefault::default(),
53 )),
54 }
55 }
56
57 pub fn make_mut(&mut self) -> &mut HashMap<String, Value, BuildHasherDefault<ahash::AHasher>> {
58 Rc::make_mut(&mut self.inner)
59 }
60
61 pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&Value>
63 where
64 String: borrow::Borrow<Q>,
65 Q: hash::Hash + std::cmp::Eq + std::cmp::Ord,
66 {
67 self.inner.get(k)
68 }
69
70 pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut Value>
72 where
73 String: borrow::Borrow<Q>,
74 Q: hash::Hash + std::cmp::Eq + std::cmp::Ord,
75 {
76 self.make_mut().get_mut(k)
77 }
78
79 pub fn get_value<Q: ?Sized, T>(&self, k: &Q) -> Option<T>
82 where
83 String: borrow::Borrow<Q>,
84 Q: hash::Hash + std::cmp::Eq + std::cmp::Ord,
85 T: FromValue,
86 {
87 let v = match self.inner.get(k) {
88 Some(v) => v.clone(),
89 None => return None,
90 };
91
92 Some(T::from_value(v).unwrap())
93 }
94
95 pub fn insert(&mut self, k: String, v: Value) {
97 self.make_mut().insert(k, v);
98 }
99
100 pub fn insert_value<V>(&mut self, k: String, v: V)
103 where
104 V: ToValue,
105 {
106 self.make_mut().insert(k, v.to_value());
107 }
108
109 pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<Value>
111 where
112 String: borrow::Borrow<Q>,
113 Q: hash::Hash + std::cmp::Eq + std::cmp::Ord,
114 {
115 self.make_mut().remove(k)
116 }
117
118 pub fn len(&self) -> usize {
120 self.inner.len()
121 }
122
123 pub fn is_empty(&self) -> bool {
125 self.inner.is_empty()
126 }
127
128 pub fn keys(&self) -> Keys<'_> {
130 self.inner.keys()
131 }
132
133 pub fn values(&self) -> Values<'_> {
135 self.inner.values()
136 }
137
138 pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
139 where
140 String: borrow::Borrow<Q>,
141 Q: hash::Hash + std::cmp::Eq + std::cmp::Ord,
142 {
143 self.inner.contains_key(k)
144 }
145}
146
147impl FromValue for Map {
148 fn from_value(value: Value) -> Result<Self, String> {
149 match value {
150 Value::Map(map) => Ok(map),
151 _ => {
152 Err("cannot coerce map from value".into())
153 }
154 }
155 }
156}
157
158impl ToValue for Map {
159 fn to_value(self) -> Value {
160 Value::Map(self)
161 }
162}
163
164impl fmt::Debug for Map {
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 f.debug_map().entries(self.inner.iter()).finish()
167 }
168}
169
170impl fmt::Display for Map {
171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 f.write_str("{")?;
173
174 for (pos, (key, value)) in self.inner.iter().enumerate() {
175 f.write_fmt(format_args!("{key}: {value}"))?;
176
177 if pos != self.inner.len() {
178 f.write_str(", ")?;
179 }
180 }
181 f.write_str("}")
182 }
183}
184
185impl PartialEq for Map {
186 fn eq(&self, other: &Self) -> bool {
187 self.len() == other.len() && self.inner == other.inner
188 }
189}
190
191impl PartialOrd for Map {
192 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
193 self.values().partial_cmp(other.values())
194 }
195}
196
197impl Named for Map {
198 const NAME: &'static str = "Map";
199}