1use core::slice::Iter;
2use std::borrow::Cow;
3
4#[derive(Clone, PartialEq, Debug)]
6pub enum JsonValue<'a> {
7 String(Cow<'a, str>),
8 Number(&'a str),
9 Boolean(bool),
10 Object(JsonObject<'a>),
11 Array(JsonArray<'a>),
12 Null,
13}
14
15#[cfg(not(feature = "preserve_order"))]
16pub type Map<K, V> = std::collections::HashMap<K, V>;
17#[cfg(feature = "preserve_order")]
18pub type Map<K, V> = indexmap::IndexMap<K, V>;
19
20#[derive(Clone, PartialEq, Debug)]
22pub struct JsonObject<'a>(Map<String, JsonValue<'a>>);
23
24impl<'a> IntoIterator for JsonObject<'a> {
25 type Item = (String, JsonValue<'a>);
26 #[cfg(not(feature = "preserve_order"))]
27 type IntoIter = std::collections::hash_map::IntoIter<String, JsonValue<'a>>;
28 #[cfg(feature = "preserve_order")]
29 type IntoIter = indexmap::map::IntoIter<String, JsonValue<'a>>;
30
31 fn into_iter(self) -> Self::IntoIter {
32 self.0.into_iter()
33 }
34}
35
36impl<'a> From<Map<String, JsonValue<'a>>> for JsonObject<'a> {
37 fn from(properties: Map<String, JsonValue>) -> JsonObject {
38 JsonObject::new(properties)
39 }
40}
41
42#[cfg(not(feature = "preserve_order"))]
43#[inline(always)]
44fn remove_entry<'a>(map: &mut Map<String, JsonValue<'a>>, key: &str) -> Option<(String, JsonValue<'a>)> {
45 map.remove_entry(key)
46}
47
48#[cfg(feature = "preserve_order")]
49#[inline(always)]
50fn remove_entry<'a>(map: &mut Map<String, JsonValue<'a>>, key: &str) -> Option<(String, JsonValue<'a>)> {
51 map.shift_remove_entry(key)
52}
53
54macro_rules! generate_take {
55 ($self:ident, $name:ident, $value_type:ident) => {
56 match remove_entry(&mut $self.0, $name) {
57 Some((_, JsonValue::$value_type(value))) => Some(value),
58 Some((key, value)) => {
59 $self.0.insert(key, value);
61 None
62 }
63 _ => None,
64 }
65 };
66}
67
68macro_rules! generate_get {
69 ($self:ident, $name:ident, $value_type:ident) => {
70 match $self.0.get($name) {
71 Some(JsonValue::$value_type(value)) => Some(value),
72 _ => None,
73 }
74 };
75}
76
77impl<'a> JsonObject<'a> {
78 pub fn new(inner: Map<String, JsonValue<'a>>) -> JsonObject<'a> {
80 JsonObject(inner)
81 }
82
83 pub fn with_capacity(capacity: usize) -> JsonObject<'a> {
85 JsonObject(Map::with_capacity(capacity))
86 }
87
88 pub fn take_inner(self) -> Map<String, JsonValue<'a>> {
90 self.0
91 }
92
93 pub fn len(&self) -> usize {
95 self.0.len()
96 }
97
98 pub fn is_empty(&self) -> bool {
100 self.0.is_empty()
101 }
102
103 pub fn get(&self, name: &str) -> Option<&JsonValue<'a>> {
105 self.0.get(name)
106 }
107
108 pub fn get_string(&self, name: &str) -> Option<&Cow<'a, str>> {
111 generate_get!(self, name, String)
112 }
113
114 pub fn get_number(&self, name: &str) -> Option<&'a str> {
117 generate_get!(self, name, Number)
118 }
119
120 pub fn get_boolean(&self, name: &str) -> Option<bool> {
123 let result = generate_get!(self, name, Boolean);
124 result.cloned()
125 }
126
127 pub fn get_object(&self, name: &str) -> Option<&JsonObject<'a>> {
130 generate_get!(self, name, Object)
131 }
132
133 pub fn get_array(&self, name: &str) -> Option<&JsonArray<'a>> {
136 generate_get!(self, name, Array)
137 }
138
139 pub fn take(&mut self, name: &str) -> Option<JsonValue<'a>> {
142 remove_entry(&mut self.0, name).map(|(_, value)| value)
143 }
144
145 pub fn take_string(&mut self, name: &str) -> Option<Cow<'a, str>> {
148 generate_take!(self, name, String)
149 }
150
151 pub fn take_number(&mut self, name: &str) -> Option<&'a str> {
154 generate_take!(self, name, Number)
155 }
156
157 pub fn take_boolean(&mut self, name: &str) -> Option<bool> {
160 generate_take!(self, name, Boolean)
161 }
162
163 pub fn take_object(&mut self, name: &str) -> Option<JsonObject<'a>> {
166 generate_take!(self, name, Object)
167 }
168
169 pub fn take_array(&mut self, name: &str) -> Option<JsonArray<'a>> {
172 generate_take!(self, name, Array)
173 }
174}
175
176#[derive(Clone, PartialEq, Debug)]
178pub struct JsonArray<'a>(Vec<JsonValue<'a>>);
179
180impl<'a> IntoIterator for JsonArray<'a> {
181 type Item = JsonValue<'a>;
182 type IntoIter = std::vec::IntoIter<Self::Item>;
183
184 fn into_iter(self) -> Self::IntoIter {
185 self.0.into_iter()
186 }
187}
188
189impl<'a> From<Vec<JsonValue<'a>>> for JsonArray<'a> {
190 fn from(elements: Vec<JsonValue<'a>>) -> JsonArray<'a> {
191 JsonArray::new(elements)
192 }
193}
194
195impl<'a> JsonArray<'a> {
196 pub fn new(inner: Vec<JsonValue<'a>>) -> JsonArray<'a> {
198 JsonArray(inner)
199 }
200
201 pub fn take_inner(self) -> Vec<JsonValue<'a>> {
203 self.0
204 }
205
206 pub fn iter(&self) -> Iter<JsonValue<'a>> {
208 self.0.iter()
209 }
210
211 pub fn get(&self, index: usize) -> Option<&JsonValue<'a>> {
213 self.0.get(index)
214 }
215
216 pub fn len(&self) -> usize {
218 self.0.len()
219 }
220
221 pub fn is_empty(&self) -> bool {
223 self.0.is_empty()
224 }
225}
226
227#[cfg(test)]
228mod test {
229 use super::*;
230
231 #[test]
232 fn it_should_take() {
233 let mut inner = Map::new();
234 inner.insert(String::from("prop"), JsonValue::String(Cow::Borrowed("asdf")));
235 inner.insert(String::from("other"), JsonValue::String(Cow::Borrowed("text")));
236 let mut obj = JsonObject::new(inner);
237
238 assert_eq!(obj.len(), 2);
239 assert_eq!(obj.take_string("asdf"), None);
240 assert_eq!(obj.len(), 2);
241 assert_eq!(obj.take_number("prop"), None);
242 assert_eq!(obj.len(), 2);
243 assert_eq!(obj.take_string("prop"), Some(Cow::Borrowed("asdf")));
244 assert_eq!(obj.len(), 1);
245 assert_eq!(obj.take("something"), None);
246 assert_eq!(obj.len(), 1);
247 assert_eq!(obj.take("other"), Some(JsonValue::String(Cow::Borrowed("text"))));
248 assert_eq!(obj.len(), 0);
249 }
250
251 #[test]
252 fn it_should_get() {
253 let mut inner = Map::new();
254 inner.insert(String::from("prop"), JsonValue::String(Cow::Borrowed("asdf")));
255 let obj = JsonObject::new(inner);
256
257 assert_eq!(obj.len(), 1);
258 assert_eq!(obj.get_string("asdf"), None);
259 assert_eq!(obj.get_string("prop"), Some(&Cow::Borrowed("asdf")));
260 assert_eq!(obj.get("prop"), Some(&JsonValue::String(Cow::Borrowed("asdf"))));
261 assert_eq!(obj.get("asdf"), None);
262 assert_eq!(obj.len(), 1);
263 }
264}