jsonb/owned.rs
1// Copyright 2023 Datafuse Labs.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::cmp::Ordering;
16use std::fmt::Display;
17use std::str::FromStr;
18
19use crate::core::ArrayBuilder;
20use crate::core::ObjectBuilder;
21use crate::core::Serializer;
22use crate::error::Error;
23use crate::error::Result;
24use crate::parse_value;
25use crate::RawJsonb;
26
27/// Represents a JSONB data that owns its underlying data.
28///
29/// This struct provides ownership over the binary JSONB representation.
30/// `OwnedJsonb` is primarily used to create JSONB data from other data types (such as JSON String).
31/// However, for most operations, it's necessary to convert an `OwnedJsonb` to a `RawJsonb` using the `as_raw()` method
32/// to avoid unnecessary copying and to take advantage of the performance benefits of the read-only access of the `RawJsonb`.
33#[derive(Debug, Clone)]
34pub struct OwnedJsonb {
35 /// The underlying `Vec<u8>` containing the binary JSONB data.
36 pub(crate) data: Vec<u8>,
37}
38
39impl OwnedJsonb {
40 /// Creates a new OwnedJsonb from a Vec<u8>.
41 ///
42 /// # Arguments
43 ///
44 /// * `data` - The `Vec<u8>` containing the JSONB data.
45 ///
46 /// # Returns
47 ///
48 /// A new `OwnedJsonb` instance.
49 pub fn new(data: Vec<u8>) -> OwnedJsonb {
50 Self { data }
51 }
52
53 /// Creates a `RawJsonb` view of the owned data.
54 /// This is useful for passing the data to functions that expect a `RawJsonb`.
55 /// This does *not* transfer ownership.
56 ///
57 /// # Returns
58 ///
59 /// A `RawJsonb` instance referencing the owned data.
60 pub fn as_raw(&self) -> RawJsonb<'_> {
61 RawJsonb::new(self.data.as_slice())
62 }
63
64 /// Consumes the OwnedJsonb and returns the underlying Vec<u8>.
65 ///
66 /// # Returns
67 ///
68 /// The underlying `Vec<u8>` containing the JSONB data.
69 pub fn to_vec(self) -> Vec<u8> {
70 self.data
71 }
72
73 /// Checks if the JSONB data is empty.
74 ///
75 /// # Returns
76 ///
77 /// `true` if the data is empty, `false` otherwise.
78 pub fn is_empty(&self) -> bool {
79 self.len() == 0
80 }
81
82 /// Returns the length of the JSONB data in bytes.
83 ///
84 /// # Returns
85 ///
86 /// The length of the data in bytes.
87 pub fn len(&self) -> usize {
88 self.data.len()
89 }
90
91 /// Builds a JSONB array from a collection of RawJsonb values.
92 ///
93 /// This function constructs a new JSONB array from an iterator of `RawJsonb` values.
94 /// The resulting `OwnedJsonb` represents the binary encoding of the array.
95 ///
96 /// # Arguments
97 ///
98 /// * `items` - An iterator of `RawJsonb` values representing the elements of the array.
99 ///
100 /// # Returns
101 ///
102 /// * `Ok(OwnedJsonb)` - The newly created JSONB array.
103 /// * `Err(Error)` - If any of the input `RawJsonb` values are invalid or if an error occurs during array construction.
104 ///
105 /// # Examples
106 ///
107 /// ```rust
108 /// use jsonb::OwnedJsonb;
109 /// use jsonb::RawJsonb;
110 ///
111 /// // Create some RawJsonb values
112 /// let owned_num = "1".parse::<OwnedJsonb>().unwrap();
113 /// let owned_str = r#""hello""#.parse::<OwnedJsonb>().unwrap();
114 /// let owned_arr = "[1,2,3]".parse::<OwnedJsonb>().unwrap();
115 ///
116 /// // Build the array
117 /// let raw_jsonbs = vec![owned_num.as_raw(), owned_str.as_raw(), owned_arr.as_raw()];
118 /// let array_result = OwnedJsonb::build_array(raw_jsonbs.into_iter());
119 /// assert!(array_result.is_ok());
120 /// let array = array_result.unwrap();
121 ///
122 /// // Convert to string for easy verification
123 /// assert_eq!(array.to_string(), "[1,\"hello\",[1,2,3]]");
124 ///
125 /// // Example with an empty iterator
126 /// let empty_array =
127 /// OwnedJsonb::build_array(<[RawJsonb<'_>; 0] as IntoIterator>::into_iter([])).unwrap();
128 /// assert_eq!(empty_array.to_string(), "[]");
129 ///
130 /// // Example with invalid input (this will cause an error)
131 /// let invalid_data = OwnedJsonb::new(vec![1, 2, 3, 4]);
132 /// let result = OwnedJsonb::build_array([invalid_data.as_raw()].into_iter());
133 /// assert!(result.is_err());
134 /// ```
135 pub fn build_array<'a>(
136 raw_jsonbs: impl IntoIterator<Item = RawJsonb<'a>>,
137 ) -> Result<OwnedJsonb> {
138 let mut builder = ArrayBuilder::new();
139 for raw_jsonb in raw_jsonbs.into_iter() {
140 builder.push_raw_jsonb(raw_jsonb);
141 }
142 builder.build()
143 }
144
145 /// Builds a JSONB object from a collection of key-value pairs.
146 ///
147 /// This function constructs a new JSONB object from an iterator of key-value pairs. The keys are strings, and the values are `RawJsonb` values.
148 /// The resulting `OwnedJsonb` represents the binary encoding of the object.
149 ///
150 /// # Arguments
151 ///
152 /// * `items` - An iterator of `(K, &'a RawJsonb<'a>)` tuples, where `K` is a type that can be converted into a string slice (`AsRef<str>`) representing the key,
153 /// and the second element is a `RawJsonb` representing the value.
154 ///
155 /// # Returns
156 ///
157 /// * `Ok(OwnedJsonb)` - The newly created JSONB object.
158 /// * `Err(Error)` - If any of the input `RawJsonb` values are invalid, if contain duplicate keys, or if an error occurs during object construction.
159 ///
160 /// # Examples
161 ///
162 /// ```rust
163 /// use jsonb::OwnedJsonb;
164 /// use jsonb::RawJsonb;
165 ///
166 /// // Create some RawJsonb values
167 /// let owned_num = "1".parse::<OwnedJsonb>().unwrap();
168 /// let owned_str = r#""hello""#.parse::<OwnedJsonb>().unwrap();
169 /// let owned_arr = "[1,2,3]".parse::<OwnedJsonb>().unwrap();
170 ///
171 /// // Build the object
172 /// let raw_jsonbs = vec![
173 /// ("a", owned_num.as_raw()),
174 /// ("b", owned_str.as_raw()),
175 /// ("c", owned_arr.as_raw()),
176 /// ];
177 /// let object_result = OwnedJsonb::build_object(raw_jsonbs.into_iter());
178 /// assert!(object_result.is_ok());
179 /// let object = object_result.unwrap();
180 ///
181 /// // Convert to string for easy verification
182 /// assert_eq!(object.to_string(), r#"{"a":1,"b":"hello","c":[1,2,3]}"#);
183 ///
184 /// // Example with an empty iterator
185 /// let empty_object =
186 /// OwnedJsonb::build_object(<[(&str, RawJsonb<'_>); 0] as IntoIterator>::into_iter([]))
187 /// .unwrap();
188 /// assert_eq!(empty_object.to_string(), "{}");
189 ///
190 /// // Example with invalid value
191 /// let invalid_data = OwnedJsonb::new(vec![1, 2, 3, 4]);
192 /// let result = OwnedJsonb::build_object([("a", invalid_data.as_raw())].into_iter());
193 /// assert!(result.is_err());
194 /// ```
195 pub fn build_object<'a, K: AsRef<str>>(
196 items: impl IntoIterator<Item = (K, RawJsonb<'a>)>,
197 ) -> Result<OwnedJsonb> {
198 let mut kvs = Vec::new();
199 for (key, val) in items.into_iter() {
200 kvs.push((key, val));
201 }
202 let mut builder = ObjectBuilder::new();
203 for (key, val) in kvs.iter() {
204 builder.push_raw_jsonb(key.as_ref(), *val)?;
205 }
206 builder.build()
207 }
208}
209
210/// Creates an `OwnedJsonb` from a borrowed byte slice. The byte slice is copied into a new `Vec<u8>`.
211impl From<&[u8]> for OwnedJsonb {
212 fn from(data: &[u8]) -> Self {
213 Self {
214 data: data.to_vec(),
215 }
216 }
217}
218
219/// Creates an `OwnedJsonb` from a `Vec<u8>`. This is a simple ownership transfer.
220impl From<Vec<u8>> for OwnedJsonb {
221 fn from(data: Vec<u8>) -> Self {
222 Self { data }
223 }
224}
225
226/// Parses a string into an `OwnedJsonb`.
227/// The string is parsed into a JSON value, then encoded into the binary JSONB format.
228impl FromStr for OwnedJsonb {
229 type Err = Error;
230
231 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
232 let value = parse_value(s.as_bytes())?;
233 let mut data = Vec::new();
234 value.write_to_vec(&mut data);
235 Ok(Self { data })
236 }
237}
238
239/// Allows accessing the underlying byte slice as a reference.
240/// This enables easy integration with functions that expect a `&[u8]`.
241impl AsRef<[u8]> for OwnedJsonb {
242 fn as_ref(&self) -> &[u8] {
243 self.data.as_ref()
244 }
245}
246
247/// Implements the Display trait, allowing OwnedJsonb to be formatted as a string using the `{}` format specifier.
248impl Display for OwnedJsonb {
249 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
250 let raw_jsonb = self.as_raw();
251 write!(f, "{}", raw_jsonb.to_string())
252 }
253}
254
255impl Eq for OwnedJsonb {}
256
257impl PartialEq for OwnedJsonb {
258 fn eq(&self, other: &Self) -> bool {
259 self.partial_cmp(other) == Some(Ordering::Equal)
260 }
261}
262
263/// Implements `PartialOrd` for `OwnedJsonb`, allowing comparison of two `OwnedJsonb` values.
264///
265/// The comparison logic handles different JSONB types (scalar, array, object) and considers null values.
266/// The ordering is defined as follows:
267///
268/// 1. Null is considered greater than any other type.
269/// 2. Scalars are compared based on their type and value (String > Number > Boolean).
270/// 3. Arrays are compared element by element.
271/// 4. Objects are compared based on their keys and values.
272/// 5. Arrays are greater than objects and scalars.
273/// 6. Objects are greater than scalars.
274/// 7. If the types are incompatible, None is returned.
275#[allow(clippy::non_canonical_partial_ord_impl)]
276impl PartialOrd for OwnedJsonb {
277 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
278 let self_raw = self.as_raw();
279 let other_raw = other.as_raw();
280 self_raw.partial_cmp(&other_raw)
281 }
282}
283
284/// Implements `Ord` for `OwnedJsonb`, allowing comparison of two `OwnedJsonb` values using the total ordering.
285/// This implementation leverages the `PartialOrd` implementation, returning `Ordering::Equal` for incomparable values.
286impl Ord for OwnedJsonb {
287 fn cmp(&self, other: &Self) -> Ordering {
288 let self_raw = self.as_raw();
289 let other_raw = other.as_raw();
290 match self_raw.partial_cmp(&other_raw) {
291 Some(ordering) => ordering,
292 None => Ordering::Equal,
293 }
294 }
295}
296
297/// Serializes a Rust data structure into an `OwnedJsonb` using Serde.
298///
299/// This function takes a Rust type `T` that implements the `Serialize` trait and
300/// serializes it into an `OwnedJsonb`, which is a struct containing a `Vec<u8>`
301/// representing the JSONB data. It uses a custom `Serializer` to handle the
302/// serialization process.
303///
304/// # Arguments
305///
306/// * `value`: A reference to the value of type `T` to be serialized.
307///
308/// # Type Parameters
309///
310/// * `T`: The Rust type to serialize. This type must implement the `serde::ser::Serialize` trait.
311///
312/// # Returns
313///
314/// * `Ok(OwnedJsonb)`: If the serialization is successful, returns an `OwnedJsonb`
315/// containing the serialized JSONB data.
316/// * `Err(e)`: If any Serde serialization error occurs.
317///
318/// # Examples
319///
320/// ```
321/// use jsonb::to_owned_jsonb;
322/// use jsonb::OwnedJsonb;
323/// use serde::Serialize;
324///
325/// #[derive(Serialize, Debug)]
326/// struct Person {
327/// name: String,
328/// age: u32,
329/// }
330///
331/// let person = Person {
332/// name: "Bob".to_string(),
333/// age: 42,
334/// };
335///
336/// let owned_jsonb: OwnedJsonb = to_owned_jsonb(&person).unwrap();
337/// assert_eq!(format!("{}", owned_jsonb), "{\"age\":42,\"name\":\"Bob\"}");
338/// println!("JSONB data: {}", owned_jsonb);
339/// ```
340pub fn to_owned_jsonb<T>(value: &T) -> Result<OwnedJsonb>
341where
342 T: serde::ser::Serialize,
343{
344 let mut serializer = Serializer::default();
345 value.serialize(&mut serializer)?;
346 Ok(serializer.to_owned_jsonb())
347}