Skip to main content

diesel/sqlite/types/
json.rs

1//! Support for JSON and JSONB values under SQLite.
2
3use crate::deserialize::{self, FromSql};
4use crate::serialize::{self, IsNull, Output, ToSql};
5use crate::sql_types;
6use crate::sqlite::{Sqlite, SqliteValue};
7
8#[cfg(all(feature = "sqlite", feature = "serde_json"))]
9impl FromSql<sql_types::Json, Sqlite> for serde_json::Value {
10    fn from_sql(mut value: SqliteValue<'_, '_, '_>) -> deserialize::Result<Self> {
11        serde_json::from_str(value.read_text()).map_err(|_| "Invalid Json".into())
12    }
13}
14
15#[cfg(all(feature = "sqlite", feature = "serde_json"))]
16impl ToSql<sql_types::Json, Sqlite> for serde_json::Value {
17    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
18        out.set_value(serde_json::to_string(self)?);
19        Ok(IsNull::No)
20    }
21}
22
23#[cfg(all(feature = "sqlite", feature = "serde_json"))]
24impl FromSql<sql_types::Jsonb, Sqlite> for serde_json::Value {
25    fn from_sql(mut value: SqliteValue<'_, '_, '_>) -> deserialize::Result<Self> {
26        use self::jsonb::*;
27
28        let bytes = value.read_blob();
29
30        if bytes.is_empty() {
31            return Err("Empty blob cannot be decoded as JSONB".into());
32        }
33
34        // Read the JSONB value from the byte stream
35        let (jsonb, size) = read_jsonb_value(bytes)?;
36        if size == bytes.len() {
37            Ok(jsonb)
38        } else {
39            Err("Payload contained more bytes than the encoded JSONB".into())
40        }
41    }
42}
43
44#[cfg(all(feature = "sqlite", feature = "serde_json"))]
45impl ToSql<sql_types::Jsonb, Sqlite> for serde_json::Value {
46    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
47        use self::jsonb::*;
48
49        // Create a buffer to hold the binary JSONB encoding
50        let mut buffer = Vec::new();
51
52        // Write the JSON value into the buffer in JSONB format
53        write_jsonb_value(self, &mut buffer)?;
54
55        // Set the serialized binary data to the output
56        out.set_value(buffer);
57
58        Ok(IsNull::No)
59    }
60}
61
62#[cfg(all(feature = "sqlite", feature = "serde_json"))]
63mod jsonb {
64    extern crate serde_json;
65
66    use std::error::Error;
67
68    use super::*;
69
70    pub(super) const JSONB_NULL: u8 = 0x00;
71    pub(super) const JSONB_TRUE: u8 = 0x01;
72    pub(super) const JSONB_FALSE: u8 = 0x02;
73    pub(super) const JSONB_INT: u8 = 0x03;
74    pub(super) const JSONB_INT5: u8 = 0x04;
75    pub(super) const JSONB_FLOAT: u8 = 0x05;
76    pub(super) const JSONB_FLOAT5: u8 = 0x06;
77    pub(super) const JSONB_TEXT: u8 = 0x07;
78    pub(super) const JSONB_TEXTJ: u8 = 0x08;
79    pub(super) const JSONB_TEXT5: u8 = 0x09;
80    pub(super) const JSONB_TEXTRAW: u8 = 0x0A;
81    pub(super) const JSONB_ARRAY: u8 = 0x0B;
82    pub(super) const JSONB_OBJECT: u8 = 0x0C;
83
84    #[derive(#[automatically_derived]
impl ::core::fmt::Debug for JsonbHeader {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field4_finish(f, "JsonbHeader",
            "element_type", &self.element_type, "payload_size",
            &self.payload_size, "header_size", &self.header_size,
            "total_size", &&self.total_size)
    }
}Debug)]
85    struct JsonbHeader {
86        element_type: u8,
87        payload_size: usize,
88        header_size: usize,
89        total_size: usize,
90    }
91
92    // Helper function to read a JSONB value from the byte stream
93    #[allow(unsafe_code)]
94    pub(super) fn read_jsonb_value(
95        bytes: &[u8],
96    ) -> deserialize::Result<(serde_json::Value, usize)> {
97        if bytes.is_empty() {
98            return Err("Empty JSONB data".into());
99        }
100        let (global_header, mut global_value) = read_header_and_value(bytes)?;
101
102        if global_value.is_array() || global_value.is_object() {
103            // we need to use pointers here, as the borrow checker does not understand
104            // that we only modify the last value in this stack. Given that we cannot
105            // invalidate any pointer that's up in the stack
106            let mut stack = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(&mut global_value as *mut serde_json::Value,
                    global_header.payload_size)]))vec![(
107                &mut global_value as *mut serde_json::Value,
108                global_header.payload_size,
109            )];
110            let mut payload = &bytes[global_header.header_size..];
111            let mut total_read = 0;
112            // we must use a loop based decoding approach here instead of the much simpler recursive implementation
113            // as we otherwise run into stack overflows for deeply nested objects/arrays
114
115            while total_read < global_header.payload_size {
116                let Some((value, _size)) = stack.last().copied() else {
117                    break;
118                };
119                let value = unsafe {
120                    // SAFETY: The pointer was initialized before
121                    // We we cannot invalidate the underlying object
122                    &mut *value
123                };
124
125                if let serde_json::Value::Array(array) = value {
126                    let (header, value) = read_header_and_value(payload)?;
127
128                    array.push(value);
129                    let last_ref = array.last_mut().expect("Pushed above");
130                    let payload_size = if last_ref.is_object() || last_ref.is_array() {
131                        stack.push((last_ref as *mut _, total_read + header.total_size));
132                        header.header_size
133                    } else {
134                        header.total_size
135                    };
136                    total_read += payload_size;
137                    if payload.len() > payload_size {
138                        payload = &payload[payload_size..];
139                    } else {
140                        for (_, v) in stack {
141                            if v != total_read {
142                                return Err("Invalid size of payload declared".into());
143                            }
144                        }
145                        break;
146                    }
147                } else if let serde_json::Value::Object(object) = value {
148                    //       while total_read < payload_size {
149                    let (key_header, key) = read_header_and_value(payload)?;
150                    total_read += key_header.total_size;
151                    let serde_json::Value::String(key) = key else {
152                        return Err("Expected a string as object key".into());
153                    };
154                    if payload.len() > key_header.total_size {
155                        payload = &payload[key_header.total_size..];
156                    } else {
157                        return Err("No value found for object".into());
158                    }
159                    let (value_header, value) = read_header_and_value(payload)?;
160                    object.insert(key.clone(), value);
161                    let last_ref = object.get_mut(&key).expect("We inserted it above");
162                    let payload_size = if last_ref.is_object() || last_ref.is_array() {
163                        stack.push((last_ref as *mut _, total_read + value_header.total_size));
164                        value_header.header_size
165                    } else {
166                        value_header.total_size
167                    };
168                    total_read += payload_size;
169                    if payload.len() > payload_size {
170                        payload = &payload[payload_size..];
171                    } else {
172                        for (_, v) in stack {
173                            if v != total_read {
174                                return Err("Invalid size of payload declared".into());
175                            }
176                        }
177                        break;
178                    }
179                } else {
180                    ::core::panicking::panic("internal error: entered unreachable code")unreachable!()
181                }
182
183                while let Some(v) = stack.last().map(|(_, v)| *v) {
184                    if v > total_read {
185                        break;
186                    } else if v == total_read {
187                        stack.pop();
188                    } else {
189                        return Err("Invalid size of payload declared".into());
190                    }
191                }
192            }
193        }
194        Ok((global_value, global_header.total_size))
195    }
196
197    // This function decodes the jsonb header
198    // and the value for non-composite values. For composite values like array and object
199    // we only decode the "value header" and leave decoding
200    // the actual child values to future calls
201    fn read_header_and_value(
202        bytes: &[u8],
203    ) -> deserialize::Result<(JsonbHeader, serde_json::Value)> {
204        let header = read_jsonb_value_header(bytes)?;
205        let payload_bytes = &bytes[header.header_size..header.total_size];
206        let value = match header.element_type {
207            JSONB_NULL => Ok(serde_json::Value::Null),
208            JSONB_TRUE => Ok(serde_json::Value::Bool(true)),
209            JSONB_FALSE => Ok(serde_json::Value::Bool(false)),
210            JSONB_INT => read_jsonb_int(payload_bytes, header.payload_size),
211            JSONB_INT5 => Err("INT5 is not supported".into()),
212            JSONB_FLOAT => read_jsonb_float(payload_bytes, header.payload_size),
213            JSONB_FLOAT5 => Err("FLOAT5 is not supported".into()),
214            JSONB_TEXT => read_jsonb_text(payload_bytes, header.payload_size),
215            JSONB_TEXTJ => read_jsonb_textj(payload_bytes, header.payload_size),
216            JSONB_TEXTRAW => read_jsonb_text(payload_bytes, header.payload_size),
217            JSONB_TEXT5 => Err("TEXT5 is not supported".into()),
218            JSONB_ARRAY => Ok(serde_json::Value::Array(Vec::new())),
219            JSONB_OBJECT => Ok(serde_json::Value::Object(serde_json::Map::new())),
220            _ => Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Unsupported or reserved JSONB type: {0}",
                header.element_type))
    })format!(
221                "Unsupported or reserved JSONB type: {}",
222                header.element_type
223            )
224            .into()),
225        }?;
226        Ok((header, value))
227    }
228
229    fn read_jsonb_value_header(bytes: &[u8]) -> deserialize::Result<JsonbHeader> {
230        let first_byte = bytes[0];
231        let element_type = first_byte & 0x0F;
232        let size_hint = (first_byte & 0xF0) >> 4;
233        let (payload_size, header_size): (usize, usize) = match size_hint {
234            0x00..=0x0B => (size_hint as usize, 1), // Payload size is directly in the upper nibble
235            0x0C => {
236                if bytes.len() < 2 {
237                    return Err("Invalid JSONB data: insufficient bytes for payload size".into());
238                }
239                (bytes[1] as usize, 2) // 1 additional byte for payload size
240            }
241            0x0D => {
242                if bytes.len() < 3 {
243                    return Err("Invalid JSONB data: insufficient bytes for payload size".into());
244                }
245                (u16::from_be_bytes([bytes[1], bytes[2]]) as usize, 3) // 2 additional bytes
246            }
247            0x0E => {
248                if bytes.len() < 5 {
249                    return Err("Invalid JSONB data: insufficient bytes for payload size".into());
250                }
251                (
252                    u32::from_be_bytes([bytes[1], bytes[2], bytes[3], bytes[4]]) as usize,
253                    5,
254                ) // 4 additional bytes
255            }
256            0x0F => {
257                if bytes.len() < 9 {
258                    return Err("Invalid JSONB data: insufficient bytes for payload size".into());
259                }
260                (
261                    usize::try_from(u64::from_be_bytes([
262                        bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
263                        bytes[8],
264                    ]))
265                    .map_err(Box::new)?,
266                    9,
267                ) // 8 additional bytes
268            }
269            _ => return Err("Invalid payload size hint".into()),
270        };
271        let total_size = header_size
272            .checked_add(payload_size)
273            .ok_or("The provided payload size overflows usize")?;
274        if bytes.len() < total_size {
275            return Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Invalid JSONB data: insufficient bytes for value of type {0}, expected {1} bytes, got {2}",
                element_type, total_size, bytes.len()))
    })format!(
276                "Invalid JSONB data: insufficient bytes for value of type {}, expected {} bytes, got {}",
277                element_type,
278                total_size,
279                bytes.len()
280            )
281            .into());
282        }
283
284        Ok(JsonbHeader {
285            element_type,
286            payload_size,
287            header_size,
288            total_size,
289        })
290    }
291
292    // Read a JSON integer in canonical format (INT)
293    pub(super) fn read_jsonb_int(
294        bytes: &[u8],
295        payload_size: usize,
296    ) -> deserialize::Result<serde_json::Value> {
297        // Ensure the bytes are at least as large as the payload size
298        if bytes.len() < payload_size {
299            return Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Expected payload of size {0}, but got {1}",
                payload_size, bytes.len()))
    })format!(
300                "Expected payload of size {}, but got {}",
301                payload_size,
302                bytes.len()
303            )
304            .into());
305        }
306
307        // Read only the number of bytes specified by the payload size
308        let int_str = std::str::from_utf8(bytes).map_err(|_| "Invalid ASCII in JSONB integer")?;
309        let int_value = serde_json::from_str(int_str)
310            .map_err(|_| "Failed to parse JSONB")
311            .and_then(|v: serde_json::Value| {
312                v.is_i64()
313                    .then_some(v)
314                    .ok_or("Failed to parse JSONB integer")
315            })?;
316
317        Ok(int_value)
318    }
319
320    // Read a JSON float in canonical format (FLOAT)
321    pub(super) fn read_jsonb_float(
322        bytes: &[u8],
323        payload_size: usize,
324    ) -> deserialize::Result<serde_json::Value> {
325        if bytes.len() < payload_size {
326            return Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Expected payload of size {0}, but got {1}",
                payload_size, bytes.len()))
    })format!(
327                "Expected payload of size {}, but got {}",
328                payload_size,
329                bytes.len()
330            )
331            .into());
332        }
333
334        let float_str = std::str::from_utf8(bytes).map_err(|_| "Invalid UTF-8 in JSONB float")?;
335        let float_value = serde_json::from_str(float_str)
336            .map_err(|_| "Failed to parse JSONB")
337            .and_then(|v: serde_json::Value| {
338                v.is_f64()
339                    .then_some(v)
340                    .ok_or("Failed to parse JSONB number")
341            })?;
342
343        Ok(float_value)
344    }
345
346    // Read a JSON string
347    pub(super) fn read_jsonb_text(
348        bytes: &[u8],
349        payload_size: usize,
350    ) -> deserialize::Result<serde_json::Value> {
351        if bytes.len() < payload_size {
352            return Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Expected payload of size {0}, but got {1}",
                payload_size, bytes.len()))
    })format!(
353                "Expected payload of size {}, but got {}",
354                payload_size,
355                bytes.len()
356            )
357            .into());
358        }
359
360        let text = std::str::from_utf8(bytes).map_err(|_| "Invalid UTF-8 in JSONB string")?;
361        Ok(serde_json::Value::String(text.to_string()))
362    }
363
364    pub(super) fn read_jsonb_textj(
365        bytes: &[u8],
366        payload_size: usize,
367    ) -> deserialize::Result<serde_json::Value> {
368        if bytes.len() < payload_size {
369            return Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Expected payload of size {0}, but got {1}",
                payload_size, bytes.len()))
    })format!(
370                "Expected payload of size {}, but got {}",
371                payload_size,
372                bytes.len()
373            )
374            .into());
375        }
376
377        let text = std::str::from_utf8(bytes).map_err(|_| "Invalid UTF-8 in JSONB string")?;
378
379        // Unescape JSON escape sequences (e.g., "\n", "\u0020")
380        let unescaped_text = serde_json::from_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("\"{0}\"", text))
    })format!("\"{text}\""))
