/rust/registry/src/index.crates.io-1949cf8c6b5b557f/simd-json-0.17.0/src/value.rs
Line | Count | Source |
1 | | /// This module holds the two dom implementations we use. |
2 | | /// |
3 | | /// We distinguish between owned and borrowed. The difference being is that |
4 | | /// the borrowed value will use `&str` as its string type, referencing the input, |
5 | | /// while owned will allocate a new String for each value. |
6 | | /// |
7 | | /// Note that since JSON strings allow for escape sequences the borrowed |
8 | | /// value does not implement zero copy parsing, it does however not allocate |
9 | | /// new memory for strings. |
10 | | /// |
11 | | /// This differs notably from Serde's zero copy implementation as, unlike Serde, |
12 | | /// we do not require prior knowledge about string content to take advantage |
13 | | /// of it. |
14 | | /// |
15 | | /// ## Usage |
16 | | /// The value trait is meant to simplify interacting with DOM values, for both |
17 | | /// creation as well as mutation and inspection. |
18 | | /// |
19 | | /// Objects can be treated as hashmap's for the most part |
20 | | /// ```rust |
21 | | /// use simd_json::{OwnedValue as Value, prelude::*}; |
22 | | /// let mut v = Value::object(); |
23 | | /// v.insert("key", 42); |
24 | | /// assert_eq!(v.get("key").unwrap(), &42); |
25 | | /// assert_eq!(v["key"], &42); |
26 | | /// assert_eq!(v.remove("key").unwrap().unwrap(), 42); |
27 | | /// assert_eq!(v.get("key"), None); |
28 | | /// ``` |
29 | | /// |
30 | | /// Arrays can be treated as vectors for the most part |
31 | | /// |
32 | | /// ```rust |
33 | | /// use simd_json::{OwnedValue as Value, prelude::*}; |
34 | | /// let mut v = Value::array(); |
35 | | /// v.push("zero"); |
36 | | /// v.push(1); |
37 | | /// assert_eq!(v[0], &"zero"); |
38 | | /// assert_eq!(v.get_idx(1).unwrap(), &1); |
39 | | /// assert_eq!(v.pop().unwrap().unwrap(), 1); |
40 | | /// assert_eq!(v.pop().unwrap().unwrap(), "zero"); |
41 | | /// assert_eq!(v.pop().unwrap(), None); |
42 | | /// ``` |
43 | | /// |
44 | | /// Nested changes are also possible: |
45 | | /// ```rust |
46 | | /// use simd_json::{OwnedValue as Value, prelude::*}; |
47 | | /// let mut o = Value::object(); |
48 | | /// o.insert("key", Value::array()); |
49 | | /// o["key"].push(Value::object()); |
50 | | /// o["key"][0].insert("other", "value"); |
51 | | /// assert_eq!(o.encode(), r#"{"key":[{"other":"value"}]}"#); |
52 | | /// ``` |
53 | | /// Borrowed values, using Cow's for strings using in situ parsing strategies wherever possible |
54 | | pub mod borrowed; |
55 | | /// Owned, lifetimeless version of the value for times when lifetimes are to be avoided |
56 | | pub mod owned; |
57 | | /// Tape implementation |
58 | | pub mod tape; |
59 | | |
60 | | pub mod lazy; |
61 | | |
62 | | pub use self::borrowed::{ |
63 | | Value as BorrowedValue, to_value as to_borrowed_value, |
64 | | to_value_with_buffers as to_borrowed_value_with_buffers, |
65 | | }; |
66 | | pub use self::owned::{ |
67 | | Value as OwnedValue, to_value as to_owned_value, |
68 | | to_value_with_buffers as to_owned_value_with_buffers, |
69 | | }; |
70 | | use crate::{Buffers, Deserializer, Result}; |
71 | | use halfbrown::HashMap; |
72 | | use std::hash::Hash; |
73 | | use std::marker::PhantomData; |
74 | | use tape::Node; |
75 | | pub use value_trait::*; |
76 | | |
77 | | /// Hasher used for objects |
78 | | #[cfg(feature = "known-key")] |
79 | | pub type ObjectHasher = crate::known_key::NotSoRandomState; |
80 | | /// Hasher used for objects |
81 | | #[cfg(not(feature = "known-key"))] |
82 | | pub type ObjectHasher = halfbrown::DefaultHashBuilder; |
83 | | |
84 | | /// Parses a slice of bytes into a Value dom. |
85 | | /// |
86 | | /// This function will rewrite the slice to de-escape strings. |
87 | | /// As we reference parts of the input slice the resulting dom |
88 | | /// has the same lifetime as the slice it was created from. |
89 | | /// |
90 | | /// # Errors |
91 | | /// |
92 | | /// Will return `Err` if `s` is invalid JSON. |
93 | 0 | pub fn deserialize<'de, Value, Key>(s: &'de mut [u8]) -> Result<Value> |
94 | 0 | where |
95 | 0 | Value: ValueBuilder<'de> + From<Vec<Value>> + From<HashMap<Key, Value, ObjectHasher>> + 'de, |
96 | 0 | Key: Hash + Eq + From<&'de str>, |
97 | | { |
98 | 0 | match Deserializer::from_slice(s) { |
99 | 0 | Ok(de) => Ok(ValueDeserializer::from_deserializer(de).parse()), |
100 | 0 | Err(e) => Err(e), |
101 | | } |
102 | 0 | } |
103 | | |
104 | | /// Parses a slice of bytes into a Value dom. |
105 | | /// |
106 | | /// This function will rewrite the slice to de-escape strings. |
107 | | /// As we reference parts of the input slice the resulting dom |
108 | | /// has the same lifetime as the slice it was created from. |
109 | | /// |
110 | | /// Passes in reusable buffers to reduce allocations. |
111 | | /// |
112 | | /// # Errors |
113 | | /// |
114 | | /// Will return `Err` if `s` is invalid JSON. |
115 | 0 | pub fn deserialize_with_buffers<'de, Value, Key>( |
116 | 0 | s: &'de mut [u8], |
117 | 0 | buffers: &mut Buffers, |
118 | 0 | ) -> Result<Value> |
119 | 0 | where |
120 | 0 | Value: ValueBuilder<'de> + From<Vec<Value>> + From<HashMap<Key, Value, ObjectHasher>> + 'de, |
121 | 0 | Key: Hash + Eq + From<&'de str>, |
122 | | { |
123 | 0 | match Deserializer::from_slice_with_buffers(s, buffers) { |
124 | 0 | Ok(de) => Ok(ValueDeserializer::from_deserializer(de).parse()), |
125 | 0 | Err(e) => Err(e), |
126 | | } |
127 | 0 | } |
128 | | |
129 | | struct ValueDeserializer<'de, Value, Key> |
130 | | where |
131 | | Value: ValueBuilder<'de> + From<Vec<Value>> + From<HashMap<Key, Value, ObjectHasher>> + 'de, |
132 | | Key: Hash + Eq + From<&'de str>, |
133 | | { |
134 | | de: Deserializer<'de>, |
135 | | _marker: PhantomData<(Value, Key)>, |
136 | | } |
137 | | |
138 | | impl<'de, Value, Key> ValueDeserializer<'de, Value, Key> |
139 | | where |
140 | | Value: ValueBuilder<'de> |
141 | | + From<&'de str> |
142 | | + From<Vec<Value>> |
143 | | + From<HashMap<Key, Value, ObjectHasher>> |
144 | | + 'de, |
145 | | Key: Hash + Eq + From<&'de str>, |
146 | | { |
147 | 0 | pub fn from_deserializer(de: Deserializer<'de>) -> Self { |
148 | 0 | Self { |
149 | 0 | de, |
150 | 0 | _marker: PhantomData, |
151 | 0 | } |
152 | 0 | } |
153 | | |
154 | | #[cfg_attr(not(feature = "no-inline"), inline)] |
155 | 0 | pub fn parse(&mut self) -> Value { |
156 | 0 | match unsafe { self.de.next_() } { |
157 | 0 | Node::Static(s) => Value::from(s), |
158 | 0 | Node::String(s) => Value::from(s), |
159 | 0 | Node::Array { len, count: _ } => self.parse_array(len), |
160 | 0 | Node::Object { len, count: _ } => self.parse_map(len), |
161 | | } |
162 | 0 | } |
163 | | |
164 | | #[cfg_attr(not(feature = "no-inline"), inline)] |
165 | 0 | fn parse_array(&mut self, len: usize) -> Value { |
166 | | // Rust doesn't optimize the normal loop away here |
167 | | // so we write our own avoiding the length |
168 | | // checks during push |
169 | 0 | let mut res: Vec<Value> = Vec::with_capacity(len); |
170 | 0 | let res_ptr = res.as_mut_ptr(); |
171 | | unsafe { |
172 | 0 | for i in 0..len { |
173 | 0 | res_ptr.add(i).write(self.parse()); |
174 | 0 | } |
175 | 0 | res.set_len(len); |
176 | | } |
177 | 0 | Value::from(res) |
178 | 0 | } |
179 | | |
180 | | #[cfg_attr(not(feature = "no-inline"), inline)] |
181 | 0 | fn parse_map(&mut self, len: usize) -> Value { |
182 | 0 | let mut res: HashMap<Key, Value, ObjectHasher> = |
183 | 0 | HashMap::with_capacity_and_hasher(len, ObjectHasher::default()); |
184 | | |
185 | | // Since we checked if it's empty we know that we at least have one |
186 | | // element so we eat this |
187 | 0 | for _ in 0..len { |
188 | 0 | if let Node::String(key) = unsafe { self.de.next_() } { |
189 | 0 | #[cfg(not(feature = "value-no-dup-keys"))] |
190 | 0 | unsafe { |
191 | 0 | res.insert_nocheck(key.into(), self.parse()); |
192 | 0 | }; |
193 | 0 | #[cfg(feature = "value-no-dup-keys")] |
194 | 0 | res.insert(key.into(), self.parse()); |
195 | 0 | } else { |
196 | 0 | unreachable!("parse_map: key needs to be a string"); |
197 | | } |
198 | | } |
199 | 0 | Value::from(res) |
200 | 0 | } |
201 | | } |