1use core::slice::Iter;
2use std::borrow::Cow;
3
4use crate::map::IntoIter as MapIntoIter;
5use crate::map::Map;
6
7#[derive(Clone, PartialEq, Debug)]
9pub enum JsonValue<'a> {
10 String(Cow<'a, str>),
11 Number(&'a str),
12 Boolean(bool),
13 Object(JsonObject<'a>),
14 Array(JsonArray<'a>),
15 Null,
16}
17
18#[derive(Clone, PartialEq, Debug)]
20pub struct JsonObject<'a>(Map<Cow<'a, str>, JsonValue<'a>>);
21
22impl<'a> IntoIterator for JsonObject<'a> {
23 type Item = (Cow<'a, str>, JsonValue<'a>);
24 type IntoIter = MapIntoIter<Cow<'a, str>, JsonValue<'a>>;
25
26 fn into_iter(self) -> Self::IntoIter {
27 self.0.into_iter()
28 }
29}
30
31impl<'a> From<Map<Cow<'a, str>, JsonValue<'a>>> for JsonObject<'a> {
32 fn from(properties: Map<Cow<'a, str>, JsonValue<'a>>) -> JsonObject<'a> {
33 JsonObject::new(properties)
34 }
35}
36
37macro_rules! generate_take {
38 ($self:ident, $name:ident, $value_type:ident) => {
39 match $self.0.remove_entry($name) {
40 Some((_, JsonValue::$value_type(value))) => Some(value),
41 Some((key, value)) => {
42 $self.0.insert(key, value);
44 None
45 }
46 _ => None,
47 }
48 };
49}
50
51macro_rules! generate_get {
52 ($self:ident, $name:ident, $value_type:ident) => {
53 match $self.0.get($name) {
54 Some(JsonValue::$value_type(value)) => Some(value),
55 _ => None,
56 }
57 };
58}
59
60impl<'a> JsonObject<'a> {
61 pub fn new(inner: Map<Cow<'a, str>, JsonValue<'a>>) -> JsonObject<'a> {
63 JsonObject(inner)
64 }
65
66 pub fn with_capacity(capacity: usize) -> JsonObject<'a> {
68 JsonObject(Map::with_capacity(capacity))
69 }
70
71 pub fn take_inner(self) -> Map<Cow<'a, str>, JsonValue<'a>> {
73 self.0
74 }
75
76 pub fn len(&self) -> usize {
78 self.0.len()
79 }
80
81 pub fn is_empty(&self) -> bool {
83 self.0.is_empty()
84 }
85
86 pub fn get(&self, name: &str) -> Option<&JsonValue<'a>> {
88 self.0.get(name)
89 }
90
91 pub fn get_string(&self, name: &str) -> Option<&Cow<'a, str>> {
94 generate_get!(self, name, String)
95 }
96
97 pub fn get_number(&self, name: &str) -> Option<&'a str> {
100 generate_get!(self, name, Number)
101 }
102
103 pub fn get_boolean(&self, name: &str) -> Option<bool> {
106 let result = generate_get!(self, name, Boolean);
107 result.cloned()
108 }
109
110 pub fn get_object(&self, name: &str) -> Option<&JsonObject<'a>> {
113 generate_get!(self, name, Object)
114 }
115
116 pub fn get_array(&self, name: &str) -> Option<&JsonArray<'a>> {
119 generate_get!(self, name, Array)
120 }
121
122 pub fn take(&mut self, name: &str) -> Option<JsonValue<'a>> {
125 self.0.remove_entry(name).map(|(_, value)| value)
126 }
127
128 pub fn take_string(&mut self, name: &str) -> Option<Cow<'a, str>> {
131 generate_take!(self, name, String)
132 }
133
134 pub fn take_number(&mut self, name: &str) -> Option<&'a str> {
137 generate_take!(self, name, Number)
138 }
139
140 pub fn take_boolean(&mut self, name: &str) -> Option<bool> {
143 generate_take!(self, name, Boolean)
144 }
145
146 pub fn take_object(&mut self, name: &str) -> Option<JsonObject<'a>> {
149 generate_take!(self, name, Object)
150 }
151
152 pub fn take_array(&mut self, name: &str) -> Option<JsonArray<'a>> {
155 generate_take!(self, name, Array)
156 }
157}
158
159#[derive(Clone, PartialEq, Debug)]
161pub struct JsonArray<'a>(Vec<JsonValue<'a>>);
162
163impl<'a> IntoIterator for JsonArray<'a> {
164 type Item = JsonValue<'a>;
165 type IntoIter = std::vec::IntoIter<Self::Item>;
166
167 fn into_iter(self) -> Self::IntoIter {
168 self.0.into_iter()
169 }
170}
171
172impl<'a> From<Vec<JsonValue<'a>>> for JsonArray<'a> {
173 fn from(elements: Vec<JsonValue<'a>>) -> JsonArray<'a> {
174 JsonArray::new(elements)
175 }
176}
177
178impl<'a> JsonArray<'a> {
179 pub fn new(inner: Vec<JsonValue<'a>>) -> JsonArray<'a> {
181 JsonArray(inner)
182 }
183
184 pub fn take_inner(self) -> Vec<JsonValue<'a>> {
186 self.0
187 }
188
189 pub fn iter(&self) -> Iter<'_, JsonValue<'a>> {
191 self.0.iter()
192 }
193
194 pub fn get(&self, index: usize) -> Option<&JsonValue<'a>> {
196 self.0.get(index)
197 }
198
199 pub fn len(&self) -> usize {
201 self.0.len()
202 }
203
204 pub fn is_empty(&self) -> bool {
206 self.0.is_empty()
207 }
208}
209
210#[cfg(test)]
211mod test {
212 use super::*;
213
214 #[test]
215 fn it_should_take() {
216 let mut inner = Map::default();
217 inner.insert(Cow::Borrowed("prop"), JsonValue::String(Cow::Borrowed("asdf")));
218 inner.insert(Cow::Borrowed("other"), JsonValue::String(Cow::Borrowed("text")));
219 let mut obj = JsonObject::new(inner);
220
221 assert_eq!(obj.len(), 2);
222 assert_eq!(obj.take_string("asdf"), None);
223 assert_eq!(obj.len(), 2);
224 assert_eq!(obj.take_number("prop"), None);
225 assert_eq!(obj.len(), 2);
226 assert_eq!(obj.take_string("prop"), Some(Cow::Borrowed("asdf")));
227 assert_eq!(obj.len(), 1);
228 assert_eq!(obj.take("something"), None);
229 assert_eq!(obj.len(), 1);
230 assert_eq!(obj.take("other"), Some(JsonValue::String(Cow::Borrowed("text"))));
231 assert_eq!(obj.len(), 0);
232 }
233
234 #[test]
235 fn it_should_get() {
236 let mut inner = Map::default();
237 inner.insert(Cow::Borrowed("prop"), JsonValue::String(Cow::Borrowed("asdf")));
238 let obj = JsonObject::new(inner);
239
240 assert_eq!(obj.len(), 1);
241 assert_eq!(obj.get_string("asdf"), None);
242 assert_eq!(obj.get_string("prop"), Some(&Cow::Borrowed("asdf")));
243 assert_eq!(obj.get("prop"), Some(&JsonValue::String(Cow::Borrowed("asdf"))));
244 assert_eq!(obj.get("asdf"), None);
245 assert_eq!(obj.len(), 1);
246 }
247}