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    #[cfg(not(miri))] // ffi call
627    use crate::ExpressionMethods;
628    #[cfg(not(miri))] // ffi call
629    use crate::{dsl::sql, IntoSql};
630    use serde_json::{json, Value};
631    use sql_types::{Json, Jsonb};
632
633    // Helper function to create the correct JsonbHeader based on the payload size
634    pub(super) fn create_jsonb_header(
635        element_type: u8,
636        payload_size: usize,
637    ) -> Result<Vec<u8>, Box<dyn core::error::Error + Send + Sync>> {
638        let mut buffer = Vec::new();
639        jsonb::write_jsonb_header(&mut buffer, element_type, payload_size)?;
640        Ok(buffer)
641    }
642
643    #[diesel_test_helper::test]
644    #[cfg(not(miri))] // ffi call
645    fn regression_float_without_a_fraction_is_written_invalid() {
646        let conn = &mut connection();
647        for value in [
648            json!(3.0),
649            json!(-0.0),
650            json!(1.5e300),
651            // an exponent and no fraction digit, so the text carries no `.`
652            json!(1e-7),
653            json!(1e300),
654        ] {
655            let blob = diesel::select(sql::<sql_types::Binary>("").bind::<Jsonb, _>(value.clone()))
656                .get_result::<Vec<u8>>(conn)
657                .unwrap();
658            let valid = diesel::select(
659                sql::<sql_types::Integer>("json_valid(")
660                    .bind::<sql_types::Binary, _>(blob.clone())
661                    .sql(", 8)"),
662            )
663            .get_result::<i32>(conn)
664            .unwrap();
665            assert_eq!(
666                valid, 1,
667                "sqlite rejects the blob written for {value}: {blob:02X?}"
668            );
669            let back = diesel::select(sql::<Jsonb>("").bind::<sql_types::Binary, _>(blob.clone()))
670                .get_result::<Value>(conn)
671                .unwrap_or_else(|error| panic!("{value} does not read back: {error}"));
672            assert_eq!(back, value, "{blob:02X?}");
673        }
674    }
675    #[diesel_test_helper::test]
676    #[cfg(not(miri))] // ffi call
677    fn json_to_sql() {
678        let conn = &mut connection();
679        let res = diesel::select(json!(true).into_sql::<Json>().eq(&sql("json('true')")))
680            .get_result::<bool>(conn)
681            .unwrap();
682        assert!(res);
683    }
684
685    #[diesel_test_helper::test]
686    fn test_read_jsonb_null() {
687        let data = vec![JSONB_NULL];
688        let result = read_jsonb_value(&data).unwrap().0;
689        assert_eq!(result, Value::Null);
690    }
691
692    #[diesel_test_helper::test]
693    fn test_read_jsonb_true() {
694        let data = vec![JSONB_TRUE];
695        let result = read_jsonb_value(&data).unwrap().0;
696        assert_eq!(result, Value::Bool(true));
697    }
698
699    #[diesel_test_helper::test]
700    fn test_read_jsonb_false() {
701        let data = vec![JSONB_FALSE];
702        let result = read_jsonb_value(&data).unwrap().0;
703        assert_eq!(result, Value::Bool(false));
704    }
705
706    #[diesel_test_helper::test]
707    fn test_read_jsonb_int() {
708        // JSONB_INT with payload "1"
709        let mut data = Vec::new();
710        data.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
711        data.push(b'1'); // Add the payload (integer "1")
712
713        let result = read_jsonb_value(&data).unwrap().0;
714        assert_eq!(result, json!(1));
715    }
716
717    #[diesel_test_helper::test]
718    fn test_read_jsonb_float() {
719        // JSONB_FLOAT with payload "1.5"
720        let mut data = Vec::new();
721        data.extend(create_jsonb_header(JSONB_FLOAT, 0x03).unwrap());
722        data.extend_from_slice(b"1.5"); // Add the payload (float "1.5")
723
724        let result = read_jsonb_value(&data).unwrap().0;
725        assert_eq!(result, json!(1.5));
726    }
727
728    #[diesel_test_helper::test]
729    fn test_read_jsonb_text() {
730        // JSONB_TEXT with payload "foo"
731        let mut data = Vec::new();
732        data.extend(create_jsonb_header(JSONB_TEXT, 0x03).unwrap());
733        data.extend_from_slice(b"foo"); // Add the payload (text "foo")
734
735        let result = read_jsonb_value(&data).unwrap().0;
736        assert_eq!(result, json!("foo"));
737    }
738
739    #[diesel_test_helper::test]
740    fn test_read_jsonb_textraw() {
741        // JSONB_TEXTRAW with payload "foo"
742        let mut data = Vec::new();
743        data.extend(create_jsonb_header(JSONB_TEXTRAW, 0x03).unwrap());
744        data.extend_from_slice(b"foo");
745
746        let result = read_jsonb_value(&data).unwrap().0;
747        assert_eq!(result, json!("foo"));
748    }
749
750    #[diesel_test_helper::test]
751    fn test_read_jsonb_object_with_textraw_key() {
752        // JSONB_OBJECT with a TEXTRAW key and value
753        let mut data = Vec::new();
754        data.extend(create_jsonb_header(JSONB_OBJECT, 0x06).unwrap());
755        data.extend(create_jsonb_header(JSONB_TEXTRAW, 0x01).unwrap());
756        data.extend_from_slice(b"a");
757        data.extend(create_jsonb_header(JSONB_TEXTRAW, 0x03).unwrap());
758        data.extend_from_slice(b"bar");
759
760        let result = read_jsonb_value(&data).unwrap().0;
761        assert_eq!(result, json!({"a": "bar"}));
762    }
763
764    #[diesel_test_helper::test]
765    fn test_read_jsonb_array() {
766        // JSONB_ARRAY with two elements: 1 and true
767        let mut data = Vec::new();
768        data.extend(create_jsonb_header(JSONB_ARRAY, 0x03).unwrap()); // Array header
769
770        // Element 1: integer "1"
771        data.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
772        data.push(b'1');
773
774        // Element 2: true
775        data.extend(create_jsonb_header(JSONB_TRUE, 0x00).unwrap());
776
777        let result = read_jsonb_value(&data).unwrap().0;
778        assert_eq!(result, json!([1, true]));
779    }
780
781    #[diesel_test_helper::test]
782    fn test_read_jsonb_object() {
783        // JSONB_OBJECT with one key-value pair: "key": 42
784        let mut data = Vec::new();
785        data.extend(create_jsonb_header(JSONB_OBJECT, 0x07).unwrap()); // Object header
786
787        // Key: "key"
788        data.extend(create_jsonb_header(JSONB_TEXT, 0x03).unwrap());
789        data.extend_from_slice(b"key"); // Add the key payload
790
791        // Value: 42 (integer)
792        data.extend(create_jsonb_header(JSONB_INT, 0x02).unwrap());
793        data.extend_from_slice(b"42"); // Add the integer payload
794
795        let result = read_jsonb_value(&data).unwrap().0;
796        assert_eq!(result, json!({"key": 42}));
797    }
798
799    #[diesel_test_helper::test]
800    fn test_read_jsonb_nested_object() {
801        let mut data = Vec::new();
802
803        data.extend(create_jsonb_header(JSONB_OBJECT, 42).unwrap());
804
805        data.extend(create_jsonb_header(JSONB_TEXT, 9).unwrap());
806        data.extend_from_slice(b"outer_key");
807
808        data.extend(create_jsonb_header(JSONB_OBJECT, 13).unwrap());
809
810        data.extend(create_jsonb_header(JSONB_TEXT, 9).unwrap());
811        data.extend_from_slice(b"inner_key");
812
813        data.extend(create_jsonb_header(JSONB_INT, 2).unwrap());
814        data.extend_from_slice(b"42");
815
816        data.extend(create_jsonb_header(JSONB_TEXT, 14).unwrap());
817        data.extend_from_slice(b"additional_key");
818
819        data.extend(create_jsonb_header(JSONB_TRUE, 0).unwrap());
820
821        let result = read_jsonb_value(&data).unwrap().0;
822        assert_eq!(
823            result,
824            json!({
825                "additional_key": true,
826                "outer_key": {
827                    "inner_key": 42
828                },
829            })
830        );
831    }
832
833    #[diesel_test_helper::test]
834    fn test_write_jsonb_null() {
835        let value = serde_json::Value::Null;
836        let mut buffer = Vec::new();
837        write_jsonb_value(&value, &mut buffer).unwrap();
838        assert_eq!(buffer, vec![JSONB_NULL]);
839    }
840
841    #[diesel_test_helper::test]
842    fn test_write_jsonb_true() {
843        let value = serde_json::Value::Bool(true);
844        let mut buffer = Vec::new();
845        write_jsonb_value(&value, &mut buffer).unwrap();
846        assert_eq!(buffer, vec![JSONB_TRUE]);
847    }
848
849    #[diesel_test_helper::test]
850    fn test_write_jsonb_false() {
851        let value = serde_json::Value::Bool(false);
852        let mut buffer = Vec::new();
853        write_jsonb_value(&value, &mut buffer).unwrap();
854        assert_eq!(buffer, vec![JSONB_FALSE]);
855    }
856
857    #[diesel_test_helper::test]
858    fn test_write_jsonb_int() {
859        let value = serde_json::Value::Number(serde_json::Number::from(1));
860        let mut buffer = Vec::new();
861        write_jsonb_value(&value, &mut buffer).unwrap();
862
863        let mut expected_buffer = Vec::new();
864        expected_buffer.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
865        expected_buffer.push(b'1'); // Payload: integer "1"
866
867        assert_eq!(buffer, expected_buffer);
868    }
869
870    #[diesel_test_helper::test]
871    fn test_write_jsonb_float() {
872        let value = serde_json::Value::Number(serde_json::Number::from_f64(1.5).unwrap());
873        let mut buffer = Vec::new();
874        write_jsonb_value(&value, &mut buffer).unwrap();
875
876        let mut expected_buffer = Vec::new();
877        expected_buffer.extend(create_jsonb_header(JSONB_FLOAT, 0x03).unwrap());
878        expected_buffer.extend_from_slice(b"1.5"); // Payload: float "1.5"
879
880        assert_eq!(buffer, expected_buffer);
881    }
882
883    #[diesel_test_helper::test]
884    fn test_write_jsonb_text() {
885        let mut buffer = Vec::new();
886        let input_string = "hello";
887        write_jsonb_string(input_string, &mut buffer).unwrap();
888
889        let mut expected_buffer = Vec::new();
890        expected_buffer.extend(create_jsonb_header(JSONB_TEXT, 0x05).unwrap());
891        expected_buffer.extend_from_slice(b"hello");
892
893        assert_eq!(buffer, expected_buffer);
894    }
895
896    #[diesel_test_helper::test]
897    fn test_write_jsonb_textj() {
898        let mut buffer = Vec::new();
899        let input_string = "hello\nworld"; // Contains a newline, requires escaping
900        write_jsonb_string(input_string, &mut buffer).unwrap();
901
902        let mut expected_buffer = Vec::new();
903        expected_buffer.extend(create_jsonb_header(JSONB_TEXTJ, 12).unwrap());
904        expected_buffer.extend_from_slice(b"hello\\nworld");
905
906        assert_eq!(buffer, expected_buffer);
907    }
908
909    #[diesel_test_helper::test]
910    fn test_write_jsonb_array() {
911        let value = json!([1, true]);
912        let mut buffer = Vec::new();
913        write_jsonb_value(&value, &mut buffer).unwrap();
914
915        let mut expected_buffer = Vec::new();
916        expected_buffer.extend(create_jsonb_header(JSONB_ARRAY, 0x03).unwrap()); // Array header
917        expected_buffer.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap()); // Integer header
918        expected_buffer.push(b'1'); // Integer payload "1"
919        expected_buffer.extend(create_jsonb_header(JSONB_TRUE, 0x00).unwrap()); // Boolean header for "true"
920
921        assert_eq!(buffer, expected_buffer);
922    }
923
924    #[diesel_test_helper::test]
925    fn test_write_jsonb_object() {
926        let value = json!({"key": 42});
927        let mut buffer = Vec::new();
928        write_jsonb_value(&value, &mut buffer).unwrap();
929
930        let mut expected = Vec::new();
931        expected.extend(create_jsonb_header(JSONB_OBJECT, 7).unwrap());
932        expected.extend(create_jsonb_header(JSONB_TEXT, 3).unwrap());
933        expected.extend_from_slice(b"key");
934        expected.extend(create_jsonb_header(JSONB_INT, 2).unwrap());
935        expected.extend_from_slice(b"42");
936
937        assert_eq!(buffer, expected,);
938    }
939
940    #[diesel_test_helper::test]
941    #[cfg(not(miri))] // ffi call
942    fn jsonb_to_sql_bool() {
943        let conn = &mut connection();
944        let res = diesel::select(json!(true).into_sql::<Jsonb>().eq(&sql("jsonb('true')")))
945            .get_result::<bool>(conn)
946            .unwrap();
947        assert!(res);
948    }
949
950    #[diesel_test_helper::test]
951    #[cfg(not(miri))] // ffi call
952    fn jsonb_to_sql_null() {
953        let conn = &mut connection();
954        let res = diesel::select(json!(null).into_sql::<Jsonb>().eq(&sql("jsonb('null')")))
955            .get_result::<bool>(conn)
956            .unwrap();
957        assert!(res);
958    }
959
960    #[diesel_test_helper::test]
961    #[cfg(not(miri))] // ffi call
962    fn jsonb_to_sql_integer() {
963        let conn = &mut connection();
964        let res = diesel::select(json!(42).into_sql::<Jsonb>().eq(&sql("jsonb('42')")))
965            .get_result::<bool>(conn)
966            .unwrap();
967        assert!(res);
968    }
969
970    #[diesel_test_helper::test]
971    #[cfg(not(miri))] // ffi call
972    fn jsonb_to_sql_float() {
973        let conn = &mut connection();
974        let res = diesel::select(json!(42.23).into_sql::<Jsonb>().eq(&sql("jsonb('42.23')")))
975            .get_result::<bool>(conn)
976            .unwrap();
977        assert!(res);
978    }
979
980    #[diesel_test_helper::test]
981    #[cfg(not(miri))] // ffi call
982    fn jsonb_to_sql_text() {
983        let conn = &mut connection();
984
985        // Test for TEXT (simple string)
986        let res = diesel::select(
987            json!("hello")
988                .into_sql::<Jsonb>()
989                .eq(&sql("jsonb('\"hello\"')")),
990        )
991        .get_result::<bool>(conn)
992        .unwrap();
993
994        assert!(res);
995    }
996
997    #[diesel_test_helper::test]
998    #[cfg(not(miri))] // ffi call
999    fn jsonb_to_sql_textj() {
1000        let conn = &mut connection();
1001
1002        // Test for TEXTJ (JSON-escaped string, e.g., containing \n or \uXXXX)
1003        let res = diesel::select(
1004            json!("hello\nworld")
1005                .into_sql::<Jsonb>()
1006                .eq(&sql("jsonb('\"hello\\nworld\"')")), // The string is JSON-escaped
1007        )
1008        .get_result::<bool>(conn)
1009        .unwrap();
1010
1011        assert!(res);
1012    }
1013
1014    #[diesel_test_helper::test]
1015    #[cfg(not(miri))] // ffi call
1016    fn jsonb_to_sql_array() {
1017        let conn = &mut connection();
1018        let res = diesel::select(
1019            json!([1, true, "foo"])
1020                .into_sql::<Jsonb>()
1021                .eq(&sql("jsonb('[1, true, \"foo\"]')")),
1022        )
1023        .get_result::<bool>(conn)
1024        .unwrap();
1025        assert!(res);
1026    }
1027
1028    #[diesel_test_helper::test]
1029    #[cfg(not(miri))] // ffi call
1030    fn jsonb_to_sql_object() {
1031        let conn = &mut connection();
1032        let res = diesel::select(
1033            json!({"key": "value"})
1034                .into_sql::<Jsonb>()
1035                .eq(&sql("jsonb('{\"key\": \"value\"}')")),
1036        )
1037        .get_result::<bool>(conn)
1038        .unwrap();
1039        assert!(res);
1040    }
1041
1042    #[diesel_test_helper::test]
1043    #[cfg(not(miri))] // ffi call
1044    fn jsonb_to_sql_object_in_object() {
1045        let conn = &mut connection();
1046        let json_value = json!({
1047            "outer_key": {
1048                "additional_key": true,
1049                "inner_key": {
1050                    "nested_key": 42
1051                },
1052            }
1053        });
1054
1055        let res = diesel::select(json_value.into_sql::<Jsonb>().eq(&sql(
1056            r#"jsonb('{"outer_key": {"additional_key": true, "inner_key": {"nested_key": 42}}}')"#,
1057        )))
1058        .get_result::<bool>(conn)
1059        .unwrap();
1060        assert!(res);
1061    }
1062
1063    #[diesel_test_helper::test]
1064    #[cfg(not(miri))] // ffi call
1065    fn jsonb_to_sql_array_in_object() {
1066        let conn = &mut connection();
1067        let json_value = json!({
1068            "is_valid": false,
1069            "key": [1, 2, 3],
1070        });
1071        let res = diesel::select(
1072            json_value
1073                .into_sql::<Jsonb>()
1074                .eq(&sql(r#"jsonb('{"is_valid": false, "key": [1, 2, 3]}')"#)),
1075        )
1076        .get_result::<bool>(conn)
1077        .unwrap();
1078        assert!(res);
1079    }
1080
1081    #[diesel_test_helper::test]
1082    #[cfg(not(miri))] // ffi call
1083    fn jsonb_to_sql_object_in_array() {
1084        let conn = &mut connection();
1085        let json_value = json!([
1086            {
1087                "nested_key": "nested_value"
1088            },
1089            {
1090                "int_value": 99
1091            }
1092        ]);
1093        let res = diesel::select(json_value.into_sql::<Jsonb>().eq(&sql(
1094            r#"jsonb('[{"nested_key": "nested_value"}, {"int_value": 99}]')"#,
1095        )))
1096        .get_result::<bool>(conn)
1097        .unwrap();
1098        assert!(res);
1099    }
1100
1101    #[diesel_test_helper::test]
1102    #[cfg(not(miri))] // ffi call
1103    fn jsonb_from_sql_null() {
1104        let conn = &mut connection();
1105        let res = diesel::select(sql::<Jsonb>("jsonb('null')"))
1106            .get_result::<serde_json::Value>(conn)
1107            .unwrap();
1108        assert_eq!(res, serde_json::json!(null));
1109    }
1110
1111    #[diesel_test_helper::test]
1112    #[cfg(not(miri))] // ffi call
1113    fn jsonb_from_sql_true() {
1114        let conn = &mut connection();
1115        let res = diesel::select(sql::<Jsonb>("jsonb('true')"))
1116            .get_result::<serde_json::Value>(conn)
1117            .unwrap();
1118        assert_eq!(res, serde_json::json!(true));
1119    }
1120
1121    #[diesel_test_helper::test]
1122    #[cfg(not(miri))] // ffi call
1123    fn jsonb_from_sql_false() {
1124        let conn = &mut connection();
1125        let res = diesel::select(sql::<Jsonb>("jsonb('false')"))
1126            .get_result::<serde_json::Value>(conn)
1127            .unwrap();
1128        assert_eq!(res, serde_json::json!(false));
1129    }
1130
1131    #[diesel_test_helper::test]
1132    #[cfg(not(miri))] // ffi call
1133    fn jsonb_from_sql_int() {
1134        let conn = &mut connection();
1135        let res = diesel::select(sql::<Jsonb>("jsonb('42')"))
1136            .get_result::<serde_json::Value>(conn)
1137            .unwrap();
1138        assert_eq!(res, serde_json::json!(42));
1139    }
1140
1141    #[diesel_test_helper::test]
1142    #[cfg(not(miri))] // ffi call
1143    fn jsonb_from_sql_float() {
1144        let conn = &mut connection();
1145        let res = diesel::select(sql::<Jsonb>("jsonb('42.23')"))
1146            .get_result::<serde_json::Value>(conn)
1147            .unwrap();
1148        assert_eq!(res, serde_json::json!(42.23));
1149    }
1150
1151    #[diesel_test_helper::test]
1152    #[cfg(not(miri))] // ffi call
1153    fn jsonb_from_sql_object() {
1154        let conn = &mut connection();
1155        let res = diesel::select(sql::<Jsonb>("jsonb('{\"key\": \"value\"}')"))
1156            .get_result::<serde_json::Value>(conn)
1157            .unwrap();
1158        assert_eq!(res, serde_json::json!({"key": "value"}));
1159    }
1160
1161    #[diesel_test_helper::test]
1162    #[cfg(not(miri))] // ffi call
1163    fn jsonb_from_sql_array() {
1164        let conn = &mut connection();
1165        let res = diesel::select(sql::<Jsonb>("jsonb('[1, 2, 3]')"))
1166            .get_result::<serde_json::Value>(conn)
1167            .unwrap();
1168        assert_eq!(res, serde_json::json!([1, 2, 3]));
1169    }
1170
1171    #[diesel_test_helper::test]
1172    #[cfg(not(miri))] // ffi call
1173    fn jsonb_from_sql_nested_objects() {
1174        let conn = &mut connection();
1175        let res = diesel::select(sql::<Jsonb>("jsonb('{\"outer\": {\"inner\": 42}}')"))
1176            .get_result::<serde_json::Value>(conn)
1177            .unwrap();
1178        assert_eq!(res, serde_json::json!({"outer": {"inner": 42}}));
1179    }
1180
1181    #[diesel_test_helper::test]
1182    #[cfg(not(miri))] // ffi call
1183    fn jsonb_from_sql_nested_arrays() {
1184        let conn = &mut connection();
1185        let res = diesel::select(sql::<Jsonb>("jsonb('[[1, 2], [3, 4]]')"))
1186            .get_result::<serde_json::Value>(conn)
1187            .unwrap();
1188        assert_eq!(res, serde_json::json!([[1, 2], [3, 4]]));
1189    }
1190
1191    #[diesel_test_helper::test]
1192    #[cfg(not(miri))] // ffi call
1193    fn jsonb_from_sql_nested_arrays_in_objects() {
1194        let conn = &mut connection();
1195        let res = diesel::select(sql::<Jsonb>("jsonb('{\"array\": [1, 2, 3]}')"))
1196            .get_result::<serde_json::Value>(conn)
1197            .unwrap();
1198        assert_eq!(res, serde_json::json!({"array": [1, 2, 3]}));
1199    }
1200
1201    #[diesel_test_helper::test]
1202    #[cfg(not(miri))] // ffi call
1203    fn jsonb_from_sql_nested_objects_in_arrays() {
1204        let conn = &mut connection();
1205        let res = diesel::select(sql::<Jsonb>(
1206            "jsonb('[{\"key1\": \"value1\"}, {\"key2\": \"value2\"}]')",
1207        ))
1208        .get_result::<serde_json::Value>(conn)
1209        .unwrap();
1210        assert_eq!(
1211            res,
1212            serde_json::json!([{"key1": "value1"}, {"key2": "value2"}])
1213        );
1214    }
1215
1216    #[diesel_test_helper::test]
1217    #[cfg(not(miri))] // ffi call
1218    fn jsonb_from_sql_text() {
1219        let conn = &mut connection();
1220        let res = diesel::select(sql::<Jsonb>("jsonb('\"hello\"')"))
1221            .get_result::<serde_json::Value>(conn)
1222            .unwrap();
1223        assert_eq!(res, serde_json::json!("hello"));
1224    }
1225
1226    #[diesel_test_helper::test]
1227    #[cfg(not(miri))] // ffi call
1228    fn jsonb_from_sql_textj() {
1229        let conn = &mut connection();
1230        let res = diesel::select(sql::<Jsonb>("jsonb('\"hello\\nworld\"')"))
1231            .get_result::<serde_json::Value>(conn)
1232            .unwrap();
1233        assert_eq!(res, serde_json::json!("hello\nworld"));
1234    }
1235
1236    #[diesel_test_helper::test]
1237    #[cfg(not(miri))] // ffi call
1238    fn bad_json_from_sql() {
1239        let conn = &mut connection();
1240        let res = diesel::select(json!(true).into_sql::<Json>().eq(&sql("json('boom')")))
1241            .get_result::<bool>(conn);
1242        assert_eq!(res.unwrap_err().to_string(), "malformed JSON");
1243    }
1244
1245    #[diesel_test_helper::test]
1246    #[cfg(not(miri))] // ffi call
1247    fn bad_jsonb_from_sql() {
1248        let conn = &mut connection();
1249        let res = diesel::select(json!(true).into_sql::<Jsonb>().eq(&sql("jsonb('boom')")))
1250            .get_result::<bool>(conn);
1251        assert_eq!(res.unwrap_err().to_string(), "malformed JSON");
1252    }
1253
1254    #[diesel_test_helper::test]
1255    fn no_json_from_sql() {
1256        let uuid: Result<serde_json::Value, _> = FromSql::<Json, Sqlite>::from_nullable_sql(None);
1257        assert_eq!(
1258            uuid.unwrap_err().to_string(),
1259            "Unexpected null for non-null column"
1260        );
1261    }
1262
1263    #[diesel_test_helper::test]
1264    fn no_jsonb_from_sql() {
1265        let uuid: Result<serde_json::Value, _> = FromSql::<Jsonb, Sqlite>::from_nullable_sql(None);
1266        assert_eq!(
1267            uuid.unwrap_err().to_string(),
1268            "Unexpected null for non-null column"
1269        );
1270    }
1271
1272    #[cfg(all(
1273        not(miri),
1274        not(all(target_family = "wasm", target_os = "unknown")),
1275        unix
1276    ))]
1277    const RECURSION_DEPTH: usize = 2000;
1278
1279    #[cfg(all(
1280        not(miri),
1281        any(windows, all(target_family = "wasm", target_os = "unknown"))
1282    ))]
1283    const RECURSION_DEPTH: usize = 1000;
1284
1285    #[cfg(any(
1286        miri,
1287        all(
1288            not(unix),
1289            not(windows),
1290            not(all(target_family = "wasm", target_os = "unknown"))
1291        )
1292    ))]
1293    const RECURSION_DEPTH: usize = 10;
1294
1295    #[diesel_test_helper::test]
1296    fn guard_against_stackoverflow_array() {
1297        let mut value = serde_json::Value::Number(42.into());
1298        for i in 0..RECURSION_DEPTH {
1299            value = serde_json::Value::Array(vec![value, serde_json::Value::Number(i.into())]);
1300        }
1301        // We compare the encoded buffer for both values here
1302        // as serde_json otherwise runs into stackoverflows itself
1303        let mut expected_buffer = Vec::new();
1304        write_jsonb_value(&value, &mut expected_buffer).unwrap();
1305        let res = read_jsonb_value(&expected_buffer).unwrap().0;
1306
1307        let mut buffer = Vec::new();
1308        write_jsonb_value(&res, &mut buffer).unwrap();
1309        assert_eq!(expected_buffer, buffer);
1310    }
1311
1312    #[diesel_test_helper::test]
1313    fn guard_against_stackoverflow_object() {
1314        let mut value = serde_json::Value::Number(42.into());
1315        for i in 0..RECURSION_DEPTH {
1316            let mut map = serde_json::Map::new();
1317            map.insert(format!("key_{i}"), value);
1318            value = serde_json::Value::Object(map);
1319        }
1320
1321        // We compare the encoded buffer for both values here
1322        // as serde_json otherwise runs into stackoverflows itself
1323        let mut expected_buffer = Vec::new();
1324        write_jsonb_value(&value, &mut expected_buffer).unwrap();
1325
1326        let res = read_jsonb_value(&expected_buffer).unwrap().0;
1327
1328        let mut buffer = Vec::new();
1329        write_jsonb_value(&res, &mut buffer).unwrap();
1330        assert_eq!(expected_buffer, buffer);
1331    }
1332
1333    #[diesel_test_helper::test]
1334    fn guard_against_stackoverflow_mixed() {
1335        let mut value = serde_json::Value::Number(42.into());
1336        for i in 0_usize..2000 {
1337            if i.is_multiple_of(2) {
1338                let mut map = serde_json::Map::new();
1339                map.insert(format!("key_{i}"), value);
1340                value = serde_json::Value::Object(map);
1341            } else {
1342                value = serde_json::Value::Array(vec![value]);
1343            }
1344        }
1345        // We compare the encoded buffer for both values here
1346        // as serde_json otherwise runs into stackoverflows itself
1347        let mut expected_buffer = Vec::new();
1348        write_jsonb_value(&value, &mut expected_buffer).unwrap();
1349        let res = read_jsonb_value(&expected_buffer).unwrap().0;
1350        let mut buffer = Vec::new();
1351        write_jsonb_value(&res, &mut buffer).unwrap();
1352        assert_eq!(expected_buffer, buffer);
1353    }
1354
1355    #[diesel_test_helper::test]
1356    #[cfg(not(miri))] // ffi call
1357    fn dangling_bytes_result_in_error() {
1358        let mut value = Vec::<u8>::new();
1359        value.extend(create_jsonb_header(JSONB_INT, 1).unwrap());
1360        value.push(b'1');
1361        value.push(42);
1362        assert_eq!(value.len(), 3);
1363        let conn = &mut connection();
1364        let res = diesel::select(
1365            crate::dsl::sql::<sql_types::Jsonb>("jsonb(?)").bind::<sql_types::Binary, _>(value),
1366        )
1367        .get_result::<serde_json::Value>(conn);
1368        assert!(res.is_err(), "{:?}", res.unwrap());
1369    }
1370
1371    #[diesel_test_helper::test]
1372    fn object_key_without_value_results_in_error() {
1373        let mut value = Vec::new();
1374        value.extend(create_jsonb_header(JSONB_OBJECT, 2).unwrap());
1375        value.extend(create_jsonb_header(JSONB_TEXT, 1).unwrap());
1376        value.push(b'a');
1377        let res = read_jsonb_value(&value);
1378        assert!(res.is_err(), "{:?}", res.unwrap());
1379    }
1380
1381    #[diesel_test_helper::test]
1382    fn check_invalid_size_header() {
1383        // 9-byte JSONB blob: first byte 0xFB (size_hint nibble = 0x0F),
1384        // bytes 1..9 = 0xFF -> encoded payload length = u64::MAX.
1385        let res = read_jsonb_value(&[0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
1386        assert!(res.is_err());
1387    }
1388
1389    #[diesel_test_helper::test]
1390    fn nested_container_cannot_cross_parent_boundary() {
1391        let res = read_jsonb_value(&[0x3B, 0x1B, 0x1B, JSONB_NULL]);
1392        assert!(res.is_err(), "{:?}", res.unwrap());
1393    }
1394
1395    #[diesel_test_helper::test]
1396    fn check_signed_integer() {
1397        let mut buf = Vec::new();
1398        write_jsonb_value(&json!(-42), &mut buf).unwrap();
1399        let mut expected = create_jsonb_header(JSONB_INT, 3).unwrap();
1400        expected.extend(b"-42");
1401        assert_eq!(buf, expected);
1402    }
1403}