381            .map_err(|_| "Failed to parse JSON-escaped text in TEXTJ")?;
382
383        Ok(unescaped_text)
384    }
385
386    enum JsonValuePtr<'a> {
387        Value(&'a serde_json::Value),
388        Array {
389            values: &'a [serde_json::Value],
390            serialized_buffer: Vec<u8>,
391        },
392        Object {
393            object: &'a serde_json::value::Map<String, serde_json::Value>,
394            keys: Box<dyn Iterator<Item = &'a String> + 'a>,
395            serialized_buffer: Vec<u8>,
396        },
397    }
398
399    pub(super) fn write_jsonb_header(
400        buffer: &mut Vec<u8>,
401        element_type: u8,
402        payload_size: usize,
403    ) -> serialize::Result {
404        // Check if payload size exceeds the maximum allowed size
405        if payload_size > 2_147_483_647 {
406            return Err("Payload size exceeds the maximum allowed size of 2GB".into());
407        }
408
409        if payload_size <= 0x0B {
410            // Small payloads, 0 additional byte for size
411            buffer.push(
412                ((u8::try_from(payload_size).map_err(|e| e.to_string())?) << 4) | element_type,
413            );
414        } else if payload_size <= 0xFF {
415            // Medium payloads, 1 additional byte for size
416            buffer.extend_from_slice(&[
417                (0x0C << 4) | element_type,
418                u8::try_from(payload_size).map_err(|e| e.to_string())?,
419            ]);
420        } else if payload_size <= 0xFFFF {
421            // Larger payloads, 2 additional bytes for size
422            buffer.push((0x0D << 4) | element_type);
423            buffer.extend_from_slice(
424                &(u16::try_from(payload_size).map_err(|e| e.to_string())?).to_be_bytes(),
425            );
426        } else {
427            // Very large payloads, 4 additional bytes for size (up to 2 GiB)
428            buffer.push((0x0E << 4) | element_type);
429            buffer.extend_from_slice(
430                &(u32::try_from(payload_size).map_err(|e| e.to_string())?).to_be_bytes(),
431            );
432        };
433
434        Ok(IsNull::No)
435    }
436
437    fn place_composite_value(
438        buffer: &mut Vec<u8>,
439        stack: &mut [JsonValuePtr<'_>],
440        serialized_buffer: Vec<u8>,
441        tpe: u8,
442    ) -> serialize::Result {
443        let buffer = match stack.last_mut() {
444            None | Some(JsonValuePtr::Value(_)) => buffer,
445            Some(
446                JsonValuePtr::Array {
447                    serialized_buffer, ..
448                }
449                | JsonValuePtr::Object {
450                    serialized_buffer, ..
451                },
452            ) => serialized_buffer,
453        };
454        write_jsonb_header(buffer, tpe, serialized_buffer.len())?;
455        buffer.extend(serialized_buffer);
456
457        Ok(IsNull::No)
458    }
459
460    // Helper function to write a JSON value into a JSONB binary format
461    pub(super) fn write_jsonb_value(
462        value: &serde_json::Value,
463        buffer: &mut Vec<u8>,
464    ) -> serialize::Result {
465        let mut stack = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [JsonValuePtr::Value(value)]))vec![JsonValuePtr::Value(value)];
466
467        while let Some(value) = stack.pop() {
468            let add_to_stack = match value {
469                JsonValuePtr::Value(value) => write_plain_jsonb_value(buffer, value)?,
470                JsonValuePtr::Array {
471                    values,
472                    mut serialized_buffer,
473                } => {
474                    if let Some((el, tail)) = values.split_first() {
475                        let ret = write_plain_jsonb_value(&mut serialized_buffer, el)?;
476                        stack.push(JsonValuePtr::Array {
477                            values: tail,
478                            serialized_buffer,
479                        });
480                        ret
481                    } else {
482                        place_composite_value(buffer, &mut stack, serialized_buffer, JSONB_ARRAY)?;
483                        None
484                    }
485                }
486                JsonValuePtr::Object {
487                    object,
488                    mut keys,
489                    mut serialized_buffer,
490                } => {
491                    if let Some(next_key) = keys.next() {
492                        let value = object
493                            .get(next_key)
494                            .ok_or_else(|| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Missing value for object key: `{0}`",
                next_key))
    })format!("Missing value for object key: `{next_key}`"))?;
