Skip to main content

jsonc_parser/
value.rs

1use core::slice::Iter;
2use std::borrow::Cow;
3
4use crate::map::IntoIter as MapIntoIter;
5use crate::map::Map;
6
7/// A JSON value.
8#[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/// A JSON object.
19#[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        // add it back
43        $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  /// Creates a new JsonObject.
62  pub fn new(inner: Map<Cow<'a, str>, JsonValue<'a>>) -> JsonObject<'a> {
63    JsonObject(inner)
64  }
65
66  /// Creates a new JsonObject with the specified capacity.
67  pub fn with_capacity(capacity: usize) -> JsonObject<'a> {
68    JsonObject(Map::with_capacity(capacity))
69  }
70
71  /// Drops the object returning the inner map.
72  pub fn take_inner(self) -> Map<Cow<'a, str>, JsonValue<'a>> {
73    self.0
74  }
75
76  /// Gets the number of properties.
77  pub fn len(&self) -> usize {
78    self.0.len()
79  }
80
81  /// Gets if there are no properties.
82  pub fn is_empty(&self) -> bool {
83    self.0.is_empty()
84  }
85
86  /// Gets a value in the object by its name.
87  pub fn get(&self, name: &str) -> Option<&JsonValue<'a>> {
88    self.0.get(name)
89  }
90
91  /// Gets a string property value from the object by name.
92  /// Returns `None` when not a string or it doesn't exist.
93  pub fn get_string(&self, name: &str) -> Option<&Cow<'a, str>> {
94    generate_get!(self, name, String)
95  }
96
97  /// Gets a number property value from the object by name.
98  /// Returns `None` when not a number or it doesn't exist.
99  pub fn get_number(&self, name: &str) -> Option<&'a str> {
100    generate_get!(self, name, Number)
101  }
102
103  /// Gets a boolean property value from the object by name.
104  /// Returns `None` when not a boolean or it doesn't exist.
105  pub fn get_boolean(&self, name: &str) -> Option<bool> {
106    let result = generate_get!(self, name, Boolean);
107    result.cloned()
108  }
109
110  /// Gets an object property value from the object by name.
111  /// Returns `None` when not an object or it doesn't exist.
112  pub fn get_object(&self, name: &str) -> Option<&JsonObject<'a>> {
113    generate_get!(self, name, Object)
114  }
115
116  /// Gets an array property value from the object by name.
117  /// Returns `None` when not an array or it doesn't exist.
118  pub fn get_array(&self, name: &str) -> Option<&JsonArray<'a>> {
119    generate_get!(self, name, Array)
120  }
121
122  /// Takes a value from the object by name.
123  /// Returns `None` when it doesn't exist.
124  pub fn take(&mut self, name: &str) -> Option<JsonValue<'a>> {
125    self.0.remove_entry(name).map(|(_, value)| value)
126  }
127
128  /// Takes a string property value from the object by name.
129  /// Returns `None` when not a string or it doesn't exist.
130  pub fn take_string(&mut self, name: &str) -> Option<Cow<'a, str>> {
131    generate_take!(self, name, String)
132  }
133
134  /// Takes a number property value from the object by name.
135  /// Returns `None` when not a number or it doesn't exist.
136  pub fn take_number(&mut self, name: &str) -> Option<&'a str> {
137    generate_take!(self, name, Number)
138  }
139
140  /// Takes a boolean property value from the object by name.
141  /// Returns `None` when not a boolean or it doesn't exist.
142  pub fn take_boolean(&mut self, name: &str) -> Option<bool> {
143    generate_take!(self, name, Boolean)
144  }
145
146  /// Takes an object property value from the object by name.
147  /// Returns `None` when not an object or it doesn't exist.
148  pub fn take_object(&mut self, name: &str) -> Option<JsonObject<'a>> {
149    generate_take!(self, name, Object)
150  }
151
152  /// Takes an array property value from the object by name.
153  /// Returns `None` when not an array or it doesn't exist.
154  pub fn take_array(&mut self, name: &str) -> Option<JsonArray<'a>> {
155    generate_take!(self, name, Array)
156  }
157}
158
159/// A JSON array.
160#[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  /// Creates a new JsonArray.
180  pub fn new(inner: Vec<JsonValue<'a>>) -> JsonArray<'a> {
181    JsonArray(inner)
182  }
183
184  /// Drops the object returning the inner vector.
185  pub fn take_inner(self) -> Vec<JsonValue<'a>> {
186    self.0
187  }
188
189  /// Iterates over the array elements.
190  pub fn iter(&self) -> Iter<'_, JsonValue<'a>> {
191    self.0.iter()
192  }
193
194  /// Gets a value from the array by index.
195  pub fn get(&self, index: usize) -> Option<&JsonValue<'a>> {
196    self.0.get(index)
197  }
198
199  /// Gets the number of elements.
200  pub fn len(&self) -> usize {
201    self.0.len()
202  }
203
204  /// Gets if the array is empty.
205  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}