jsonb_rs/
functions.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 core::convert::TryInto;
16use std::borrow::Cow;
17use std::cmp::Ordering;
18use std::collections::VecDeque;
19
20use super::constants::*;
21use super::error::*;
22use super::jentry::JEntry;
23use super::json_path::JsonPathRef;
24use super::number::Number;
25use super::parser::decode_value;
26use super::value::Value;
27
28// builtin functions for `JSONB` bytes and `JSON` strings without decode all Values.
29// The input value must be valid `JSONB' or `JSON`.
30
31/// Build `JSONB` array from items.
32/// Assuming that the input values is valid JSONB data.
33pub fn build_array<'a>(
34    items: impl IntoIterator<Item = &'a [u8]>,
35    buf: &mut Vec<u8>,
36) -> Result<(), Error> {
37    let start = buf.len();
38    // reserve space for header
39    buf.resize(start + 4, 0);
40    let mut len: u32 = 0;
41    let mut data = Vec::new();
42    for value in items.into_iter() {
43        let header = read_u32(value, 0)?;
44        let encoded_jentry = match header & CONTAINER_HEADER_TYPE_MASK {
45            SCALAR_CONTAINER_TAG => {
46                let jentry = &value[4..8];
47                data.extend_from_slice(&value[8..]);
48                jentry.try_into().unwrap()
49            }
50            ARRAY_CONTAINER_TAG | OBJECT_CONTAINER_TAG => {
51                data.extend_from_slice(value);
52                (CONTAINER_TAG | value.len() as u32).to_be_bytes()
53            }
54            _ => return Err(Error::InvalidJsonbHeader),
55        };
56        len += 1;
57        buf.extend_from_slice(&encoded_jentry);
58    }
59    // write header
60    let header = ARRAY_CONTAINER_TAG | len;
61    for (i, b) in header.to_be_bytes().iter().enumerate() {
62        buf[start + i] = *b;
63    }
64    buf.extend_from_slice(&data);
65
66    Ok(())
67}
68
69/// Build `JSONB` object from items.
70/// Assuming that the input values is valid JSONB data.
71pub fn build_object<'a, K: AsRef<str>>(
72    items: impl IntoIterator<Item = (K, &'a [u8])>,
73    buf: &mut Vec<u8>,
74) -> Result<(), Error> {
75    let start = buf.len();
76    // reserve space for header
77    buf.resize(start + 4, 0);
78    let mut len: u32 = 0;
79    let mut key_data = Vec::new();
80    let mut val_data = Vec::new();
81    let mut val_jentries = VecDeque::new();
82    for (key, value) in items.into_iter() {
83        let key = key.as_ref();
84        // write key jentry and key data
85        let encoded_key_jentry = (STRING_TAG | key.len() as u32).to_be_bytes();
86        buf.extend_from_slice(&encoded_key_jentry);
87        key_data.extend_from_slice(key.as_bytes());
88
89        // build value jentry and write value data
90        let header = read_u32(value, 0)?;
91        let encoded_val_jentry = match header & CONTAINER_HEADER_TYPE_MASK {
92            SCALAR_CONTAINER_TAG => {
93                let jentry = &value[4..8];
94                val_data.extend_from_slice(&value[8..]);
95                jentry.try_into().unwrap()
96            }
97            ARRAY_CONTAINER_TAG | OBJECT_CONTAINER_TAG => {
98                val_data.extend_from_slice(value);
99                (CONTAINER_TAG | value.len() as u32).to_be_bytes()
100            }
101            _ => return Err(Error::InvalidJsonbHeader),
102        };
103        val_jentries.push_back(encoded_val_jentry);
104        len += 1;
105    }
106    // write header and value jentry
107    let header = OBJECT_CONTAINER_TAG | len;
108    for (i, b) in header.to_be_bytes().iter().enumerate() {
109        buf[start + i] = *b;
110    }
111    while let Some(val_jentry) = val_jentries.pop_front() {
112        buf.extend_from_slice(&val_jentry);
113    }
114    // write key data and value data
115    buf.extend_from_slice(&key_data);
116    buf.extend_from_slice(&val_data);
117
118    Ok(())
119}
120
121/// Get the length of `JSONB` array.
122pub fn array_length(value: &[u8]) -> Option<usize> {
123    if !is_jsonb(value) {
124        let json_value = decode_value(value).unwrap();
125        return json_value.array_length();
126    }
127    let header = read_u32(value, 0).unwrap();
128    match header & CONTAINER_HEADER_TYPE_MASK {
129        ARRAY_CONTAINER_TAG => {
130            let length = (header & CONTAINER_HEADER_LEN_MASK) as usize;
131            Some(length)
132        }
133        _ => None,
134    }
135}
136
137/// Get the inner value by ignoring case name of `JSONB` object.
138pub fn get_by_name_ignore_case(value: &[u8], name: &str) -> Option<Vec<u8>> {
139    if !is_jsonb(value) {
140        let json_value = decode_value(value).unwrap();
141        return json_value.get_by_name_ignore_case(name).map(Value::to_vec);
142    }
143
144    let header = read_u32(value, 0).unwrap();
145    match header & CONTAINER_HEADER_TYPE_MASK {
146        OBJECT_CONTAINER_TAG => {
147            let length = (header & CONTAINER_HEADER_LEN_MASK) as usize;
148            let mut jentry_offset = 4;
149            let mut val_offset = 8 * length + 4;
150
151            let mut key_jentries: VecDeque<JEntry> = VecDeque::with_capacity(length);
152            for _ in 0..length {
153                let encoded = read_u32(value, jentry_offset).unwrap();
154                let key_jentry = JEntry::decode_jentry(encoded);
155
156                jentry_offset += 4;
157                val_offset += key_jentry.length as usize;
158                key_jentries.push_back(key_jentry);
159            }
160
161            let mut offsets = None;
162            let mut key_offset = 8 * length + 4;
163            while let Some(key_jentry) = key_jentries.pop_front() {
164                let prev_key_offset = key_offset;
165                key_offset += key_jentry.length as usize;
166                let key =
167                    unsafe { std::str::from_utf8_unchecked(&value[prev_key_offset..key_offset]) };
168                // first match the value with the same name, if not found,
169                // then match the value with the ignoring case name.
170                if name.eq(key) {
171                    offsets = Some((jentry_offset, val_offset));
172                    break;
173                } else if name.eq_ignore_ascii_case(key) && offsets.is_none() {
174                    offsets = Some((jentry_offset, val_offset));
175                }
176                let val_encoded = read_u32(value, jentry_offset).unwrap();
177                let val_jentry = JEntry::decode_jentry(val_encoded);
178                jentry_offset += 4;
179                val_offset += val_jentry.length as usize;
180            }
181            if let Some((jentry_offset, mut val_offset)) = offsets {
182                let mut buf: Vec<u8> = Vec::new();
183                let encoded = read_u32(value, jentry_offset).unwrap();
184                let jentry = JEntry::decode_jentry(encoded);
185                let prev_val_offset = val_offset;
186                val_offset += jentry.length as usize;
187                match jentry.type_code {
188                    CONTAINER_TAG => buf.extend_from_slice(&value[prev_val_offset..val_offset]),
189                    _ => {
190                        let scalar_header = SCALAR_CONTAINER_TAG;
191                        buf.extend_from_slice(&scalar_header.to_be_bytes());
192                        buf.extend_from_slice(&encoded.to_be_bytes());
193                        if val_offset > prev_val_offset {
194                            buf.extend_from_slice(&value[prev_val_offset..val_offset]);
195                        }
196                    }
197                }
198                return Some(buf);
199            }
200            None
201        }
202        _ => None,
203    }
204}
205
206/// Get the inner value by JSON path of `JSONB` object.
207/// JSON path can be a nested index or name,
208/// used to get inner value of array and object respectively.
209pub fn get_by_path<'a>(value: &'a [u8], paths: Vec<JsonPathRef<'a>>) -> Option<Vec<u8>> {
210    if !is_jsonb(value) {
211        let json_value = decode_value(value).unwrap();
212        return json_value.get_by_path(&paths).map(Value::to_vec);
213    }
214
215    let mut offset = 0;
216    let mut buf: Vec<u8> = Vec::new();
217
218    for i in 0..paths.len() {
219        let path = paths.get(i).unwrap();
220        let header = read_u32(value, offset).unwrap();
221        let (jentry_offset, val_offset) = match path {
222            JsonPathRef::String(name) => {
223                if header & CONTAINER_HEADER_TYPE_MASK != OBJECT_CONTAINER_TAG {
224                    return None;
225                }
226                let length = (header & CONTAINER_HEADER_LEN_MASK) as usize;
227                let mut jentry_offset = offset + 4;
228                let mut val_offset = offset + 8 * length + 4;
229
230                let mut key_jentries: VecDeque<JEntry> = VecDeque::with_capacity(length);
231                for _ in 0..length {
232                    let encoded = read_u32(value, jentry_offset).unwrap();
233                    let key_jentry = JEntry::decode_jentry(encoded);
234
235                    jentry_offset += 4;
236                    val_offset += key_jentry.length as usize;
237                    key_jentries.push_back(key_jentry);
238                }
239
240                let mut found = false;
241                let mut key_offset = offset + 8 * length + 4;
242                while let Some(key_jentry) = key_jentries.pop_front() {
243                    let prev_key_offset = key_offset;
244                    key_offset += key_jentry.length as usize;
245                    let key = unsafe {
246                        std::str::from_utf8_unchecked(&value[prev_key_offset..key_offset])
247                    };
248                    if name.eq(key) {
249                        found = true;
250                        break;
251                    }
252                    let val_encoded = read_u32(value, jentry_offset).unwrap();
253                    let val_jentry = JEntry::decode_jentry(val_encoded);
254                    jentry_offset += 4;
255                    val_offset += val_jentry.length as usize;
256                }
257                if !found {
258                    return None;
259                }
260                (jentry_offset, val_offset)
261            }
262            JsonPathRef::UInt64(index) => {
263                if header & CONTAINER_HEADER_TYPE_MASK != ARRAY_CONTAINER_TAG {
264                    return None;
265                }
266                let length = (header & CONTAINER_HEADER_LEN_MASK) as usize;
267                if *index as usize >= length {
268                    return None;
269                }
270                let mut jentry_offset = offset + 4;
271                let mut val_offset = offset + 4 * length + 4;
272
273                for _ in 0..*index {
274                    let encoded = read_u32(value, jentry_offset).unwrap();
275                    let jentry = JEntry::decode_jentry(encoded);
276
277                    jentry_offset += 4;
278                    val_offset += jentry.length as usize;
279                }
280                (jentry_offset, val_offset)
281            }
282        };
283        let encoded = read_u32(value, jentry_offset).unwrap();
284        let jentry = JEntry::decode_jentry(encoded);
285        // if the last JSON path, return the value
286        // if the value is a container value, then continue get for next JSON path.
287        match jentry.type_code {
288            CONTAINER_TAG => {
289                if i == paths.len() - 1 {
290                    buf.extend_from_slice(&value[val_offset..val_offset + jentry.length as usize]);
291                } else {
292                    offset = val_offset;
293                }
294            }
295            _ => {
296                if i == paths.len() - 1 {
297                    let scalar_header = SCALAR_CONTAINER_TAG;
298                    buf.extend_from_slice(&scalar_header.to_be_bytes());
299                    buf.extend_from_slice(&encoded.to_be_bytes());
300                    if jentry.length > 0 {
301                        buf.extend_from_slice(
302                            &value[val_offset..val_offset + jentry.length as usize],
303                        );
304                    }
305                } else {
306                    return None;
307                }
308            }
309        }
310    }
311    Some(buf)
312}
313
314/// Get the keys of a `JSONB` object.
315pub fn object_keys(value: &[u8]) -> Option<Vec<u8>> {
316    if !is_jsonb(value) {
317        let json_value = decode_value(value).unwrap();
318        return json_value.object_keys().map(|val| val.to_vec());
319    }
320
321    let header = read_u32(value, 0).unwrap();
322    match header & CONTAINER_HEADER_TYPE_MASK {
323        OBJECT_CONTAINER_TAG => {
324            let mut buf: Vec<u8> = Vec::new();
325            let length = (header & CONTAINER_HEADER_LEN_MASK) as usize;
326            let key_header = ARRAY_CONTAINER_TAG | length as u32;
327            buf.extend_from_slice(&key_header.to_be_bytes());
328
329            let mut jentry_offset = 4;
330            let mut key_offset = 8 * length + 4;
331            let mut key_offsets = Vec::with_capacity(length);
332            for _ in 0..length {
333                let key_encoded = read_u32(value, jentry_offset).unwrap();
334                let key_jentry = JEntry::decode_jentry(key_encoded);
335                buf.extend_from_slice(&key_encoded.to_be_bytes());
336
337                jentry_offset += 4;
338                key_offset += key_jentry.length as usize;
339                key_offsets.push(key_offset);
340            }
341            let mut prev_key_offset = 8 * length + 4;
342            for key_offset in key_offsets {
343                if key_offset > prev_key_offset {
344                    buf.extend_from_slice(&value[prev_key_offset..key_offset]);
345                }
346                prev_key_offset = key_offset;
347            }
348            Some(buf)
349        }
350        _ => None,
351    }
352}
353
354/// `JSONB` values supports partial decode for comparison,
355/// if the values are found to be unequal, the result will be returned immediately.
356/// In first level header, values compare as the following order:
357/// Scalar Null > Array > Object > Other Scalars(String > Number > Boolean).
358pub fn compare(left: &[u8], right: &[u8]) -> Result<Ordering, Error> {
359    if !is_jsonb(left) {
360        let lval = decode_value(left).unwrap();
361        let lbuf = lval.to_vec();
362        return compare(&lbuf, right);
363    } else if !is_jsonb(right) {
364        let rval = decode_value(right).unwrap();
365        let rbuf = rval.to_vec();
366        return compare(left, &rbuf);
367    }
368
369    let left_header = read_u32(left, 0)?;
370    let right_header = read_u32(right, 0)?;
371    match (
372        left_header & CONTAINER_HEADER_TYPE_MASK,
373        right_header & CONTAINER_HEADER_TYPE_MASK,
374    ) {
375        (SCALAR_CONTAINER_TAG, SCALAR_CONTAINER_TAG) => {
376            let left_encoded = read_u32(left, 4)?;
377            let left_jentry = JEntry::decode_jentry(left_encoded);
378            let right_encoded = read_u32(right, 4)?;
379            let right_jentry = JEntry::decode_jentry(right_encoded);
380            compare_scalar(&left_jentry, &left[8..], &right_jentry, &right[8..])
381        }
382        (ARRAY_CONTAINER_TAG, ARRAY_CONTAINER_TAG) => {
383            compare_array(left_header, &left[4..], right_header, &right[4..])
384        }
385        (OBJECT_CONTAINER_TAG, OBJECT_CONTAINER_TAG) => {
386            compare_object(left_header, &left[4..], right_header, &right[4..])
387        }
388        (SCALAR_CONTAINER_TAG, ARRAY_CONTAINER_TAG | OBJECT_CONTAINER_TAG) => {
389            let left_encoded = read_u32(left, 4)?;
390            let left_jentry = JEntry::decode_jentry(left_encoded);
391            match left_jentry.type_code {
392                NULL_TAG => Ok(Ordering::Greater),
393                _ => Ok(Ordering::Less),
394            }
395        }
396        (ARRAY_CONTAINER_TAG | OBJECT_CONTAINER_TAG, SCALAR_CONTAINER_TAG) => {
397            let right_encoded = read_u32(right, 4)?;
398            let right_jentry = JEntry::decode_jentry(right_encoded);
399            match right_jentry.type_code {
400                NULL_TAG => Ok(Ordering::Less),
401                _ => Ok(Ordering::Greater),
402            }
403        }
404        (ARRAY_CONTAINER_TAG, OBJECT_CONTAINER_TAG) => Ok(Ordering::Greater),
405        (OBJECT_CONTAINER_TAG, ARRAY_CONTAINER_TAG) => Ok(Ordering::Less),
406        (_, _) => Err(Error::InvalidJsonbHeader),
407    }
408}
409
410// Different types of values have different levels and are definitely not equal
411fn jentry_compare_level(jentry: &JEntry) -> Result<u8, Error> {
412    match jentry.type_code {
413        NULL_TAG => Ok(5),
414        CONTAINER_TAG => Ok(4),
415        STRING_TAG => Ok(3),
416        NUMBER_TAG => Ok(2),
417        TRUE_TAG => Ok(1),
418        FALSE_TAG => Ok(0),
419        _ => Err(Error::InvalidJsonbJEntry),
420    }
421}
422
423// `Scalar` values compare as the following order
424// Null > Container(Array > Object) > String > Number > Boolean
425fn compare_scalar(
426    left_jentry: &JEntry,
427    left: &[u8],
428    right_jentry: &JEntry,
429    right: &[u8],
430) -> Result<Ordering, Error> {
431    let left_level = jentry_compare_level(left_jentry)?;
432    let right_level = jentry_compare_level(right_jentry)?;
433    if left_level != right_level {
434        return Ok(left_level.cmp(&right_level));
435    }
436
437    match (left_jentry.type_code, right_jentry.type_code) {
438        (NULL_TAG, NULL_TAG) => Ok(Ordering::Equal),
439        (CONTAINER_TAG, CONTAINER_TAG) => compare_container(left, right),
440        (STRING_TAG, STRING_TAG) => {
441            let left_offset = left_jentry.length as usize;
442            let left_str = unsafe { std::str::from_utf8_unchecked(&left[..left_offset]) };
443            let right_offset = right_jentry.length as usize;
444            let right_str = unsafe { std::str::from_utf8_unchecked(&right[..right_offset]) };
445            Ok(left_str.cmp(right_str))
446        }
447        (NUMBER_TAG, NUMBER_TAG) => {
448            let left_offset = left_jentry.length as usize;
449            let left_num = Number::decode(&left[..left_offset]);
450            let right_offset = right_jentry.length as usize;
451            let right_num = Number::decode(&right[..right_offset]);
452            Ok(left_num.cmp(&right_num))
453        }
454        (TRUE_TAG, TRUE_TAG) => Ok(Ordering::Equal),
455        (FALSE_TAG, FALSE_TAG) => Ok(Ordering::Equal),
456        (_, _) => Err(Error::InvalidJsonbJEntry),
457    }
458}
459
460fn compare_container(left: &[u8], right: &[u8]) -> Result<Ordering, Error> {
461    let left_header = read_u32(left, 0)?;
462    let right_header = read_u32(right, 0)?;
463
464    match (
465        left_header & CONTAINER_HEADER_TYPE_MASK,
466        right_header & CONTAINER_HEADER_TYPE_MASK,
467    ) {
468        (ARRAY_CONTAINER_TAG, ARRAY_CONTAINER_TAG) => {
469            compare_array(left_header, &left[4..], right_header, &right[4..])
470        }
471        (OBJECT_CONTAINER_TAG, OBJECT_CONTAINER_TAG) => {
472            compare_object(left_header, &left[4..], right_header, &right[4..])
473        }
474        (ARRAY_CONTAINER_TAG, OBJECT_CONTAINER_TAG) => Ok(Ordering::Greater),
475        (OBJECT_CONTAINER_TAG, ARRAY_CONTAINER_TAG) => Ok(Ordering::Less),
476        (_, _) => Err(Error::InvalidJsonbHeader),
477    }
478}
479
480// `Array` values compares each element in turn.
481fn compare_array(
482    left_header: u32,
483    left: &[u8],
484    right_header: u32,
485    right: &[u8],
486) -> Result<Ordering, Error> {
487    let left_length = (left_header & CONTAINER_HEADER_LEN_MASK) as usize;
488    let right_length = (right_header & CONTAINER_HEADER_LEN_MASK) as usize;
489
490    let mut jentry_offset = 0;
491    let mut left_val_offset = 4 * left_length;
492    let mut right_val_offset = 4 * right_length;
493    let length = if left_length < right_length {
494        left_length
495    } else {
496        right_length
497    };
498    for _ in 0..length {
499        let left_encoded = read_u32(left, jentry_offset)?;
500        let left_jentry = JEntry::decode_jentry(left_encoded);
501        let right_encoded = read_u32(right, jentry_offset)?;
502        let right_jentry = JEntry::decode_jentry(right_encoded);
503
504        let order = compare_scalar(
505            &left_jentry,
506            &left[left_val_offset..],
507            &right_jentry,
508            &right[right_val_offset..],
509        )?;
510        if order != Ordering::Equal {
511            return Ok(order);
512        }
513        jentry_offset += 4;
514
515        left_val_offset += left_jentry.length as usize;
516        right_val_offset += right_jentry.length as usize;
517    }
518
519    Ok(left_length.cmp(&right_length))
520}
521
522// `Object` values compares each key-value in turn,
523// first compare the key, and then compare the value if the key is equal.
524// The Greater the key, the Less the Object, the Greater the value, the Greater the Object
525fn compare_object(
526    left_header: u32,
527    left: &[u8],
528    right_header: u32,
529    right: &[u8],
530) -> Result<Ordering, Error> {
531    let left_length = (left_header & CONTAINER_HEADER_LEN_MASK) as usize;
532    let right_length = (right_header & CONTAINER_HEADER_LEN_MASK) as usize;
533
534    let mut jentry_offset = 0;
535    let mut left_val_offset = 8 * left_length;
536    let mut right_val_offset = 8 * right_length;
537
538    let length = if left_length < right_length {
539        left_length
540    } else {
541        right_length
542    };
543    // read all key jentries first
544    let mut left_key_jentries: VecDeque<JEntry> = VecDeque::with_capacity(length);
545    let mut right_key_jentries: VecDeque<JEntry> = VecDeque::with_capacity(length);
546    for _ in 0..length {
547        let left_encoded = read_u32(left, jentry_offset)?;
548        let left_key_jentry = JEntry::decode_jentry(left_encoded);
549        let right_encoded = read_u32(right, jentry_offset)?;
550        let right_key_jentry = JEntry::decode_jentry(right_encoded);
551
552        jentry_offset += 4;
553        left_val_offset += left_key_jentry.length as usize;
554        right_val_offset += right_key_jentry.length as usize;
555
556        left_key_jentries.push_back(left_key_jentry);
557        right_key_jentries.push_back(right_key_jentry);
558    }
559
560    let mut left_jentry_offset = 4 * left_length;
561    let mut right_jentry_offset = 4 * right_length;
562    let mut left_key_offset = 8 * left_length;
563    let mut right_key_offset = 8 * right_length;
564    for _ in 0..length {
565        // first compare key, if keys are equal, then compare the value
566        let left_key_jentry = left_key_jentries.pop_front().unwrap();
567        let right_key_jentry = right_key_jentries.pop_front().unwrap();
568
569        let key_order = compare_scalar(
570            &left_key_jentry,
571            &left[left_key_offset..],
572            &right_key_jentry,
573            &right[right_key_offset..],
574        )?;
575        if key_order != Ordering::Equal {
576            if key_order == Ordering::Greater {
577                return Ok(Ordering::Less);
578            } else {
579                return Ok(Ordering::Greater);
580            }
581        }
582
583        let left_encoded = read_u32(left, left_jentry_offset)?;
584        let left_val_jentry = JEntry::decode_jentry(left_encoded);
585        let right_encoded = read_u32(right, right_jentry_offset)?;
586        let right_val_jentry = JEntry::decode_jentry(right_encoded);
587
588        let val_order = compare_scalar(
589            &left_val_jentry,
590            &left[left_val_offset..],
591            &right_val_jentry,
592            &right[right_val_offset..],
593        )?;
594        if val_order != Ordering::Equal {
595            return Ok(val_order);
596        }
597        left_jentry_offset += 4;
598        right_jentry_offset += 4;
599
600        left_key_offset += left_key_jentry.length as usize;
601        right_key_offset += right_key_jentry.length as usize;
602        left_val_offset += left_val_jentry.length as usize;
603        right_val_offset += right_val_jentry.length as usize;
604    }
605
606    Ok(left_length.cmp(&right_length))
607}
608
609/// Returns true if the `JSONB` is a Null.
610pub fn is_null(value: &[u8]) -> bool {
611    as_null(value).is_some()
612}
613
614/// If the `JSONB` is a Null, returns (). Returns None otherwise.
615pub fn as_null(value: &[u8]) -> Option<()> {
616    if !is_jsonb(value) {
617        if value.is_empty() {
618            return Some(());
619        }
620        let v = value.first().unwrap();
621        if *v == b'n' {
622            return Some(());
623        } else {
624            return None;
625        }
626    }
627    let header = read_u32(value, 0).unwrap();
628    match header & CONTAINER_HEADER_TYPE_MASK {
629        SCALAR_CONTAINER_TAG => {
630            let jentry = read_u32(value, 4).unwrap();
631            match jentry {
632                NULL_TAG => Some(()),
633                _ => None,
634            }
635        }
636        _ => None,
637    }
638}
639
640/// Returns true if the `JSONB` is a Boolean. Returns false otherwise.
641pub fn is_boolean(value: &[u8]) -> bool {
642    as_bool(value).is_some()
643}
644
645/// If the `JSONB` is a Boolean, returns the associated bool. Returns None otherwise.
646pub fn as_bool(value: &[u8]) -> Option<bool> {
647    if !is_jsonb(value) {
648        let v = value.first().unwrap();
649        if *v == b't' {
650            return Some(true);
651        } else if *v == b'f' {
652            return Some(false);
653        } else {
654            return None;
655        }
656    }
657    let header = read_u32(value, 0).unwrap();
658    match header & CONTAINER_HEADER_TYPE_MASK {
659        SCALAR_CONTAINER_TAG => {
660            let jentry = read_u32(value, 4).unwrap();
661            match jentry {
662                FALSE_TAG => Some(false),
663                TRUE_TAG => Some(true),
664                _ => None,
665            }
666        }
667        _ => None,
668    }
669}
670
671/// Cast `JSONB` value to Boolean
672pub fn to_bool(value: &[u8]) -> Result<bool, Error> {
673    if let Some(v) = as_bool(value) {
674        return Ok(v);
675    } else if let Some(v) = as_str(value) {
676        if &v.to_lowercase() == "true" {
677            return Ok(true);
678        } else if &v.to_lowercase() == "false" {
679            return Ok(false);
680        }
681    }
682    Err(Error::InvalidCast)
683}
684
685/// Returns true if the `JSONB` is a Number. Returns false otherwise.
686pub fn is_number(value: &[u8]) -> bool {
687    as_number(value).is_some()
688}
689
690/// If the `JSONB` is a Number, returns the Number. Returns None otherwise.
691pub fn as_number(value: &[u8]) -> Option<Number> {
692    if !is_jsonb(value) {
693        let json_value = decode_value(value).unwrap();
694        return json_value.as_number().cloned();
695    }
696    let header = read_u32(value, 0).unwrap();
697    match header & CONTAINER_HEADER_TYPE_MASK {
698        SCALAR_CONTAINER_TAG => {
699            let jentry_encoded = read_u32(value, 4).unwrap();
700            let jentry = JEntry::decode_jentry(jentry_encoded);
701            match jentry.type_code {
702                NUMBER_TAG => {
703                    let length = jentry.length as usize;
704                    let num = Number::decode(&value[8..8 + length]);
705                    Some(num)
706                }
707                _ => None,
708            }
709        }
710        _ => None,
711    }
712}
713
714/// Returns true if the `JSONB` is a i64 Number. Returns false otherwise.
715pub fn is_i64(value: &[u8]) -> bool {
716    as_i64(value).is_some()
717}
718
719/// Cast `JSONB` value to i64
720pub fn to_i64(value: &[u8]) -> Result<i64, Error> {
721    if let Some(v) = as_i64(value) {
722        return Ok(v);
723    } else if let Some(v) = as_bool(value) {
724        if v {
725            return Ok(1_i64);
726        } else {
727            return Ok(0_i64);
728        }
729    } else if let Some(v) = as_str(value) {
730        if let Ok(v) = v.parse::<i64>() {
731            return Ok(v);
732        }
733    }
734    Err(Error::InvalidCast)
735}
736
737/// If the `JSONB` is a Number, represent it as i64 if possible. Returns None otherwise.
738pub fn as_i64(value: &[u8]) -> Option<i64> {
739    match as_number(value) {
740        Some(num) => num.as_i64(),
741        None => None,
742    }
743}
744
745/// Returns true if the `JSONB` is a u64 Number. Returns false otherwise.
746pub fn is_u64(value: &[u8]) -> bool {
747    as_u64(value).is_some()
748}
749
750/// If the `JSONB` is a Number, represent it as u64 if possible. Returns None otherwise.
751pub fn as_u64(value: &[u8]) -> Option<u64> {
752    match as_number(value) {
753        Some(num) => num.as_u64(),
754        None => None,
755    }
756}
757
758/// Cast `JSONB` value to u64
759pub fn to_u64(value: &[u8]) -> Result<u64, Error> {
760    if let Some(v) = as_u64(value) {
761        return Ok(v);
762    } else if let Some(v) = as_bool(value) {
763        if v {
764            return Ok(1_u64);
765        } else {
766            return Ok(0_u64);
767        }
768    } else if let Some(v) = as_str(value) {
769        if let Ok(v) = v.parse::<u64>() {
770            return Ok(v);
771        }
772    }
773    Err(Error::InvalidCast)
774}
775
776/// Returns true if the `JSONB` is a f64 Number. Returns false otherwise.
777pub fn is_f64(value: &[u8]) -> bool {
778    as_f64(value).is_some()
779}
780
781/// If the `JSONB` is a Number, represent it as f64 if possible. Returns None otherwise.
782pub fn as_f64(value: &[u8]) -> Option<f64> {
783    match as_number(value) {
784        Some(num) => num.as_f64(),
785        None => None,
786    }
787}
788
789/// Cast `JSONB` value to f64
790pub fn to_f64(value: &[u8]) -> Result<f64, Error> {
791    if let Some(v) = as_f64(value) {
792        return Ok(v);
793    } else if let Some(v) = as_bool(value) {
794        if v {
795            return Ok(1_f64);
796        } else {
797            return Ok(0_f64);
798        }
799    } else if let Some(v) = as_str(value) {
800        if let Ok(v) = v.parse::<f64>() {
801            return Ok(v);
802        }
803    }
804    Err(Error::InvalidCast)
805}
806
807/// Returns true if the `JSONB` is a String. Returns false otherwise.
808pub fn is_string(value: &[u8]) -> bool {
809    as_str(value).is_some()
810}
811
812/// If the `JSONB` is a String, returns the String. Returns None otherwise.
813pub fn as_str(value: &[u8]) -> Option<Cow<'_, str>> {
814    if !is_jsonb(value) {
815        let v = value.first().unwrap();
816        if *v == b'"' {
817            let s = unsafe { std::str::from_utf8_unchecked(&value[1..value.len() - 1]) };
818            return Some(Cow::Borrowed(s));
819        } else {
820            return None;
821        }
822    }
823    let header = read_u32(value, 0).unwrap();
824    match header & CONTAINER_HEADER_TYPE_MASK {
825        SCALAR_CONTAINER_TAG => {
826            let jentry_encoded = read_u32(value, 4).unwrap();
827            let jentry = JEntry::decode_jentry(jentry_encoded);
828            match jentry.type_code {
829                STRING_TAG => {
830                    let length = jentry.length as usize;
831                    let s = unsafe { std::str::from_utf8_unchecked(&value[8..8 + length]) };
832                    Some(Cow::Borrowed(s))
833                }
834                _ => None,
835            }
836        }
837        _ => None,
838    }
839}
840
841/// Cast `JSONB` value to String
842pub fn to_str(value: &[u8]) -> Result<String, Error> {
843    if is_null(value) {
844        return Err(Error::InvalidCast);
845    } else if let Some(v) = as_str(value) {
846        return Ok(v.to_string());
847    }
848    Ok(to_string(value))
849}
850
851/// Returns true if the `JSONB` is An Array. Returns false otherwise.
852pub fn is_array(value: &[u8]) -> bool {
853    if !is_jsonb(value) {
854        let v = value.first().unwrap();
855        return *v == b'[';
856    }
857    let header = read_u32(value, 0).unwrap();
858    matches!(header & CONTAINER_HEADER_TYPE_MASK, ARRAY_CONTAINER_TAG)
859}
860
861/// Returns true if the `JSONB` is An Object. Returns false otherwise.
862pub fn is_object(value: &[u8]) -> bool {
863    if !is_jsonb(value) {
864        let v = value.first().unwrap();
865        return *v == b'{';
866    }
867    let header = read_u32(value, 0).unwrap();
868    matches!(header & CONTAINER_HEADER_TYPE_MASK, OBJECT_CONTAINER_TAG)
869}
870
871/// Parse path string to Json path.
872/// Support `["<name>"]`, `[<index>]`, `:name` and `.name`.
873pub fn parse_json_path(path: &[u8]) -> Result<Vec<JsonPathRef>, Error> {
874    let mut idx = 0;
875    let mut prev_idx = 0;
876    let mut json_paths = Vec::new();
877    while idx < path.len() {
878        let c = read_char(path, &mut idx)?;
879        if c == b'[' {
880            let c = read_char(path, &mut idx)?;
881            if c == b'"' {
882                prev_idx = idx;
883                loop {
884                    let c = read_char(path, &mut idx)?;
885                    if c == b'\\' {
886                        idx += 1;
887                    } else if c == b'"' {
888                        let c = read_char(path, &mut idx)?;
889                        if c != b']' {
890                            return Err(Error::InvalidToken);
891                        }
892                        break;
893                    }
894                }
895                if prev_idx == idx - 2 {
896                    return Err(Error::InvalidToken);
897                }
898                let s = std::str::from_utf8(&path[prev_idx..idx - 2])?;
899                let json_path = JsonPathRef::String(Cow::Borrowed(s));
900
901                json_paths.push(json_path);
902            } else {
903                prev_idx = idx - 1;
904                loop {
905                    let c = read_char(path, &mut idx)?;
906                    if c == b']' {
907                        break;
908                    }
909                }
910                if prev_idx == idx - 1 {
911                    return Err(Error::InvalidToken);
912                }
913                let s = std::str::from_utf8(&path[prev_idx..idx - 1])?;
914                if let Ok(v) = s.parse::<u64>() {
915                    let json_path = JsonPathRef::UInt64(v);
916                    json_paths.push(json_path);
917                } else {
918                    return Err(Error::InvalidToken);
919                }
920            }
921        } else if c == b'"' {
922            prev_idx = idx;
923            loop {
924                let c = read_char(path, &mut idx)?;
925                if c == b'\\' {
926                    idx += 1;
927                } else if c == b'"' {
928                    if idx < path.len() {
929                        return Err(Error::InvalidToken);
930                    }
931                    break;
932                }
933            }
934            let s = std::str::from_utf8(&path[prev_idx..idx - 1])?;
935            let json_path = JsonPathRef::String(Cow::Borrowed(s));
936            if json_paths.is_empty() {
937                json_paths.push(json_path);
938            } else {
939                return Err(Error::InvalidToken);
940            }
941        } else {
942            if c == b':' || c == b'.' {
943                if idx == 1 {
944                    return Err(Error::InvalidToken);
945                } else {
946                    prev_idx = idx;
947                }
948            }
949            while idx < path.len() {
950                let c = read_char(path, &mut idx)?;
951                if c == b':' || c == b'.' || c == b'[' {
952                    idx -= 1;
953                    break;
954                } else if c == b'\\' {
955                    idx += 1;
956                }
957            }
958            if prev_idx == idx {
959                return Err(Error::InvalidToken);
960            }
961            let s = std::str::from_utf8(&path[prev_idx..idx])?;
962            let json_path = JsonPathRef::String(Cow::Borrowed(s));
963            json_paths.push(json_path);
964        }
965    }
966    Ok(json_paths)
967}
968
969/// Convert `JSONB` value to String
970pub fn to_string(value: &[u8]) -> String {
971    if !is_jsonb(value) {
972        let json = unsafe { String::from_utf8_unchecked(value.to_vec()) };
973        return json;
974    }
975
976    let mut json = String::new();
977    container_to_string(value, &mut 0, &mut json);
978    json
979}
980
981fn container_to_string(value: &[u8], offset: &mut usize, json: &mut String) {
982    let header = read_u32(value, *offset).unwrap();
983    match header & CONTAINER_HEADER_TYPE_MASK {
984        SCALAR_CONTAINER_TAG => {
985            let mut jentry_offset = 4 + *offset;
986            let mut value_offset = 8 + *offset;
987            scalar_to_string(value, &mut jentry_offset, &mut value_offset, json);
988        }
989        ARRAY_CONTAINER_TAG => {
990            json.push('[');
991            let length = (header & CONTAINER_HEADER_LEN_MASK) as usize;
992            let mut jentry_offset = 4 + *offset;
993            let mut value_offset = 4 + *offset + 4 * length;
994            for i in 0..length {
995                if i > 0 {
996                    json.push(',');
997                }
998                scalar_to_string(value, &mut jentry_offset, &mut value_offset, json);
999            }
1000            json.push(']');
1001        }
1002        OBJECT_CONTAINER_TAG => {
1003            json.push('{');
1004            let length = (header & CONTAINER_HEADER_LEN_MASK) as usize;
1005            let mut jentry_offset = 4 + *offset;
1006            let mut key_offset = 4 + *offset + 8 * length;
1007            let mut keys = VecDeque::with_capacity(length);
1008            for _ in 0..length {
1009                let jentry_encoded = read_u32(value, jentry_offset).unwrap();
1010                let jentry = JEntry::decode_jentry(jentry_encoded);
1011                let key_length = jentry.length as usize;
1012                let key = unsafe {
1013                    std::str::from_utf8_unchecked(&value[key_offset..key_offset + key_length])
1014                };
1015                keys.push_back(key);
1016                jentry_offset += 4;
1017                key_offset += key_length;
1018            }
1019            let mut value_offset = key_offset;
1020            for i in 0..length {
1021                if i > 0 {
1022                    json.push(',');
1023                }
1024                let key = keys.pop_front().unwrap();
1025                json.push('\"');
1026                json.push_str(key);
1027                json.push('\"');
1028                json.push(':');
1029                scalar_to_string(value, &mut jentry_offset, &mut value_offset, json);
1030            }
1031            json.push('}');
1032        }
1033        _ => {}
1034    }
1035}
1036
1037fn scalar_to_string(
1038    value: &[u8],
1039    jentry_offset: &mut usize,
1040    value_offset: &mut usize,
1041    json: &mut String,
1042) {
1043    let jentry_encoded = read_u32(value, *jentry_offset).unwrap();
1044    let jentry = JEntry::decode_jentry(jentry_encoded);
1045    let length = jentry.length as usize;
1046    match jentry.type_code {
1047        NULL_TAG => json.push_str("null"),
1048        TRUE_TAG => json.push_str("true"),
1049        FALSE_TAG => json.push_str("false"),
1050        NUMBER_TAG => {
1051            let num = Number::decode(&value[*value_offset..*value_offset + length]);
1052            json.push_str(&format!("{num}"));
1053        }
1054        STRING_TAG => {
1055            let val = unsafe {
1056                std::str::from_utf8_unchecked(&value[*value_offset..*value_offset + length])
1057            };
1058            json.push('\"');
1059            json.push_str(val);
1060            json.push('\"');
1061        }
1062        CONTAINER_TAG => {
1063            container_to_string(value, value_offset, json);
1064        }
1065        _ => {}
1066    }
1067    *jentry_offset += 4;
1068    *value_offset += length;
1069}
1070
1071// Check whether the value is `JSONB` format,
1072// for compatibility with previous `JSON` string.
1073fn is_jsonb(value: &[u8]) -> bool {
1074    if let Some(v) = value.first() {
1075        if *v == ARRAY_PREFIX || *v == OBJECT_PREFIX || *v == SCALAR_PREFIX {
1076            return true;
1077        }
1078    }
1079    false
1080}
1081
1082fn read_char(buf: &[u8], idx: &mut usize) -> Result<u8, Error> {
1083    match buf.get(*idx) {
1084        Some(v) => {
1085            *idx += 1;
1086            Ok(*v)
1087        }
1088        None => Err(Error::InvalidEOF),
1089    }
1090}
1091
1092fn read_u32(buf: &[u8], idx: usize) -> Result<u32, Error> {
1093    let bytes: [u8; 4] = buf
1094        .get(idx..idx + 4)
1095        .ok_or(Error::InvalidEOF)?
1096        .try_into()
1097        .unwrap();
1098    Ok(u32::from_be_bytes(bytes))
1099}