495                        write_jsonb_string(next_key, &mut serialized_buffer)?;
496                        let ret = write_plain_jsonb_value(&mut serialized_buffer, value)?;
497                        stack.push(JsonValuePtr::Object {
498                            object,
499                            keys,
500                            serialized_buffer,
501                        });
502                        ret
503                    } else {
504                        place_composite_value(buffer, &mut stack, serialized_buffer, JSONB_OBJECT)?;
505                        None
506                    }
507                }
508            };
509            if let Some(next) = add_to_stack {
510                stack.push(next);
511            }
512        }
513
514        Ok(IsNull::No)
515    }
516
517    fn write_plain_jsonb_value<'a>(
518        buffer: &mut Vec<u8>,
519        value: &'a serde_json::Value,
520    ) -> Result<Option<JsonValuePtr<'a>>, Box<dyn Error + Send + Sync>> {
521        let ret = if value.is_null() {
522            write_jsonb_null(buffer)?;
523            None
524        } else if value.is_boolean() {
525            write_jsonb_bool(value.as_bool().ok_or("Failed to read JSONB value")?, buffer)?;
526            None
527        } else if value.is_number() {
528            write_jsonb_number(value, buffer)?;
529            None
530        } else if value.is_string() {
531            write_jsonb_string(value.as_str().ok_or("Failed to read JSONB value")?, buffer)?;
532            None
533        } else if value.is_array() {
534            let array = value.as_array().ok_or("Failed to read JSONB value")?;
535            Some(JsonValuePtr::Array {
536                values: array,
537                serialized_buffer: Vec::new(),
538            })
539        } else if value.is_object() {
540            let object = value.as_object().ok_or("Failed to read JSONB value")?;
541            Some(JsonValuePtr::Object {
542                object,
543                keys: Box::new(object.keys()),
544                serialized_buffer: Vec::new(),
545            })
546        } else {
547            return Err("Unsupported JSONB value type".into());
548        };
549        Ok(ret)
550    }
551
552    // Write a JSON null
553    pub(super) fn write_jsonb_null(buffer: &mut Vec<u8>) -> serialize::Result {
554        write_jsonb_header(buffer, JSONB_NULL, 0x0)?;
555        Ok(IsNull::No)
556    }
557
558    // Write a JSON boolean
559    pub(super) fn write_jsonb_bool(b: bool, buffer: &mut Vec<u8>) -> serialize::Result {
560        // Use the constants for true and false
561        write_jsonb_header(buffer, if b { JSONB_TRUE } else { JSONB_FALSE }, 0x0)?;
562        Ok(IsNull::No)
563    }
564
565    // Write a JSON number (integers and floats)
566    pub(super) fn write_jsonb_number(
567        n: &serde_json::Value,
568        buffer: &mut Vec<u8>,
569    ) -> serialize::Result {
570        let n = n.to_string();
571        let tpe = if n
572            .char_indices()
573            .any(|(idx, c)| !(c.is_ascii_digit() || (idx == 0 && (c == '-' || c == '+'))))
574        {
575            JSONB_FLOAT
576        } else {
577            JSONB_INT
578        };
579        write_jsonb_header(buffer, tpe, n.len())?;
580
581        // Write the ASCII text representation of the integer/float as the payload
582        buffer.extend_from_slice(n.as_bytes());
583
584        Ok(IsNull::No)
585    }
586
587    pub(super) fn write_jsonb_string(s: &str, buffer: &mut Vec<u8>) -> serialize::Result {
588        if s.chars().any(|c| c.is_control()) {
589            // If the string contains control characters, treat it as TEXTJ (escaped JSON)
590            write_jsonb_textj(s, buffer)
591        } else {
592            write_jsonb_header(buffer, JSONB_TEXT, s.len())?;
593            // Write the UTF-8 text of the string as the payload (no delimiters)
594            buffer.extend_from_slice(s.as_bytes());
595            Ok(IsNull::No)
596        }
597    }
598
599    pub(super) fn write_jsonb_textj(s: &str, buffer: &mut Vec<u8>) -> serialize::Result {
600        // Escaping the string for JSON (e.g., \n, \uXXXX)
601        let escaped_string = serde_json::to_string(&String::from(s))
602            .map_err(|_| "Failed to serialize string for TEXTJ")?;
603
604        // Remove the surrounding quotes from serde_json::to_string result
605        let escaped_string = &escaped_string[1..escaped_string.len() - 1];
606
607        // Write the header (JSONB_TEXTJ) and the length of the escaped string
608        write_jsonb_header(buffer, JSONB_TEXTJ, escaped_string.len())?;
609
610        // Write the escaped string as the payload
611        buffer.extend_from_slice(escaped_string.as_bytes());
612
613        Ok(IsNull::No)
614    }
615}
616
617#[cfg(test)]
618#[cfg(all(feature = "sqlite", feature = "serde_json"))]
619mod tests {
620    use super::jsonb::*;
621    use super::*;
622    #[cfg(not(miri))] // ffi call
623    use crate::query_dsl::RunQueryDsl;
624    #[cfg(not(miri))] // ffi call
625    use crate::test_helpers::connection;
626    use crate::test_helpers::format_error;
627    #[cfg(not(miri))] // ffi call
628    use crate::ExpressionMethods;
629    #[cfg(not(miri))] // ffi call
630    use crate::{dsl::sql, IntoSql};
631    use serde_json::{json, Value};
632    use sql_types::{Json, Jsonb};
633
634    // Helper function to create the correct JsonbHeader based on the payload size
635    pub(super) fn create_jsonb_header(
636        element_type: u8,
637        payload_size: usize,
638    ) -> Result<Vec<u8>, Box<dyn core::error::Error + Send + Sync>> {
639        let mut buffer = Vec::new();
640        jsonb::write_jsonb_header(&mut buffer, element_type, payload_size)?;
641        Ok(buffer)
642    }
643
644    #[diesel_test_helper::test]
645    #[cfg(not(miri))] // ffi call
646    fn regression_float_without_a_fraction_is_written_invalid() {
647        let conn = &mut connection();
648        for value in [
649            json!(3.0),
650            json!(-0.0),
651            json!(1.5e300),
652            // an exponent and no fraction digit, so the text carries no `.`
653            json!(1e-7),
654            json!(1e300),
655        ] {
656            let blob = diesel::select(sql::<sql_types::Binary>("").bind::<Jsonb, _>(value.clone()))
657                .get_result::<Vec<u8>>(conn)
658                .unwrap();
659            let valid = diesel::select(
660                sql::<sql_types::Integer>("json_valid(")
661                    .bind::<sql_types::Binary, _>(blob.clone())
662                    .sql(", 8)"),
663            )
664            .get_result::<i32>(conn)
665            .unwrap();
666            assert_eq!(
667                valid, 1,
668                "sqlite rejects the blob written for {value}: {blob:02X?}"
669            );
670            let back = diesel::select(sql::<Jsonb>("").bind::<sql_types::Binary, _>(blob.clone()))
671                .get_result::<Value>(conn)
672                .unwrap_or_else(|error| panic!("{value} does not read back: {error}"));
673            assert_eq!(back, value, "{blob:02X?}");
674        }
675    }
676    #[diesel_test_helper::test]
677    #[cfg(not(miri))] // ffi call
678    fn json_to_sql() {
679        let conn = &mut connection();
680        let res = diesel::select(json!(true).into_sql::<Json>().eq(&sql("json('true')")))
681            .get_result::<bool>(conn)
682            .unwrap();
683        assert!(res);
684    }
685
686    #[diesel_test_helper::test]
687    fn test_read_jsonb_null() {
688        let data = vec![JSONB_NULL];
689        let result = read_jsonb_value(&data).unwrap().0;
690        assert_eq!(result, Value::Null);
691    }
692
693    #[diesel_test_helper::test]
694    fn test_read_jsonb_true() {
695        let data = vec![JSONB_TRUE];
696        let result = read_jsonb_value(&data).unwrap().0;
697        assert_eq!(result, Value::Bool(true));
698    }
699
700    #[diesel_test_helper::test]
701    fn test_read_jsonb_false() {
702        let data = vec![JSONB_FALSE];
703        let result = read_jsonb_value(&data).unwrap().0;
704        assert_eq!(result, Value::Bool(false));
705    }
706
707    #[diesel_test_helper::test]
708    fn test_read_jsonb_int() {
709        // JSONB_INT with payload "1"
710        let mut data = Vec::new();
711        data.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
712        data.push(b'1'); // Add the payload (integer "1")
713
714        let result = read_jsonb_value(&data).unwrap().0;
715        assert_eq!(result, json!(1));
716    }
717
718    #[diesel_test_helper::test]
719    fn test_read_jsonb_float() {
720        // JSONB_FLOAT with payload "1.5"
721        let mut data = Vec::new();
722        data.extend(create_jsonb_header(JSONB_FLOAT, 0x03).unwrap());
723        data.extend_from_slice(b"1.5"); // Add the payload (float "1.5")
724
725        let result = read_jsonb_value(&data).unwrap().0;
726        assert_eq!(result, json!(1.5));
727    }
728
729    #[diesel_test_helper::test]
730    fn test_read_jsonb_text() {
731        // JSONB_TEXT with payload "foo"
732        let mut data = Vec::new();
733        data.extend(create_jsonb_header(JSONB_TEXT, 0x03).unwrap());
734        data.extend_from_slice(b"foo"); // Add the payload (text "foo")
735
736        let result = read_jsonb_value(&data).unwrap().0;
737        assert_eq!(result, json!("foo"));
738    }
739
740    #[diesel_test_helper::test]
741    fn test_read_jsonb_textraw() {
742        // JSONB_TEXTRAW with payload "foo"
743        let mut data = Vec::new();
744        data.extend(create_jsonb_header(JSONB_TEXTRAW, 0x03).unwrap());
745        data.extend_from_slice(b"foo");
746
747        let result = read_jsonb_value(&data).unwrap().0;
748        assert_eq!(result, json!("foo"));
749    }
750
751    #[diesel_test_helper::test]
752    fn test_read_jsonb_object_with_textraw_key() {
753        // JSONB_OBJECT with a TEXTRAW key and value
754        let mut data = Vec::new();
755        data.extend(create_jsonb_header(JSONB_OBJECT, 0x06).unwrap());
756        data.extend(create_jsonb_header(JSONB_TEXTRAW, 0x01).unwrap());
757        data.extend_from_slice(b"a");
758        data.extend(create_jsonb_header(JSONB_TEXTRAW, 0x03).unwrap());
759        data.extend_from_slice(b"bar");
760
761        let result = read_jsonb_value(&data).unwrap().0;
762        assert_eq!(result, json!({"a": "bar"}));
763    }
764
765    #[diesel_test_helper::test]
766    fn test_read_jsonb_array() {
767        // JSONB_ARRAY with two elements: 1 and true
768        let mut data = Vec::new();
769        data.extend(create_jsonb_header(JSONB_ARRAY, 0x03).unwrap()); // Array header
770
771        // Element 1: integer "1"
772        data.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
773        data.push(b'1');
774
775        // Element 2: true
776        data.extend(create_jsonb_header(JSONB_TRUE, 0x00).unwrap());
777
778        let result = read_jsonb_value(&data).unwrap().0;
779        assert_eq!(result, json!([1, true]));
780    }
781
782    #[diesel_test_helper::test]
783    fn test_read_jsonb_object() {
784        // JSONB_OBJECT with one key-value pair: "key": 42
785        let mut data = Vec::new();
786        data.extend(create_jsonb_header(JSONB_OBJECT, 0x07).unwrap()); // Object header
787
788        // Key: "key"
789        data.extend(create_jsonb_header(JSONB_TEXT, 0x03).unwrap());
790        data.extend_from_slice(b"key"); // Add the key payload
791
792        // Value: 42 (integer)
793        data.extend(create_jsonb_header(JSONB_INT, 0x02).unwrap());
794        data.extend_from_slice(b"42"); // Add the integer payload
795
796        let result = read_jsonb_value(&data).unwrap().0;
797        assert_eq!(result, json!({"key": 42}));
798    }
799
800    #[diesel_test_helper::test]
801    fn test_read_jsonb_nested_object() {
802        let mut data = Vec::new();
803
804        data.extend(create_jsonb_header(JSONB_OBJECT, 42).unwrap());
805
806        data.extend(create_jsonb_header(JSONB_TEXT, 9).unwrap());
807        data.extend_from_slice(b"outer_key");
808
809        data.extend(create_jsonb_header(JSONB_OBJECT, 13).unwrap());
810
811        data.extend(create_jsonb_header(JSONB_TEXT, 9).unwrap());
812        data.extend_from_slice(b"inner_key");
813
814        data.extend(create_jsonb_header(JSONB_INT, 2).unwrap());
815        data.extend_from_slice(b"42");
816
817        data.extend(create_jsonb_header(JSONB_TEXT, 14).unwrap());
818        data.extend_from_slice(b"additional_key");
819
820        data.extend(create_jsonb_header(JSONB_TRUE, 0).unwrap());
821
822        let result = read_jsonb_value(&data).unwrap().0;
823        assert_eq!(
824            result,
825            json!({
826                "additional_key": true,
827                "outer_key": {
828                    "inner_key": 42
829                },
830            })
831        );
832    }
833
834    #[diesel_test_helper::test]
835    fn test_write_jsonb_null() {
836        let value = serde_json::Value::Null;
837        let mut buffer = Vec::new();
838        write_jsonb_value(&value, &mut buffer).unwrap();
839        assert_eq!(buffer, vec![JSONB_NULL]);
840    }
841
842    #[diesel_test_helper::test]
843    fn test_write_jsonb_true() {
844        let value = serde_json::Value::Bool(true);
845        let mut buffer = Vec::new();
846        write_jsonb_value(&value, &mut buffer).unwrap();
847        assert_eq!(buffer, vec![JSONB_TRUE]);
848    }
849
850    #[diesel_test_helper::test]
851    fn test_write_jsonb_false() {
852        let value = serde_json::Value::Bool(false);
853        let mut buffer = Vec::new();
854        write_jsonb_value(&value, &mut buffer).unwrap();
855        assert_eq!(buffer, vec![JSONB_FALSE]);
856    }
857
858    #[diesel_test_helper::test]
859    fn test_write_jsonb_int() {
860        let value = serde_json::Value::Number(serde_json::Number::from(1));
861        let mut buffer = Vec::new();
862        write_jsonb_value(&value, &mut buffer).unwrap();
863
864        let mut expected_buffer = Vec::new();
865        expected_buffer.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
866        expected_buffer.push(b'1'); // Payload: integer "1"
867
868        assert_eq!(buffer, expected_buffer);
869    }
870
871    #[diesel_test_helper::test]
872    fn test_write_jsonb_float() {
873        let value = serde_json::Value::Number(serde_json::Number::from_f64(1.5).unwrap());
874        let mut buffer = Vec::new();
875        write_jsonb_value(&value, &mut buffer).unwrap();
876
877        let mut expected_buffer = Vec::new();
878        expected_buffer.extend(create_jsonb_header(JSONB_FLOAT, 0x03).unwrap());
879        expected_buffer.extend_from_slice(b"1.5"); // Payload: float "1.5"
880
881        assert_eq!(buffer, expected_buffer);
882    }
883
884    #[diesel_test_helper::test]
885    fn test_write_jsonb_text() {
886        let mut buffer = Vec::new();
887        let input_string = "hello";
888        write_jsonb_string(input_string, &mut buffer).unwrap();
889
890        let mut expected_buffer = Vec::new();
891        expected_buffer.extend(create_jsonb_header(JSONB_TEXT, 0x05).unwrap());
892        expected_buffer.extend_from_slice(b"hello");
893
894        assert_eq!(buffer, expected_buffer);
895    }
896
897    #[diesel_test_helper::test]
898    fn test_write_jsonb_textj() {
899        let mut buffer = Vec::new();
900        let input_string = "hello\nworld"; // Contains a newline, requires escaping
901        write_jsonb_string(input_string, &mut buffer).unwrap();
902
903        let mut expected_buffer = Vec::new();
904        expected_buffer.extend(create_jsonb_header(JSONB_TEXTJ, 12).unwrap());
905        expected_buffer.extend_from_slice(b"hello\\nworld");
906
907        assert_eq!(buffer, expected_buffer);
908    }
909
910    #[diesel_test_helper::test]
911    fn test_write_jsonb_array() {
912        let value = json!([1, true]);
913        let mut buffer = Vec::new();
914        write_jsonb_value(&value, &mut buffer).unwrap();
915
916        let mut expected_buffer = Vec::new();
917        expected_buffer.extend(create_jsonb_header(JSONB_ARRAY, 0x03).unwrap()); // Array header
918        expected_buffer.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap()); // Integer header
919        expected_buffer.push(b'1'); // Integer payload "1"
920        expected_buffer.extend(create_jsonb_header(JSONB_TRUE, 0x00).unwrap()); // Boolean header for "true"
921
922        assert_eq!(buffer, expected_buffer);
923    }
924
925    #[diesel_test_helper::test]
926    fn test_write_jsonb_object() {
927        let value = json!({"key": 42});
928        let mut buffer = Vec::new();
929        write_jsonb_value(&value, &mut buffer).unwrap();
930
931        let mut expected = Vec::new();
932        expected.extend(create_jsonb_header(JSONB_OBJECT, 7).unwrap());
933        expected.extend(create_jsonb_header(JSONB_TEXT, 3).unwrap());
934        expected.extend_from_slice(b"key");
935        expected.extend(create_jsonb_header(JSONB_INT, 2).unwrap());
936        expected.extend_from_slice(b"42");
937
938        assert_eq!(buffer, expected,);
939    }
940
941    #[diesel_test_helper::test]
942    #[cfg(not(miri))] // ffi call
943    fn jsonb_to_sql_bool() {
944        let conn = &mut connection();
945        let res = diesel::select(json!(true).into_sql::<Jsonb>().eq(&sql("jsonb('true')")))
946            .get_result::<bool>(conn)
947            .unwrap();
948        assert!(res);
949    }
950
951    #[diesel_test_helper::test]
952    #[cfg(not(miri))] // ffi call
953    fn jsonb_to_sql_null() {
954        let conn = &mut connection();
955        let res = diesel::select(json!(null).into_sql::<Jsonb>().eq(&sql("jsonb('null')")))
956            .get_result::<bool>(conn)
957            .unwrap();
958        assert!(res);
959    }
960
961    #[diesel_test_helper::test]
962    #[cfg(not(miri))] // ffi call
963    fn jsonb_to_sql_integer() {
964        let conn = &mut connection();
965        let res = diesel::select(json!(42).into_sql::<Jsonb>().eq(&sql("jsonb('42')")))
966            .get_result::<bool>(conn)
967            .unwrap();
968        assert!(res);
969    }
970
971    #[diesel_test_helper::test]
972    #[cfg(not(miri))] // ffi call
973    fn jsonb_to_sql_float() {
974        let conn = &mut connection();
975        let res = diesel::select(json!(42.23).into_sql::<Jsonb>().eq(&sql("jsonb('42.23')")))
976            .get_result::<bool>(conn)
977            .unwrap();
978        assert!(res);
979    }
980
981    #[diesel_test_helper::test]
982    #[cfg(not(miri))] // ffi call
983    fn jsonb_to_sql_text() {
984        let conn = &mut connection();
985
986        // Test for TEXT (simple string)
987        let res = diesel::select(
988            json!("hello")
989                .into_sql::<Jsonb>()
990                .eq(&sql("jsonb('\"hello\"')")),
991        )
992        .get_result::<bool>(conn)
993        .unwrap();
994
995        assert!(res);
996    }
997
998    #[diesel_test_helper::test]
999    #[cfg(not(miri))] // ffi call
1000    fn jsonb_to_sql_textj() {
1001        let conn = &mut connection();
1002
1003        // Test for TEXTJ (JSON-escaped string, e.g., containing \n or \uXXXX)
1004        let res = diesel::select(
1005            json!("hello\nworld")
1006                .into_sql::<Jsonb>()
1007                .eq(&sql("jsonb('\"hello\\nworld\"')")), // The string is JSON-escaped
1008        )
1009        .get_result::<bool>(conn)
1010        .unwrap();
1011
1012        assert!(res);
1013    }
1014
1015    #[diesel_test_helper::test]
1016    #[cfg(not(miri))] // ffi call
1017    fn jsonb_to_sql_array() {
1018        let conn = &mut connection();
1019        let res = diesel::select(
1020            json!([1, true, "foo"])
1021                .into_sql::<Jsonb>()
1022                .eq(&sql("jsonb('[1, true, \"foo\"]')")),
1023        )
1024        .get_result::<bool>(conn)
1025        .unwrap();
1026        assert!(res);
1027    }
1028
1029    #[diesel_test_helper::test]
1030    #[cfg(not(miri))] // ffi call
1031    fn jsonb_to_sql_object() {
1032        let conn = &mut connection();
1033        let res = diesel::select(
1034            json!({"key": "value"})
1035                .into_sql::<Jsonb>()
1036                .eq(&sql("jsonb('{\"key\": \"value\"}')")),
1037        )
1038        .get_result::<bool>(conn)
1039        .unwrap();
1040        assert!(res);
1041    }
1042
1043    #[diesel_test_helper::test]
1044    #[cfg(not(miri))] // ffi call
1045    fn jsonb_to_sql_object_in_object() {
1046        let conn = &mut connection();
1047        let json_value = json!({
1048            "outer_key": {
1049                "additional_key": true,
1050                "inner_key": {
1051                    "nested_key": 42
1052                },
1053            }
1054        });
1055
1056        let res = diesel::select(json_value.into_sql::<Jsonb>().eq(&sql(
1057            r#"jsonb('{"outer_key": {"additional_key": true, "inner_key": {"nested_key": 42}}}')"#,
1058        )))
1059        .get_result::<bool>(conn)
1060        .unwrap();
1061        assert!(res);
1062    }
1063
1064    #[diesel_test_helper::test]
1065    #[cfg(not(miri))] // ffi call
1066    fn jsonb_to_sql_array_in_object() {
1067        let conn = &mut connection();
1068        let json_value = json!({
1069            "is_valid": false,
1070            "key": [1, 2, 3],
1071        });
1072        let res = diesel::select(
1073            json_value
1074                .into_sql::<Jsonb>()
1075                .eq(&sql(r#"jsonb('{"is_valid": false, "key": [1, 2, 3]}')"#)),
1076        )
1077        .get_result::<bool>(conn)
1078        .unwrap();
1079        assert!(res);
1080    }
1081
1082    #[diesel_test_helper::test]
1083    #[cfg(not(miri))] // ffi call
1084    fn jsonb_to_sql_object_in_array() {
1085        let conn = &mut connection();
1086        let json_value = json!([
1087            {
1088                "nested_key": "nested_value"
1089            },
1090            {
1091                "int_value": 99
1092            }
1093        ]);
1094        let res = diesel::select(json_value.into_sql::<Jsonb>().eq(&sql(
1095            r#"jsonb('[{"nested_key": "nested_value"}, {"int_value": 99}]')"#,
1096        )))
1097        .get_result::<bool>(conn)
1098        .unwrap();
1099        assert!(res);
1100    }
1101
1102    #[diesel_test_helper::test]
1103    #[cfg(not(miri))] // ffi call
1104    fn jsonb_from_sql_null() {
1105        let conn = &mut connection();
1106        let res = diesel::select(sql::<Jsonb>("jsonb('null')"))
1107            .get_result::<serde_json::Value>(conn)
1108            .unwrap();
1109        assert_eq!(res, serde_json::json!(null));
1110    }
1111
1112    #[diesel_test_helper::test]
1113    #[cfg(not(miri))] // ffi call
1114    fn jsonb_from_sql_true() {
1115        let conn = &mut connection();
1116        let res = diesel::select(sql::<Jsonb>("jsonb('true')"))
1117            .get_result::<serde_json::Value>(conn)
1118            .unwrap();
1119        assert_eq!(res, serde_json::json!(true));
1120    }
1121
1122    #[diesel_test_helper::test]
1123    #[cfg(not(miri))] // ffi call
1124    fn jsonb_from_sql_false() {
1125        let conn = &mut connection();
1126        let res = diesel::select(sql::<Jsonb>("jsonb('false')"))
1127            .get_result::<serde_json::Value>(conn)
1128            .unwrap();
1129        assert_eq!(res, serde_json::json!(false));
1130    }
1131
1132    #[diesel_test_helper::test]
1133    #[cfg(not(miri))] // ffi call
1134    fn jsonb_from_sql_int() {
1135        let conn = &mut connection();
1136        let res = diesel::select(sql::<Jsonb>("jsonb('42')"))
1137            .get_result::<serde_json::Value>(conn)
1138            .unwrap();
1139        assert_eq!(res, serde_json::json!(42));
1140    }
1141
1142    #[diesel_test_helper::test]
1143    #[cfg(not(miri))] // ffi call
1144    fn jsonb_from_sql_float() {
1145        let conn = &mut connection();
1146        let res = diesel::select(sql::<Jsonb>("jsonb('42.23')"))
1147            .get_result::<serde_json::Value>(conn)
1148            .unwrap();
1149        assert_eq!(res, serde_json::json!(42.23));
1150    }
1151
1152    #[diesel_test_helper::test]
1153    #[cfg(not(miri))] // ffi call
1154    fn jsonb_from_sql_object() {
1155        let conn = &mut connection();
1156        let res = diesel::select(sql::<Jsonb>("jsonb('{\"key\": \"value\"}')"))
1157            .get_result::<serde_json::Value>(conn)
1158            .unwrap();
1159        assert_eq!(res, serde_json::json!({"key": "value"}));
1160    }
1161
1162    #[diesel_test_helper::test]
1163    #[cfg(not(miri))] // ffi call
1164    fn jsonb_from_sql_array() {
1165        let conn = &mut connection();
1166        let res = diesel::select(sql::<Jsonb>("jsonb('[1, 2, 3]')"))
1167            .get_result::<serde_json::Value>(conn)
1168            .unwrap();
1169        assert_eq!(res, serde_json::json!([1, 2, 3]));
1170    }
1171
1172    #[diesel_test_helper::test]
1173    #[cfg(not(miri))] // ffi call
1174    fn jsonb_from_sql_nested_objects() {
1175        let conn = &mut connection();
1176        let res = diesel::select(sql::<Jsonb>("jsonb('{\"outer\": {\"inner\": 42}}')"))
1177            .get_result::<serde_json::Value>(conn)
1178            .unwrap();
1179        assert_eq!(res, serde_json::json!({"outer": {"inner": 42}}));
1180    }
1181
1182    #[diesel_test_helper::test]
1183    #[cfg(not(miri))] // ffi call
1184    fn jsonb_from_sql_nested_arrays() {
1185        let conn = &mut connection();
1186        let res = diesel::select(sql::<Jsonb>("jsonb('[[1, 2], [3, 4]]')"))
1187            .get_result::<serde_json::Value>(conn)
1188            .unwrap();
1189        assert_eq!(res, serde_json::json!([[1, 2], [3, 4]]));
1190    }
1191
1192    #[diesel_test_helper::test]
1193    #[cfg(not(miri))] // ffi call
1194    fn jsonb_from_sql_nested_arrays_in_objects() {
1195        let conn = &mut connection();
1196        let res = diesel::select(sql::<Jsonb>("jsonb('{\"array\": [1, 2, 3]}')"))
1197            .get_result::<serde_json::Value>(conn)
1198            .unwrap();
1199        assert_eq!(res, serde_json::json!({"array": [1, 2, 3]}));
1200    }
1201
1202    #[diesel_test_helper::test]
1203    #[cfg(not(miri))] // ffi call
1204    fn jsonb_from_sql_nested_objects_in_arrays() {
1205        let conn = &mut connection();
1206        let res = diesel::select(sql::<Jsonb>(
1207            "jsonb('[{\"key1\": \"value1\"}, {\"key2\": \"value2\"}]')",
1208        ))
1209        .get_result::<serde_json::Value>(conn)
1210        .unwrap();
1211        assert_eq!(
1212            res,
1213            serde_json::json!([{"key1": "value1"}, {"key2": "value2"}])
1214        );
1215    }
1216
1217    #[diesel_test_helper::test]
1218    #[cfg(not(miri))] // ffi call
1219    fn jsonb_from_sql_text() {
1220        let conn = &mut connection();
1221        let res = diesel::select(sql::<Jsonb>("jsonb('\"hello\"')"))
1222            .get_result::<serde_json::Value>(conn)
1223            .unwrap();
1224        assert_eq!(res, serde_json::json!("hello"));
1225    }
1226
1227    #[diesel_test_helper::test]
1228    #[cfg(not(miri))] // ffi call
1229    fn jsonb_from_sql_textj() {
1230        let conn = &mut connection();
1231        let res = diesel::select(sql::<Jsonb>("jsonb('\"hello\\nworld\"')"))
1232            .get_result::<serde_json::Value>(conn)
1233            .unwrap();
1234        assert_eq!(res, serde_json::json!("hello\nworld"));
1235    }
1236
1237    #[diesel_test_helper::test]
1238    #[cfg(not(miri))] // ffi call
1239    fn bad_json_from_sql() {
1240        let conn = &mut connection();
1241        let res = diesel::select(json!(true).into_sql::<Json>().eq(&sql("json('boom')")))
1242            .get_result::<bool>(conn);
1243        assert_eq!(format_error(&res.unwrap_err()), "malformed JSON");
1244    }
1245
1246    #[diesel_test_helper::test]
1247    #[cfg(not(miri))] // ffi call
1248    fn bad_jsonb_from_sql() {
1249        let conn = &mut connection();
1250        let res = diesel::select(json!(true).into_sql::<Jsonb>().eq(&sql("jsonb('boom')")))
1251            .get_result::<bool>(conn);
1252        assert_eq!(format_error(&res.unwrap_err()), "malformed JSON");
1253    }
1254
1255    #[diesel_test_helper::test]
1256    fn no_json_from_sql() {
1257        let uuid: Result<serde_json::Value, _> = FromSql::<Json, Sqlite>::from_nullable_sql(None);
1258        assert_eq!(
1259            format_error(&*uuid.unwrap_err()),
1260            "Unexpected null for non-null column"
1261        );
1262    }
1263
1264    #[diesel_test_helper::test]
1265    fn no_jsonb_from_sql() {
1266        let uuid: Result<serde_json::Value, _> = FromSql::<Jsonb, Sqlite>::from_nullable_sql(None);
1267        assert_eq!(
1268            format_error(&*uuid.unwrap_err()),
1269            "Unexpected null for non-null column"
1270        );
1271    }
1272
1273    #[cfg(all(
1274        not(miri),
1275        not(all(target_family = "wasm", target_os = "unknown")),
1276        unix
1277    ))]
1278    const RECURSION_DEPTH: usize = 2000;
1279
1280    #[cfg(all(
1281        not(miri),
1282        any(windows, all(target_family = "wasm", target_os = "unknown"))
1283    ))]
1284    const RECURSION_DEPTH: usize = 1000;
1285
1286    #[cfg(any(
1287        miri,
1288        all(
1289            not(unix),
1290            not(windows),
1291            not(all(target_family = "wasm", target_os = "unknown"))
1292        )
1293    ))]
1294    const RECURSION_DEPTH: usize = 10;
1295
1296    #[diesel_test_helper::test]
1297    fn guard_against_stackoverflow_array() {
1298        let mut value = serde_json::Value::Number(42.into());
1299        for i in 0..RECURSION_DEPTH {
1300            value = serde_json::Value::Array(vec![value, serde_json::Value::Number(i.into())]);
1301        }
1302        // We compare the encoded buffer for both values here
1303        // as serde_json otherwise runs into stackoverflows itself
1304        let mut expected_buffer = Vec::new();
1305        write_jsonb_value(&value, &mut expected_buffer).unwrap();
1306        let res = read_jsonb_value(&expected_buffer).unwrap().0;
1307
1308        let mut buffer = Vec::new();
1309        write_jsonb_value(&res, &mut buffer).unwrap();
1310        assert_eq!(expected_buffer, buffer);
1311    }
1312
1313    #[diesel_test_helper::test]
1314    fn guard_against_stackoverflow_object() {
1315        let mut value = serde_json::Value::Number(42.into());
1316        for i in 0..RECURSION_DEPTH {
1317            let mut map = serde_json::Map::new();
1318            map.insert(format!("key_{i}"), value);
1319            value = serde_json::Value::Object(map);
1320        }
1321
1322        // We compare the encoded buffer for both values here
1323        // as serde_json otherwise runs into stackoverflows itself
1324        let mut expected_buffer = Vec::new();
1325        write_jsonb_value(&value, &mut expected_buffer).unwrap();
1326
1327        let res = read_jsonb_value(&expected_buffer).unwrap().0;
1328
1329        let mut buffer = Vec::new();
1330        write_jsonb_value(&res, &mut buffer).unwrap();
1331        assert_eq!(expected_buffer, buffer);
1332    }
1333
1334    #[diesel_test_helper::test]
1335    fn guard_against_stackoverflow_mixed() {
1336        let mut value = serde_json::Value::Number(42.into());
1337        for i in 0_usize..2000 {
1338            if i.is_multiple_of(2) {
1339                let mut map = serde_json::Map::new();
1340                map.insert(format!("key_{i}"), value);
1341                value = serde_json::Value::Object(map);
1342            } else {
1343                value = serde_json::Value::Array(vec![value]);
1344            }
1345        }
1346        // We compare the encoded buffer for both values here
1347        // as serde_json otherwise runs into stackoverflows itself
1348        let mut expected_buffer = Vec::new();
1349        write_jsonb_value(&value, &mut expected_buffer).unwrap();
1350        let res = read_jsonb_value(&expected_buffer).unwrap().0;
1351        let mut buffer = Vec::new();
1352        write_jsonb_value(&res, &mut buffer).unwrap();
1353        assert_eq!(expected_buffer, buffer);
1354    }
1355
1356    #[diesel_test_helper::test]
1357    #[cfg(not(miri))] // ffi call
1358    fn dangling_bytes_result_in_error() {
1359        let mut value = Vec::<u8>::new();
1360        value.extend(create_jsonb_header(JSONB_INT, 1).unwrap());
1361        value.push(b'1');
1362        value.push(42);
1363        assert_eq!(value.len(), 3);
1364        let conn = &mut connection();
1365        let res = diesel::select(
1366            crate::dsl::sql::<sql_types::Jsonb>("jsonb(?)").bind::<sql_types::Binary, _>(value),
1367        )
1368        .get_result::<serde_json::Value>(conn);
1369        assert!(res.is_err(), "{:?}", res.unwrap());
1370    }
1371
1372    #[diesel_test_helper::test]
1373    fn object_key_without_value_results_in_error() {
1374        let mut value = Vec::new();
1375        value.extend(create_jsonb_header(JSONB_OBJECT, 2).unwrap());
1376        value.extend(create_jsonb_header(JSONB_TEXT, 1).unwrap());
1377        value.push(b'a');
1378        let res = read_jsonb_value(&value);
1379        assert!(res.is_err(), "{:?}", res.unwrap());
1380    }
1381
1382    #[diesel_test_helper::test]
1383    fn check_invalid_size_header() {
1384        // 9-byte JSONB blob: first byte 0xFB (size_hint nibble = 0x0F),
1385        // bytes 1..9 = 0xFF -> encoded payload length = u64::MAX.
1386        let res = read_jsonb_value(&[0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
1387        assert!(res.is_err());
1388    }
1389
1390    #[diesel_test_helper::test]
1391    fn nested_container_cannot_cross_parent_boundary() {
1392        let res = read_jsonb_value(&[0x3B, 0x1B, 0x1B, JSONB_NULL]);
1393        assert!(res.is_err(), "{:?}", res.unwrap());
1394    }
1395
1396    #[diesel_test_helper::test]
1397    fn check_signed_integer() {
1398        let mut buf = Vec::new();
1399        write_jsonb_value(&json!(-42), &mut buf).unwrap();
1400        let mut expected = create_jsonb_header(JSONB_INT, 3).unwrap();
1401        expected.extend(b"-42");
1402        assert_eq!(buf, expected);
1403    }
1404}