1use crate::deserialize::{self, FromSql};
4use crate::serialize::{self, IsNull, Output, ToSql};
5use crate::sql_types;
6use crate::sqlite::{Sqlite, SqliteValue};
7use alloc::boxed::Box;
8use alloc::string::{String, ToString};
9use alloc::vec::Vec;
10
11#[cfg(all(feature = "__sqlite-shared", feature = "serde_json"))]
12impl FromSql<sql_types::Json, Sqlite> for serde_json::Value {
13 fn from_sql(mut value: SqliteValue<'_, '_, '_>) -> deserialize::Result<Self> {
14 serde_json::from_str(value.read_text()).map_err(|_| "Invalid Json".into())
15 }
16}
17
18#[cfg(all(feature = "__sqlite-shared", feature = "serde_json"))]
19impl ToSql<sql_types::Json, Sqlite> for serde_json::Value {
20 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
21 out.set_value(serde_json::to_string(self)?);
22 Ok(IsNull::No)
23 }
24}
25
26#[cfg(all(feature = "__sqlite-shared", feature = "serde_json"))]
27impl FromSql<sql_types::Jsonb, Sqlite> for serde_json::Value {
28 fn from_sql(mut value: SqliteValue<'_, '_, '_>) -> deserialize::Result<Self> {
29 use self::jsonb::*;
30
31 let bytes = value.read_blob();
32
33 if bytes.is_empty() {
34 return Err("Empty blob cannot be decoded as JSONB".into());
35 }
36
37 let (jsonb, size) = read_jsonb_value(bytes)?;
39 if size == bytes.len() {
40 Ok(jsonb)
41 } else {
42 Err("Payload contained more bytes than the encoded JSONB".into())
43 }
44 }
45}
46
47#[cfg(all(feature = "__sqlite-shared", feature = "serde_json"))]
48impl ToSql<sql_types::Jsonb, Sqlite> for serde_json::Value {
49 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
50 use self::jsonb::*;
51
52 let mut buffer = Vec::new();
54
55 write_jsonb_value(self, &mut buffer)?;
57
58 out.set_value(buffer);
60
61 Ok(IsNull::No)
62 }
63}
64
65#[cfg(all(feature = "__sqlite-shared", feature = "serde_json"))]
66mod jsonb {
67 extern crate serde_json;
68
69 use core::error::Error;
70
71 use super::*;
72
73 pub(super) const JSONB_NULL: u8 = 0x00;
74 pub(super) const JSONB_TRUE: u8 = 0x01;
75 pub(super) const JSONB_FALSE: u8 = 0x02;
76 pub(super) const JSONB_INT: u8 = 0x03;
77 pub(super) const JSONB_INT5: u8 = 0x04;
78 pub(super) const JSONB_FLOAT: u8 = 0x05;
79 pub(super) const JSONB_FLOAT5: u8 = 0x06;
80 pub(super) const JSONB_TEXT: u8 = 0x07;
81 pub(super) const JSONB_TEXTJ: u8 = 0x08;
82 pub(super) const JSONB_TEXT5: u8 = 0x09;
83 pub(super) const JSONB_TEXTRAW: u8 = 0x0A;
84 pub(super) const JSONB_ARRAY: u8 = 0x0B;
85 pub(super) const JSONB_OBJECT: u8 = 0x0C;
86
87 #[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)]
88 struct JsonbHeader {
89 element_type: u8,
90 payload_size: usize,
91 header_size: usize,
92 total_size: usize,
93 }
94
95 #[allow(unsafe_code)]
97 pub(super) fn read_jsonb_value(
98 bytes: &[u8],
99 ) -> deserialize::Result<(serde_json::Value, usize)> {
100 if bytes.is_empty() {
101 return Err("Empty JSONB data".into());
102 }
103 let (global_header, mut global_value) = read_header_and_value(bytes)?;
104
105 if global_value.is_array() || global_value.is_object() {
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![(
110 &mut global_value as *mut serde_json::Value,
111 global_header.payload_size,
112 )];
113 let mut payload = &bytes[global_header.header_size..];
114 let mut total_read = 0;
115 while total_read < global_header.payload_size {
119 let Some((value, _size)) = stack.last().copied() else {
120 break;
121 };
122 let value = unsafe {
123 &mut *value
126 };
127
128 if let serde_json::Value::Array(array) = value {
129 let (header, value) = read_header_and_value(payload)?;
130
131 array.push(value);
132 let last_ref = array.last_mut().expect("Pushed above");
133 let payload_size = if last_ref.is_object() || last_ref.is_array() {
134 stack.push((last_ref as *mut _, total_read + header.total_size));
135 header.header_size
136 } else {
137 header.total_size
138 };
139 total_read += payload_size;
140 if payload.len() > payload_size {
141 payload = &payload[payload_size..];
142 } else {
143 for (_, v) in stack {
144 if v != total_read {
145 return Err("Invalid size of payload declared".into());
146 }
147 }
148 break;
149 }
150 } else if let serde_json::Value::Object(object) = value {
151 let (key_header, key) = read_header_and_value(payload)?;
153 total_read += key_header.total_size;
154 let serde_json::Value::String(key) = key else {
155 return Err("Expected a string as object key".into());
156 };
157 if payload.len() > key_header.total_size {
158 payload = &payload[key_header.total_size..];
159 } else {
160 return Err("No value found for object".into());
161 }
162 let (value_header, value) = read_header_and_value(payload)?;
163 object.insert(key.clone(), value);
164 let last_ref = object.get_mut(&key).expect("We inserted it above");
165 let payload_size = if last_ref.is_object() || last_ref.is_array() {
166 stack.push((last_ref as *mut _, total_read + value_header.total_size));
167 value_header.header_size
168 } else {
169 value_header.total_size
170 };
171 total_read += payload_size;
172 if payload.len() > payload_size {
173 payload = &payload[payload_size..];
174 } else {
175 for (_, v) in stack {
176 if v != total_read {
177 return Err("Invalid size of payload declared".into());
178 }
179 }
180 break;
181 }
182 } else {
183 ::core::panicking::panic("internal error: entered unreachable code")unreachable!()
184 }
185
186 while let Some(v) = stack.last().map(|(_, v)| *v) {
187 if v > total_read {
188 break;
189 } else if v == total_read {
190 stack.pop();
191 } else {
192 return Err("Invalid size of payload declared".into());
193 }
194 }
195 }
196 }
197 Ok((global_value, global_header.total_size))
198 }
199
200 fn read_header_and_value(
205 bytes: &[u8],
206 ) -> deserialize::Result<(JsonbHeader, serde_json::Value)> {
207 let header = read_jsonb_value_header(bytes)?;
208 let payload_bytes = &bytes[header.header_size..header.total_size];
209 let value = match header.element_type {
210 JSONB_NULL | JSONB_TRUE | JSONB_FALSE if header.total_size != 1 => {
212 Err("Invalid JSONB data: a constant must be a single byte".into())
213 }
214 JSONB_NULL => Ok(serde_json::Value::Null),
215 JSONB_TRUE => Ok(serde_json::Value::Bool(true)),
216 JSONB_FALSE => Ok(serde_json::Value::Bool(false)),
217 JSONB_INT => read_jsonb_int(payload_bytes, header.payload_size),
218 JSONB_INT5 => Err("INT5 is not supported".into()),
219 JSONB_FLOAT => read_jsonb_float(payload_bytes, header.payload_size),
220 JSONB_FLOAT5 => Err("FLOAT5 is not supported".into()),
221 JSONB_TEXT => read_jsonb_text(payload_bytes, header.payload_size),
222 JSONB_TEXTJ => read_jsonb_textj(payload_bytes, header.payload_size),
223 JSONB_TEXTRAW => read_jsonb_text(payload_bytes, header.payload_size),
224 JSONB_TEXT5 => Err("TEXT5 is not supported".into()),
225 JSONB_ARRAY => Ok(serde_json::Value::Array(alloc::vec::Vec::new())),
226 JSONB_OBJECT => Ok(serde_json::Value::Object(serde_json::Map::new())),
227 _ => Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Unsupported or reserved JSONB type: {0}",
header.element_type))
})alloc::format!(
228 "Unsupported or reserved JSONB type: {}",
229 header.element_type
230 )
231 .into()),
232 }?;
233 Ok((header, value))
234 }
235
236 fn read_jsonb_value_header(bytes: &[u8]) -> deserialize::Result<JsonbHeader> {
237 let first_byte = bytes[0];
238 let element_type = first_byte & 0x0F;
239 let size_hint = (first_byte & 0xF0) >> 4;
240 let (payload_size, header_size): (usize, usize) = match size_hint {
241 0x00..=0x0B => (size_hint as usize, 1), 0x0C => {
243 if bytes.len() < 2 {
244 return Err("Invalid JSONB data: insufficient bytes for payload size".into());
245 }
246 (bytes[1] as usize, 2) }
248 0x0D => {
249 if bytes.len() < 3 {
250 return Err("Invalid JSONB data: insufficient bytes for payload size".into());
251 }
252 (u16::from_be_bytes([bytes[1], bytes[2]]) as usize, 3) }
254 0x0E => {
255 if bytes.len() < 5 {
256 return Err("Invalid JSONB data: insufficient bytes for payload size".into());
257 }
258 (
259 u32::from_be_bytes([bytes[1], bytes[2], bytes[3], bytes[4]]) as usize,
260 5,
261 ) }
263 0x0F => {
264 if bytes.len() < 9 {
265 return Err("Invalid JSONB data: insufficient bytes for payload size".into());
266 }
267 (
268 usize::try_from(u64::from_be_bytes([
269 bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
270 bytes[8],
271 ]))
272 .map_err(Box::new)?,
273 9,
274 ) }
276 _ => return Err("Invalid payload size hint".into()),
277 };
278 let total_size = header_size
279 .checked_add(payload_size)
280 .ok_or("The provided payload size overflows usize")?;
281 if bytes.len() < total_size {
282 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()))
})alloc::format!(
283 "Invalid JSONB data: insufficient bytes for value of type {}, expected {} bytes, got {}",
284 element_type,
285 total_size,
286 bytes.len()
287 )
288 .into());
289 }
290
291 Ok(JsonbHeader {
292 element_type,
293 payload_size,
294 header_size,
295 total_size,
296 })
297 }
298
299 pub(super) fn read_jsonb_int(
301 bytes: &[u8],
302 payload_size: usize,
303 ) -> deserialize::Result<serde_json::Value> {
304 if bytes.len() < payload_size {
306 return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Expected payload of size {0}, but got {1}",
payload_size, bytes.len()))
})alloc::format!(
307 "Expected payload of size {}, but got {}",
308 payload_size,
309 bytes.len()
310 )
311 .into());
312 }
313
314 let int_str = core::str::from_utf8(bytes).map_err(|_| "Invalid ASCII in JSONB integer")?;
316 if int_str.contains(['.', 'e', 'E']) {
319 return Err("Failed to parse JSONB integer".into());
320 }
321 if int_str == "-0" {
324 return Ok(serde_json::Value::Number(serde_json::Number::from(0)));
325 }
326 let int_value = serde_json::from_str(int_str)
327 .map_err(|_| "Failed to parse JSONB")
328 .and_then(|v: serde_json::Value| {
329 (v.is_number() && !v.is_f64())
332 .then_some(v)
333 .ok_or("Failed to parse JSONB integer")
334 })?;
335
336 Ok(int_value)
337 }
338
339 pub(super) fn read_jsonb_float(
341 bytes: &[u8],
342 payload_size: usize,
343 ) -> deserialize::Result<serde_json::Value> {
344 if bytes.len() < payload_size {
345 return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Expected payload of size {0}, but got {1}",
payload_size, bytes.len()))
})alloc::format!(
346 "Expected payload of size {}, but got {}",
347 payload_size,
348 bytes.len()
349 )
350 .into());
351 }
352
353 let float_str = core::str::from_utf8(bytes).map_err(|_| "Invalid UTF-8 in JSONB float")?;
354 let float_value = serde_json::from_str(float_str)
355 .map_err(|_| "Failed to parse JSONB")
356 .and_then(|v: serde_json::Value| {
357 v.is_f64()
358 .then_some(v)
359 .ok_or("Failed to parse JSONB number")
360 })?;
361
362 Ok(float_value)
363 }
364
365 pub(super) fn read_jsonb_text(
367 bytes: &[u8],
368 payload_size: usize,
369 ) -> deserialize::Result<serde_json::Value> {
370 if bytes.len() < payload_size {
371 return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Expected payload of size {0}, but got {1}",
payload_size, bytes.len()))
})alloc::format!(
372 "Expected payload of size {}, but got {}",
373 payload_size,
374 bytes.len()
375 )
376 .into());
377 }
378
379 let text = core::str::from_utf8(bytes).map_err(|_| "Invalid UTF-8 in JSONB string")?;
380 Ok(serde_json::Value::String(text.to_string()))
381 }
382
383 pub(super) fn read_jsonb_textj(
384 bytes: &[u8],
385 payload_size: usize,
386 ) -> deserialize::Result<serde_json::Value> {
387 if bytes.len() < payload_size {
388 return Err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Expected payload of size {0}, but got {1}",
payload_size, bytes.len()))
})alloc::format!(
389 "Expected payload of size {}, but got {}",
390 payload_size,
391 bytes.len()
392 )
393 .into());
394 }
395
396 let text = core::str::from_utf8(bytes).map_err(|_| "Invalid UTF-8 in JSONB string")?;
397
398 let unescaped_text = serde_json::from_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("\"{0}\"", text))
})alloc::format!("\"{text}\""))
400 .map_err(|_| "Failed to parse JSON-escaped text in TEXTJ")?;
401
402 Ok(unescaped_text)
403 }
404
405 enum JsonValuePtr<'a> {
406 Value(&'a serde_json::Value),
407 Array {
408 values: &'a [serde_json::Value],
409 serialized_buffer: Vec<u8>,
410 },
411 Object {
412 object: &'a serde_json::value::Map<String, serde_json::Value>,
413 keys: Box<dyn Iterator<Item = &'a String> + 'a>,
414 serialized_buffer: Vec<u8>,
415 },
416 }
417
418 pub(super) fn write_jsonb_header(
419 buffer: &mut Vec<u8>,
420 element_type: u8,
421 payload_size: usize,
422 ) -> serialize::Result {
423 if payload_size > 2_147_483_647 {
425 return Err("Payload size exceeds the maximum allowed size of 2GB".into());
426 }
427
428 if payload_size <= 0x0B {
429 buffer.push(
431 ((u8::try_from(payload_size).map_err(|e| e.to_string())?) << 4) | element_type,
432 );
433 } else if payload_size <= 0xFF {
434 buffer.extend_from_slice(&[
436 (0x0C << 4) | element_type,
437 u8::try_from(payload_size).map_err(|e| e.to_string())?,
438 ]);
439 } else if payload_size <= 0xFFFF {
440 buffer.push((0x0D << 4) | element_type);
442 buffer.extend_from_slice(
443 &(u16::try_from(payload_size).map_err(|e| e.to_string())?).to_be_bytes(),
444 );
445 } else {
446 buffer.push((0x0E << 4) | element_type);
448 buffer.extend_from_slice(
449 &(u32::try_from(payload_size).map_err(|e| e.to_string())?).to_be_bytes(),
450 );
451 };
452
453 Ok(IsNull::No)
454 }
455
456 fn place_composite_value(
457 buffer: &mut Vec<u8>,
458 stack: &mut [JsonValuePtr<'_>],
459 serialized_buffer: Vec<u8>,
460 tpe: u8,
461 ) -> serialize::Result {
462 let buffer = match stack.last_mut() {
463 None | Some(JsonValuePtr::Value(_)) => buffer,
464 Some(
465 JsonValuePtr::Array {
466 serialized_buffer, ..
467 }
468 | JsonValuePtr::Object {
469 serialized_buffer, ..
470 },
471 ) => serialized_buffer,
472 };
473 write_jsonb_header(buffer, tpe, serialized_buffer.len())?;
474 buffer.extend(serialized_buffer);
475
476 Ok(IsNull::No)
477 }
478
479 pub(super) fn write_jsonb_value(
481 value: &serde_json::Value,
482 buffer: &mut Vec<u8>,
483 ) -> serialize::Result {
484 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)];
485
486 while let Some(value) = stack.pop() {
487 let add_to_stack = match value {
488 JsonValuePtr::Value(value) => write_plain_jsonb_value(buffer, value)?,
489 JsonValuePtr::Array {
490 values,
491 mut serialized_buffer,
492 } => {
493 if let Some((el, tail)) = values.split_first() {
494 let ret = write_plain_jsonb_value(&mut serialized_buffer, el)?;
495 stack.push(JsonValuePtr::Array {
496 values: tail,
497 serialized_buffer,
498 });
499 ret
500 } else {
501 place_composite_value(buffer, &mut stack, serialized_buffer, JSONB_ARRAY)?;
502 None
503 }
504 }
505 JsonValuePtr::Object {
506 object,
507 mut keys,
508 mut serialized_buffer,
509 } => {
510 if let Some(next_key) = keys.next() {
511 let value = object
512 .get(next_key)
513 .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}`"))?;
514 write_jsonb_string(next_key, &mut serialized_buffer)?;
515 let ret = write_plain_jsonb_value(&mut serialized_buffer, value)?;
516 stack.push(JsonValuePtr::Object {
517 object,
518 keys,
519 serialized_buffer,
520 });
521 ret
522 } else {
523 place_composite_value(buffer, &mut stack, serialized_buffer, JSONB_OBJECT)?;
524 None
525 }
526 }
527 };
528 if let Some(next) = add_to_stack {
529 stack.push(next);
530 }
531 }
532
533 Ok(IsNull::No)
534 }
535
536 fn write_plain_jsonb_value<'a>(
537 buffer: &mut Vec<u8>,
538 value: &'a serde_json::Value,
539 ) -> Result<Option<JsonValuePtr<'a>>, Box<dyn Error + Send + Sync>> {
540 let ret = if value.is_null() {
541 write_jsonb_null(buffer)?;
542 None
543 } else if value.is_boolean() {
544 write_jsonb_bool(value.as_bool().ok_or("Failed to read JSONB value")?, buffer)?;
545 None
546 } else if value.is_number() {
547 write_jsonb_number(value, buffer)?;
548 None
549 } else if value.is_string() {
550 write_jsonb_string(value.as_str().ok_or("Failed to read JSONB value")?, buffer)?;
551 None
552 } else if value.is_array() {
553 let array = value.as_array().ok_or("Failed to read JSONB value")?;
554 Some(JsonValuePtr::Array {
555 values: array,
556 serialized_buffer: Vec::new(),
557 })
558 } else if value.is_object() {
559 let object = value.as_object().ok_or("Failed to read JSONB value")?;
560 Some(JsonValuePtr::Object {
561 object,
562 keys: Box::new(object.keys()),
563 serialized_buffer: Vec::new(),
564 })
565 } else {
566 return Err("Unsupported JSONB value type".into());
567 };
568 Ok(ret)
569 }
570
571 pub(super) fn write_jsonb_null(buffer: &mut Vec<u8>) -> serialize::Result {
573 write_jsonb_header(buffer, JSONB_NULL, 0x0)?;
574 Ok(IsNull::No)
575 }
576
577 pub(super) fn write_jsonb_bool(b: bool, buffer: &mut Vec<u8>) -> serialize::Result {
579 write_jsonb_header(buffer, if b { JSONB_TRUE } else { JSONB_FALSE }, 0x0)?;
581 Ok(IsNull::No)
582 }
583
584 pub(super) fn write_jsonb_number(
586 n: &serde_json::Value,
587 buffer: &mut Vec<u8>,
588 ) -> serialize::Result {
589 let n = n.to_string();
590 let tpe = if n
591 .char_indices()
592 .any(|(idx, c)| !(c.is_ascii_digit() || (idx == 0 && (c == '-' || c == '+'))))
593 {
594 JSONB_FLOAT
595 } else {
596 JSONB_INT
597 };
598 write_jsonb_header(buffer, tpe, n.len())?;
599
600 buffer.extend_from_slice(n.as_bytes());
602
603 Ok(IsNull::No)
604 }
605
606 pub(super) fn write_jsonb_string(s: &str, buffer: &mut Vec<u8>) -> serialize::Result {
607 if s.bytes().any(|b| b < 0x20 || b == b'"' || b == b'\\') {
610 write_jsonb_textj(s, buffer)
611 } else {
612 write_jsonb_header(buffer, JSONB_TEXT, s.len())?;
613 buffer.extend_from_slice(s.as_bytes());
614 Ok(IsNull::No)
615 }
616 }
617
618 pub(super) fn write_jsonb_textj(s: &str, buffer: &mut Vec<u8>) -> serialize::Result {
619 let escaped_string =
621 serde_json::to_string(&s).map_err(|_| "Failed to serialize string for TEXTJ")?;
622
623 let escaped_string = &escaped_string[1..escaped_string.len() - 1];
624
625 write_jsonb_header(buffer, JSONB_TEXTJ, escaped_string.len())?;
626
627 buffer.extend_from_slice(escaped_string.as_bytes());
628
629 Ok(IsNull::No)
630 }
631}
632
633#[cfg(test)]
634#[cfg(all(feature = "__sqlite-shared", feature = "serde_json"))]
635mod tests {
636 use super::jsonb::*;
637 use super::*;
638 #[cfg(not(miri))] use crate::ExpressionMethods;
640 #[cfg(not(miri))] use crate::dsl::json_valid_with_flags;
642 #[cfg(not(miri))] use crate::query_dsl::RunQueryDsl;
644 #[cfg(not(miri))] use crate::sqlite::JsonValidFlag;
646 #[cfg(not(miri))] use crate::test_helpers::connection;
648 #[cfg(not(miri))] use crate::{IntoSql, dsl::sql};
650 use serde_json::{Value, json};
651 use sql_types::{Json, Jsonb};
652
653 pub(super) fn create_jsonb_header(
655 element_type: u8,
656 payload_size: usize,
657 ) -> Result<Vec<u8>, Box<dyn core::error::Error + Send + Sync>> {
658 let mut buffer = Vec::new();
659 jsonb::write_jsonb_header(&mut buffer, element_type, payload_size)?;
660 Ok(buffer)
661 }
662
663 fn value_with_payload(element_type: u8, payload: &[u8]) -> Vec<u8> {
664 let mut buffer = create_jsonb_header(element_type, payload.len()).unwrap();
665 buffer.extend_from_slice(payload);
666 buffer
667 }
668
669 #[diesel_test_helper::test]
670 fn regression_a_constant_reads_its_declared_size() {
671 let blobs: Vec<Vec<u8>> = vec![
672 value_with_payload(JSONB_NULL, &[0x0D, 0x00, 0xF3]), value_with_payload(JSONB_TRUE, b"1.5"), value_with_payload(JSONB_NULL, &[0x00]), value_with_payload(JSONB_TRUE, &[0x08]), value_with_payload(JSONB_FALSE, &[0xFF]), vec![0xC0, 0x00], vec![0xC1, 0x00], {
681 let mut blob = create_jsonb_header(JSONB_ARRAY, 2).unwrap();
683 blob.extend_from_slice(&[0xC1, 0x00]);
684 blob
685 },
686 {
687 let mut blob = create_jsonb_header(JSONB_OBJECT, 4).unwrap();
689 blob.extend(create_jsonb_header(JSONB_TEXT, 1).unwrap());
690 blob.extend_from_slice(b"a");
691 blob.extend_from_slice(&[0xC1, 0x00]);
692 blob
693 },
694 ];
695 for blob in blobs {
696 let blob: &[u8] = &blob;
697 assert!(
698 read_jsonb_value(blob).is_err(),
699 "{blob:02X?} decoded to {:?}",
700 read_jsonb_value(blob).map(|value| value.0)
701 );
702 }
703
704 let mut blob = create_jsonb_header(JSONB_ARRAY, 2).unwrap();
706 blob.extend(create_jsonb_header(JSONB_TRUE, 0).unwrap());
707 blob.extend(create_jsonb_header(JSONB_NULL, 0).unwrap());
708 assert_eq!(read_jsonb_value(&blob).unwrap().0, json!([true, null]));
709 }
710
711 #[diesel_test_helper::test]
712 #[cfg(not(miri))] fn regression_json_text_float_survives_a_round_trip() {
714 let conn = &mut connection();
715 for float in [
716 8.829872855928286e-308f64,
717 -0.20221894534048165,
718 1.7383394626966921e-307,
719 6.178787134922198e305,
720 ] {
721 let value = json!(float);
722 let text = diesel::select(sql::<sql_types::Text>("").bind::<sql_types::Json, _>(value))
723 .get_result::<String>(conn)
724 .unwrap();
725 let back = diesel::select(sql::<sql_types::Json>("").bind::<sql_types::Text, _>(text))
726 .get_result::<Value>(conn)
727 .unwrap();
728 assert_eq!(back.as_f64().map(f64::to_bits), Some(float.to_bits()));
729 }
730 }
731
732 #[diesel_test_helper::test]
733 #[cfg(not(miri))] fn regression_float_keeps_its_bits_through_the_writers_text() {
735 let conn = &mut connection();
736 let mut assert_roundtrip = |value: Value| {
737 let expected = value.as_f64().unwrap();
738 let blob = diesel::select(sql::<sql_types::Binary>("").bind::<Jsonb, _>(value))
739 .get_result::<Vec<u8>>(conn)
740 .unwrap();
741 let back = diesel::select(sql::<Jsonb>("").bind::<sql_types::Binary, _>(blob))
742 .get_result::<Value>(conn)
743 .unwrap();
744 assert_eq!(
745 back.as_f64().unwrap().to_bits(),
746 expected.to_bits(),
747 "{expected:?} came back as {back}"
748 );
749 };
750
751 assert_roundtrip(serde_json::from_str("-922333372720360.5975808").unwrap());
753
754 for f in [
755 -0.20221894534048165,
757 6.178787134922198e305,
758 -5.276099561814224e214,
759 3.587959730897931e-246,
760 9.136353238902674e-45,
761 2.4261860608815182e-160,
762 -2.5496151068102186e-175,
763 5.0513463356317975e-231,
764 0.1,
766 1e-7,
767 5e-324,
768 -0.0,
769 f64::MAX,
770 f64::MIN_POSITIVE,
771 ] {
772 assert_roundtrip(json!(f));
773 }
774 }
775
776 #[diesel_test_helper::test]
777 fn regression_every_float_text_reads_back_as_the_same_double() {
778 let mut drifted = Vec::new();
779 let mut check = |bits: u64| {
780 let f = f64::from_bits(bits);
781 if !f.is_finite() {
782 return;
783 }
784 let mut buffer = Vec::new();
785 write_jsonb_number(&json!(f), &mut buffer).unwrap();
786 let back = read_jsonb_value(&buffer).unwrap().0;
787 if back.as_f64().map(f64::to_bits) != Some(bits) {
788 drifted.push(alloc::format!("{bits:#018x} {f:?} -> {back}"));
789 }
790 };
791
792 for exponent in [0, 1, 2, 512, 1021, 1022, 1023, 1024, 1075, 2045, 2046] {
793 for mantissa in [0, 1, 2, 1 << 26, 1 << 51, (1 << 52) - 2, (1 << 52) - 1] {
794 for sign in [0, 1u64 << 63] {
795 check(sign | (exponent << 52) | mantissa);
796 }
797 }
798 }
799
800 let witness = serde_json::from_str::<Value>("-922333372720360.5975808")
802 .unwrap()
803 .as_f64()
804 .unwrap()
805 .to_bits();
806 for bits in witness - 2..=witness + 2 {
807 check(bits);
808 }
809
810 let mut state: u64 = 0x2545F4914F6CDD1D;
812 for _ in 0..256 {
813 state ^= state << 13;
814 state ^= state >> 7;
815 state ^= state << 17;
816 check(state);
817 }
818
819 assert!(
820 drifted.is_empty(),
821 "{} floats drifted, first {:?}",
822 drifted.len(),
823 &drifted[..drifted.len().min(4)]
824 );
825 }
826
827 #[diesel_test_helper::test]
828 #[cfg(not(miri))] fn every_jsonb_number_is_written_valid_and_round_trips() {
830 let conn = &mut connection();
831
832 let numbers = [
835 (json!(0), JSONB_INT),
836 (json!(1), JSONB_INT),
837 (json!(-1), JSONB_INT),
838 (json!(-5), JSONB_INT),
839 (json!(u64::from(u32::MAX)), JSONB_INT),
840 (json!(i64::MAX), JSONB_INT),
841 (json!(i64::MIN), JSONB_INT),
842 (json!(1u64 << 63), JSONB_INT),
843 (json!(u64::MAX), JSONB_INT),
844 (json!(3.0), JSONB_FLOAT),
845 (json!(-0.0), JSONB_FLOAT),
846 (json!(-2.5), JSONB_FLOAT),
847 (json!(1e-7), JSONB_FLOAT),
848 (json!(1e300), JSONB_FLOAT),
849 (json!(-1e300), JSONB_FLOAT),
850 (json!(1.5e300), JSONB_FLOAT),
851 (json!(1e21), JSONB_FLOAT),
852 (json!(f64::MIN), JSONB_FLOAT),
853 (json!(f64::MAX), JSONB_FLOAT),
854 (json!(f64::MIN_POSITIVE), JSONB_FLOAT),
855 ];
856
857 for (value, element_type) in numbers {
858 let blob = diesel::select(sql::<sql_types::Binary>("").bind::<Jsonb, _>(value.clone()))
859 .get_result::<Vec<u8>>(conn)
860 .unwrap();
861 assert_eq!(
862 blob[0] & 0x0F,
863 element_type,
864 "{value} was written with the wrong element type: {blob:02X?}"
865 );
866 let valid = diesel::select(json_valid_with_flags::<sql_types::Binary, _, _>(
867 blob.as_slice(),
868 JsonValidFlag::JsonbStrict,
869 ))
870 .get_result::<bool>(conn)
871 .unwrap();
872 assert!(
873 valid,
874 "sqlite rejects the blob written for {value}: {blob:02X?}"
875 );
876 let back = diesel::select(sql::<Jsonb>("").bind::<sql_types::Binary, _>(blob.clone()))
877 .get_result::<Value>(conn)
878 .unwrap_or_else(|error| panic!("{value} does not read back: {error}"));
879 assert_eq!(back, value, "{blob:02X?}");
880 }
881 }
882
883 #[cfg(not(miri))] fn jsonb_survives(conn: &mut crate::SqliteConnection, value: &Value) -> Result<(), String> {
886 let blob = diesel::select(sql::<sql_types::Binary>("").bind::<Jsonb, _>(value.clone()))
887 .get_result::<Vec<u8>>(conn)
888 .unwrap();
889 let valid = diesel::select(json_valid_with_flags::<sql_types::Binary, _, _>(
890 blob.as_slice(),
891 JsonValidFlag::JsonbStrict,
892 ))
893 .get_result::<bool>(conn)
894 .unwrap();
895 let back = diesel::select(sql::<Jsonb>("").bind::<sql_types::Binary, _>(blob.clone()))
896 .get_result::<Value>(conn);
897 if !valid {
898 return Err(alloc::format!(
899 "sqlite calls {value} malformed as {blob:02X?}"
900 ));
901 }
902 match back {
903 Ok(ref back) if back == value => Ok(()),
904 Ok(back) => Err(alloc::format!("{value} came back as {back}")),
905 Err(e) => Err(alloc::format!("{value} came back as {e}")),
906 }
907 }
908
909 #[diesel_test_helper::test]
910 #[cfg(not(miri))] fn regression_string_needing_an_escape_is_written_valid() {
912 let conn = &mut connection();
913 for value in [
914 json!(r#"a"b"#),
915 json!(r#"a\b"#),
916 json!(r#"a"\b"#),
917 json!(r#"""#),
918 json!(r#"\"#),
919 json!(r#"\""#),
920 json!(r#""leading"#),
921 json!(r#"trailing""#),
922 json!(r#"aaaaaaaaaaaa"bbbbbbbbbbbb"#),
923 json!({ "k": r#"a"b"# }),
924 json!([r#"a\b"#]),
925 json!({ r#"a"b"#: 1 }),
926 json!(""),
927 json!("abc"),
928 json!("a\nb"),
929 json!("a\"\nb"),
930 ] {
931 jsonb_survives(conn, &value).unwrap_or_else(|e| panic!("{e}"));
932 }
933 }
934
935 #[diesel_test_helper::test]
936 fn test_write_jsonb_number_classifies_by_integer_text() {
937 for (value, element_type, payload) in [
939 (json!(0), JSONB_INT, "0"),
940 (json!(-1), JSONB_INT, "-1"),
941 (json!(i64::MIN), JSONB_INT, "-9223372036854775808"),
942 (json!(u64::MAX), JSONB_INT, "18446744073709551615"),
943 (json!(3.0), JSONB_FLOAT, "3.0"),
944 (json!(-0.0), JSONB_FLOAT, "-0.0"),
945 (json!(-2.5), JSONB_FLOAT, "-2.5"),
946 (json!(1e-7), JSONB_FLOAT, "1e-7"),
947 (json!(1e300), JSONB_FLOAT, "1e+300"),
948 ] {
949 let mut buffer = Vec::new();
950 write_jsonb_value(&value, &mut buffer).unwrap();
951
952 let mut expected = create_jsonb_header(element_type, payload.len()).unwrap();
953 expected.extend_from_slice(payload.as_bytes());
954
955 assert_eq!(buffer, expected, "{value} was not written as {payload}");
956 }
957 }
958
959 #[diesel_test_helper::test]
960 #[cfg(not(miri))] fn numbers_nested_in_containers_are_written_valid() {
962 let conn = &mut connection();
963 let value = json!({"a": -1, "b": [-2, -2.5, 1e-7, 0, u64::MAX], "c": {"d": i64::MIN}});
964
965 let blob = diesel::select(sql::<sql_types::Binary>("").bind::<Jsonb, _>(value.clone()))
966 .get_result::<Vec<u8>>(conn)
967 .unwrap();
968 let valid = diesel::select(
969 sql::<sql_types::Integer>("json_valid(")
970 .bind::<sql_types::Binary, _>(blob.clone())
971 .sql(", 8)"),
972 )
973 .get_result::<i32>(conn)
974 .unwrap();
975 assert_eq!(valid, 1, "sqlite rejects {blob:02X?}");
976
977 let back = diesel::select(sql::<Jsonb>("").bind::<sql_types::Binary, _>(blob))
978 .get_result::<Value>(conn)
979 .unwrap();
980 assert_eq!(back, value);
981 }
982
983 #[diesel_test_helper::test]
984 fn test_read_jsonb_int_decodes_the_whole_representable_range() {
985 for (payload, expected) in [
986 (&b"0"[..], json!(0)),
987 (&b"1"[..], json!(1)),
988 (&b"-1"[..], json!(-1)),
989 (&b"-0"[..], json!(0)),
991 (&b"9223372036854775807"[..], json!(i64::MAX)),
992 (&b"-9223372036854775808"[..], json!(i64::MIN)),
993 (&b"9223372036854775808"[..], json!(1u64 << 63)),
994 (&b"18446744073709551615"[..], json!(u64::MAX)),
995 ] {
996 let mut data = create_jsonb_header(JSONB_INT, payload.len()).unwrap();
997 data.extend_from_slice(payload);
998
999 let payload = core::str::from_utf8(payload).unwrap();
1000 assert_eq!(
1001 read_jsonb_value(&data).unwrap().0,
1002 expected,
1003 "{payload} did not decode to itself"
1004 );
1005 }
1006 }
1007
1008 #[diesel_test_helper::test]
1009 #[cfg(not(miri))] fn regression_every_char_is_written_valid() {
1011 let conn = &mut connection();
1012 let mut offenders = Vec::new();
1013 let mut chunk = Vec::new();
1015 for code in 0u32..=0x10FFFF {
1016 if let Some(c) = char::from_u32(code) {
1017 let mut s = alloc::string::String::from('a');
1018 s.push(c);
1019 s.push('b');
1020 chunk.push(json!(s));
1021 }
1022 if chunk.len() < 2048 && code != 0x10FFFF {
1023 continue;
1024 }
1025 let batch = Value::Array(core::mem::take(&mut chunk));
1026 if let Err(batch_error) = jsonb_survives(conn, &batch) {
1027 let Value::Array(values) = batch else {
1028 unreachable!()
1029 };
1030 let known = offenders.len();
1031 for value in values {
1032 if let Err(e) = jsonb_survives(conn, &value) {
1033 offenders.push(e);
1034 }
1035 }
1036 if offenders.len() == known {
1038 offenders.push(batch_error);
1039 }
1040 }
1041 }
1042 assert!(
1043 offenders.is_empty(),
1044 "{} values broke the blob, first {:?}",
1045 offenders.len(),
1046 &offenders[..offenders.len().min(4)]
1047 );
1048 }
1049
1050 #[diesel_test_helper::test]
1051 fn test_read_jsonb_int_rejects_non_integer_payloads() {
1052 for payload in [
1053 &b"1.5"[..],
1055 &b"1e5"[..],
1056 &b"1e999"[..],
1058 &b"+1"[..],
1060 &b"01"[..],
1061 &b""[..],
1062 &b"-"[..],
1063 &b"0x10"[..],
1064 &b"nan"[..],
1065 &b"Infinity"[..],
1066 ] {
1067 let mut data = create_jsonb_header(JSONB_INT, payload.len()).unwrap();
1068 data.extend_from_slice(payload);
1069
1070 let payload = core::str::from_utf8(payload).unwrap();
1071 assert!(
1072 read_jsonb_value(&data).is_err(),
1073 "{payload} is not a JSONB integer"
1074 );
1075 }
1076 }
1077
1078 #[diesel_test_helper::test]
1079 fn test_read_jsonb_int_decodes_a_wide_integer_exactly_or_not_at_all() {
1080 for payload in [
1084 &b"18446744073709551616"[..],
1085 &b"123456789012345678901234567890"[..],
1086 ] {
1087 let mut data = create_jsonb_header(JSONB_INT, payload.len()).unwrap();
1088 data.extend_from_slice(payload);
1089
1090 let payload = core::str::from_utf8(payload).unwrap();
1091 let exact = serde_json::Number::from_u128(payload.parse().unwrap()).map(Value::Number);
1092 let decoded = read_jsonb_value(&data);
1093
1094 match exact {
1095 Some(expected) => assert_eq!(
1096 decoded.unwrap().0,
1097 expected,
1098 "{payload} is representable and must decode"
1099 ),
1100 None => assert!(decoded.is_err(), "{payload} would decode rounded"),
1101 }
1102 }
1103 }
1104
1105 #[diesel_test_helper::test]
1106 fn test_read_jsonb_int_above_i64_max_inside_containers() {
1107 let mut element = create_jsonb_header(JSONB_INT, 20).unwrap();
1108 element.extend_from_slice(b"18446744073709551615");
1109
1110 let mut array = create_jsonb_header(JSONB_ARRAY, element.len()).unwrap();
1111 array.extend_from_slice(&element);
1112 assert_eq!(read_jsonb_value(&array).unwrap().0, json!([u64::MAX]));
1113
1114 let mut key = create_jsonb_header(JSONB_TEXT, 1).unwrap();
1115 key.extend_from_slice(b"a");
1116 let mut object = create_jsonb_header(JSONB_OBJECT, key.len() + element.len()).unwrap();
1117 object.extend_from_slice(&key);
1118 object.extend_from_slice(&element);
1119 assert_eq!(read_jsonb_value(&object).unwrap().0, json!({"a": u64::MAX}));
1120 }
1121
1122 #[diesel_test_helper::test]
1123 #[cfg(not(miri))] fn regression_unsigned_above_i64_reads_a_blob_sqlite_wrote() {
1125 let conn = &mut connection();
1126
1127 let back = diesel::select(sql::<Jsonb>("jsonb('18446744073709551615')"))
1128 .get_result::<Value>(conn)
1129 .unwrap();
1130
1131 assert_eq!(back, json!(u64::MAX));
1132 }
1133
1134 #[diesel_test_helper::test]
1135 #[cfg(not(miri))] fn regression_negative_zero_reads_a_blob_sqlite_wrote() {
1137 let conn = &mut connection();
1138
1139 let back = diesel::select(sql::<Jsonb>("jsonb('-0')"))
1140 .get_result::<Value>(conn)
1141 .unwrap();
1142
1143 assert_eq!(back, json!(0));
1144 }
1145
1146 #[diesel_test_helper::test]
1147 #[cfg(not(miri))] fn json_to_sql() {
1149 let conn = &mut connection();
1150 let res = diesel::select(json!(true).into_sql::<Json>().eq(&sql("json('true')")))
1151 .get_result::<bool>(conn)
1152 .unwrap();
1153 assert!(res);
1154 }
1155
1156 #[diesel_test_helper::test]
1157 fn test_read_jsonb_null() {
1158 let data = vec![JSONB_NULL];
1159 let result = read_jsonb_value(&data).unwrap().0;
1160 assert_eq!(result, Value::Null);
1161 }
1162
1163 #[diesel_test_helper::test]
1164 fn test_read_jsonb_true() {
1165 let data = vec![JSONB_TRUE];
1166 let result = read_jsonb_value(&data).unwrap().0;
1167 assert_eq!(result, Value::Bool(true));
1168 }
1169
1170 #[diesel_test_helper::test]
1171 fn test_read_jsonb_false() {
1172 let data = vec![JSONB_FALSE];
1173 let result = read_jsonb_value(&data).unwrap().0;
1174 assert_eq!(result, Value::Bool(false));
1175 }
1176
1177 #[diesel_test_helper::test]
1178 fn test_read_jsonb_int() {
1179 let mut data = Vec::new();
1181 data.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
1182 data.push(b'1'); let result = read_jsonb_value(&data).unwrap().0;
1185 assert_eq!(result, json!(1));
1186 }
1187
1188 #[diesel_test_helper::test]
1189 fn test_read_jsonb_float() {
1190 let mut data = Vec::new();
1192 data.extend(create_jsonb_header(JSONB_FLOAT, 0x03).unwrap());
1193 data.extend_from_slice(b"1.5"); let result = read_jsonb_value(&data).unwrap().0;
1196 assert_eq!(result, json!(1.5));
1197 }
1198
1199 #[diesel_test_helper::test]
1200 fn test_read_jsonb_text() {
1201 let mut data = Vec::new();
1203 data.extend(create_jsonb_header(JSONB_TEXT, 0x03).unwrap());
1204 data.extend_from_slice(b"foo"); let result = read_jsonb_value(&data).unwrap().0;
1207 assert_eq!(result, json!("foo"));
1208 }
1209
1210 #[diesel_test_helper::test]
1211 fn test_read_jsonb_textraw() {
1212 let mut data = Vec::new();
1214 data.extend(create_jsonb_header(JSONB_TEXTRAW, 0x03).unwrap());
1215 data.extend_from_slice(b"foo");
1216
1217 let result = read_jsonb_value(&data).unwrap().0;
1218 assert_eq!(result, json!("foo"));
1219 }
1220
1221 #[diesel_test_helper::test]
1222 fn test_read_jsonb_object_with_textraw_key() {
1223 let mut data = Vec::new();
1225 data.extend(create_jsonb_header(JSONB_OBJECT, 0x06).unwrap());
1226 data.extend(create_jsonb_header(JSONB_TEXTRAW, 0x01).unwrap());
1227 data.extend_from_slice(b"a");
1228 data.extend(create_jsonb_header(JSONB_TEXTRAW, 0x03).unwrap());
1229 data.extend_from_slice(b"bar");
1230
1231 let result = read_jsonb_value(&data).unwrap().0;
1232 assert_eq!(result, json!({"a": "bar"}));
1233 }
1234
1235 #[diesel_test_helper::test]
1236 fn test_read_jsonb_array() {
1237 let mut data = Vec::new();
1239 data.extend(create_jsonb_header(JSONB_ARRAY, 0x03).unwrap()); data.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
1243 data.push(b'1');
1244
1245 data.extend(create_jsonb_header(JSONB_TRUE, 0x00).unwrap());
1247
1248 let result = read_jsonb_value(&data).unwrap().0;
1249 assert_eq!(result, json!([1, true]));
1250 }
1251
1252 #[diesel_test_helper::test]
1253 fn test_read_jsonb_object() {
1254 let mut data = Vec::new();
1256 data.extend(create_jsonb_header(JSONB_OBJECT, 0x07).unwrap()); data.extend(create_jsonb_header(JSONB_TEXT, 0x03).unwrap());
1260 data.extend_from_slice(b"key"); data.extend(create_jsonb_header(JSONB_INT, 0x02).unwrap());
1264 data.extend_from_slice(b"42"); let result = read_jsonb_value(&data).unwrap().0;
1267 assert_eq!(result, json!({"key": 42}));
1268 }
1269
1270 #[diesel_test_helper::test]
1271 fn test_read_jsonb_nested_object() {
1272 let mut data = Vec::new();
1273
1274 data.extend(create_jsonb_header(JSONB_OBJECT, 42).unwrap());
1275
1276 data.extend(create_jsonb_header(JSONB_TEXT, 9).unwrap());
1277 data.extend_from_slice(b"outer_key");
1278
1279 data.extend(create_jsonb_header(JSONB_OBJECT, 13).unwrap());
1280
1281 data.extend(create_jsonb_header(JSONB_TEXT, 9).unwrap());
1282 data.extend_from_slice(b"inner_key");
1283
1284 data.extend(create_jsonb_header(JSONB_INT, 2).unwrap());
1285 data.extend_from_slice(b"42");
1286
1287 data.extend(create_jsonb_header(JSONB_TEXT, 14).unwrap());
1288 data.extend_from_slice(b"additional_key");
1289
1290 data.extend(create_jsonb_header(JSONB_TRUE, 0).unwrap());
1291
1292 let result = read_jsonb_value(&data).unwrap().0;
1293 assert_eq!(
1294 result,
1295 json!({
1296 "additional_key": true,
1297 "outer_key": {
1298 "inner_key": 42
1299 },
1300 })
1301 );
1302 }
1303
1304 #[diesel_test_helper::test]
1305 fn test_write_jsonb_null() {
1306 let value = serde_json::Value::Null;
1307 let mut buffer = Vec::new();
1308 write_jsonb_value(&value, &mut buffer).unwrap();
1309 assert_eq!(buffer, vec![JSONB_NULL]);
1310 }
1311
1312 #[diesel_test_helper::test]
1313 fn test_write_jsonb_true() {
1314 let value = serde_json::Value::Bool(true);
1315 let mut buffer = Vec::new();
1316 write_jsonb_value(&value, &mut buffer).unwrap();
1317 assert_eq!(buffer, vec![JSONB_TRUE]);
1318 }
1319
1320 #[diesel_test_helper::test]
1321 fn test_write_jsonb_false() {
1322 let value = serde_json::Value::Bool(false);
1323 let mut buffer = Vec::new();
1324 write_jsonb_value(&value, &mut buffer).unwrap();
1325 assert_eq!(buffer, vec![JSONB_FALSE]);
1326 }
1327
1328 #[diesel_test_helper::test]
1329 fn test_write_jsonb_int() {
1330 let value = serde_json::Value::Number(serde_json::Number::from(1));
1331 let mut buffer = Vec::new();
1332 write_jsonb_value(&value, &mut buffer).unwrap();
1333
1334 let mut expected_buffer = Vec::new();
1335 expected_buffer.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
1336 expected_buffer.push(b'1'); assert_eq!(buffer, expected_buffer);
1339 }
1340
1341 #[diesel_test_helper::test]
1342 fn test_write_jsonb_float() {
1343 let value = serde_json::Value::Number(serde_json::Number::from_f64(1.5).unwrap());
1344 let mut buffer = Vec::new();
1345 write_jsonb_value(&value, &mut buffer).unwrap();
1346
1347 let mut expected_buffer = Vec::new();
1348 expected_buffer.extend(create_jsonb_header(JSONB_FLOAT, 0x03).unwrap());
1349 expected_buffer.extend_from_slice(b"1.5"); assert_eq!(buffer, expected_buffer);
1352 }
1353
1354 #[diesel_test_helper::test]
1355 fn test_write_jsonb_text() {
1356 let mut buffer = Vec::new();
1357 let input_string = "hello";
1358 write_jsonb_string(input_string, &mut buffer).unwrap();
1359
1360 let mut expected_buffer = Vec::new();
1361 expected_buffer.extend(create_jsonb_header(JSONB_TEXT, 0x05).unwrap());
1362 expected_buffer.extend_from_slice(b"hello");
1363
1364 assert_eq!(buffer, expected_buffer);
1365 }
1366
1367 #[diesel_test_helper::test]
1368 fn test_write_jsonb_textj() {
1369 let mut buffer = Vec::new();
1370 let input_string = "hello\nworld"; write_jsonb_string(input_string, &mut buffer).unwrap();
1372
1373 let mut expected_buffer = Vec::new();
1374 expected_buffer.extend(create_jsonb_header(JSONB_TEXTJ, 12).unwrap());
1375 expected_buffer.extend_from_slice(b"hello\\nworld");
1376
1377 assert_eq!(buffer, expected_buffer);
1378 }
1379
1380 #[diesel_test_helper::test]
1381 fn test_write_jsonb_textj_quote_and_backslash() {
1382 let mut buffer = Vec::new();
1383 let input_string = r#"a"b\c"#;
1384 write_jsonb_string(input_string, &mut buffer).unwrap();
1385
1386 let mut expected_buffer = Vec::new();
1387 expected_buffer.extend(create_jsonb_header(JSONB_TEXTJ, 7).unwrap());
1388 expected_buffer.extend_from_slice(br#"a\"b\\c"#);
1389
1390 assert_eq!(buffer, expected_buffer);
1391 }
1392
1393 #[diesel_test_helper::test]
1394 fn test_write_jsonb_text_keeps_high_control_free_text() {
1395 let mut buffer = Vec::new();
1397 write_jsonb_string("a\u{7f}b", &mut buffer).unwrap();
1398
1399 let mut expected_buffer = Vec::new();
1400 expected_buffer.extend(create_jsonb_header(JSONB_TEXT, 3).unwrap());
1401 expected_buffer.extend_from_slice("a\u{7f}b".as_bytes());
1402
1403 assert_eq!(buffer, expected_buffer);
1404 }
1405
1406 #[diesel_test_helper::test]
1407 fn test_write_jsonb_array() {
1408 let value = json!([1, true]);
1409 let mut buffer = Vec::new();
1410 write_jsonb_value(&value, &mut buffer).unwrap();
1411
1412 let mut expected_buffer = Vec::new();
1413 expected_buffer.extend(create_jsonb_header(JSONB_ARRAY, 0x03).unwrap()); expected_buffer.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap()); expected_buffer.push(b'1'); expected_buffer.extend(create_jsonb_header(JSONB_TRUE, 0x00).unwrap()); assert_eq!(buffer, expected_buffer);
1419 }
1420
1421 #[diesel_test_helper::test]
1422 fn test_write_jsonb_object() {
1423 let value = json!({"key": 42});
1424 let mut buffer = Vec::new();
1425 write_jsonb_value(&value, &mut buffer).unwrap();
1426
1427 let mut expected = Vec::new();
1428 expected.extend(create_jsonb_header(JSONB_OBJECT, 7).unwrap());
1429 expected.extend(create_jsonb_header(JSONB_TEXT, 3).unwrap());
1430 expected.extend_from_slice(b"key");
1431 expected.extend(create_jsonb_header(JSONB_INT, 2).unwrap());
1432 expected.extend_from_slice(b"42");
1433
1434 assert_eq!(buffer, expected,);
1435 }
1436
1437 #[diesel_test_helper::test]
1438 #[cfg(not(miri))] fn jsonb_to_sql_bool() {
1440 let conn = &mut connection();
1441 let res = diesel::select(json!(true).into_sql::<Jsonb>().eq(&sql("jsonb('true')")))
1442 .get_result::<bool>(conn)
1443 .unwrap();
1444 assert!(res);
1445 }
1446
1447 #[diesel_test_helper::test]
1448 #[cfg(not(miri))] fn jsonb_to_sql_null() {
1450 let conn = &mut connection();
1451 let res = diesel::select(json!(null).into_sql::<Jsonb>().eq(&sql("jsonb('null')")))
1452 .get_result::<bool>(conn)
1453 .unwrap();
1454 assert!(res);
1455 }
1456
1457 #[diesel_test_helper::test]
1458 #[cfg(not(miri))] fn jsonb_to_sql_integer() {
1460 let conn = &mut connection();
1461 let res = diesel::select(json!(42).into_sql::<Jsonb>().eq(&sql("jsonb('42')")))
1462 .get_result::<bool>(conn)
1463 .unwrap();
1464 assert!(res);
1465 }
1466
1467 #[diesel_test_helper::test]
1468 #[cfg(not(miri))] fn jsonb_to_sql_float() {
1470 let conn = &mut connection();
1471 let res = diesel::select(json!(42.23).into_sql::<Jsonb>().eq(&sql("jsonb('42.23')")))
1472 .get_result::<bool>(conn)
1473 .unwrap();
1474 assert!(res);
1475 }
1476
1477 #[diesel_test_helper::test]
1478 #[cfg(not(miri))] fn jsonb_to_sql_text() {
1480 let conn = &mut connection();
1481
1482 let res = diesel::select(
1484 json!("hello")
1485 .into_sql::<Jsonb>()
1486 .eq(&sql(r#"jsonb('"hello"')"#)),
1487 )
1488 .get_result::<bool>(conn)
1489 .unwrap();
1490
1491 assert!(res);
1492 }
1493
1494 #[diesel_test_helper::test]
1495 #[cfg(not(miri))] fn jsonb_to_sql_textj() {
1497 let conn = &mut connection();
1498
1499 let res = diesel::select(
1501 json!("hello\nworld")
1502 .into_sql::<Jsonb>()
1503 .eq(&sql(r#"jsonb('"hello\nworld"')"#)), )
1505 .get_result::<bool>(conn)
1506 .unwrap();
1507
1508 assert!(res);
1509 }
1510
1511 #[diesel_test_helper::test]
1512 #[cfg(not(miri))] fn jsonb_to_sql_textj_quote_and_backslash() {
1514 let conn = &mut connection();
1515
1516 let res = diesel::select(
1518 json!(r#"a"b\c"#)
1519 .into_sql::<Jsonb>()
1520 .eq(&sql(r#"jsonb('"a\"b\\c"')"#)),
1521 )
1522 .get_result::<bool>(conn)
1523 .unwrap();
1524
1525 assert!(res);
1526 }
1527
1528 #[diesel_test_helper::test]
1529 #[cfg(not(miri))] fn jsonb_to_sql_array() {
1531 let conn = &mut connection();
1532 let res = diesel::select(
1533 json!([1, true, "foo"])
1534 .into_sql::<Jsonb>()
1535 .eq(&sql(r#"jsonb('[1, true, "foo"]')"#)),
1536 )
1537 .get_result::<bool>(conn)
1538 .unwrap();
1539 assert!(res);
1540 }
1541
1542 #[diesel_test_helper::test]
1543 #[cfg(not(miri))] fn jsonb_to_sql_object() {
1545 let conn = &mut connection();
1546 let res = diesel::select(
1547 json!({"key": "value"})
1548 .into_sql::<Jsonb>()
1549 .eq(&sql(r#"jsonb('{"key": "value"}')"#)),
1550 )
1551 .get_result::<bool>(conn)
1552 .unwrap();
1553 assert!(res);
1554 }
1555
1556 #[diesel_test_helper::test]
1557 #[cfg(not(miri))] fn jsonb_to_sql_object_in_object() {
1559 let conn = &mut connection();
1560 let json_value = json!({
1561 "outer_key": {
1562 "additional_key": true,
1563 "inner_key": {
1564 "nested_key": 42
1565 },
1566 }
1567 });
1568
1569 let res = diesel::select(json_value.into_sql::<Jsonb>().eq(&sql(
1570 r#"jsonb('{"outer_key": {"additional_key": true, "inner_key": {"nested_key": 42}}}')"#,
1571 )))
1572 .get_result::<bool>(conn)
1573 .unwrap();
1574 assert!(res);
1575 }
1576
1577 #[diesel_test_helper::test]
1578 #[cfg(not(miri))] fn jsonb_to_sql_array_in_object() {
1580 let conn = &mut connection();
1581 let json_value = json!({
1582 "is_valid": false,
1583 "key": [1, 2, 3],
1584 });
1585 let res = diesel::select(
1586 json_value
1587 .into_sql::<Jsonb>()
1588 .eq(&sql(r#"jsonb('{"is_valid": false, "key": [1, 2, 3]}')"#)),
1589 )
1590 .get_result::<bool>(conn)
1591 .unwrap();
1592 assert!(res);
1593 }
1594
1595 #[diesel_test_helper::test]
1596 #[cfg(not(miri))] fn jsonb_to_sql_object_in_array() {
1598 let conn = &mut connection();
1599 let json_value = json!([
1600 {
1601 "nested_key": "nested_value"
1602 },
1603 {
1604 "int_value": 99
1605 }
1606 ]);
1607 let res = diesel::select(json_value.into_sql::<Jsonb>().eq(&sql(
1608 r#"jsonb('[{"nested_key": "nested_value"}, {"int_value": 99}]')"#,
1609 )))
1610 .get_result::<bool>(conn)
1611 .unwrap();
1612 assert!(res);
1613 }
1614
1615 #[diesel_test_helper::test]
1616 #[cfg(not(miri))] fn jsonb_from_sql_null() {
1618 let conn = &mut connection();
1619 let res = diesel::select(sql::<Jsonb>("jsonb('null')"))
1620 .get_result::<serde_json::Value>(conn)
1621 .unwrap();
1622 assert_eq!(res, serde_json::json!(null));
1623 }
1624
1625 #[diesel_test_helper::test]
1626 #[cfg(not(miri))] fn jsonb_from_sql_true() {
1628 let conn = &mut connection();
1629 let res = diesel::select(sql::<Jsonb>("jsonb('true')"))
1630 .get_result::<serde_json::Value>(conn)
1631 .unwrap();
1632 assert_eq!(res, serde_json::json!(true));
1633 }
1634
1635 #[diesel_test_helper::test]
1636 #[cfg(not(miri))] fn jsonb_from_sql_false() {
1638 let conn = &mut connection();
1639 let res = diesel::select(sql::<Jsonb>("jsonb('false')"))
1640 .get_result::<serde_json::Value>(conn)
1641 .unwrap();
1642 assert_eq!(res, serde_json::json!(false));
1643 }
1644
1645 #[diesel_test_helper::test]
1646 #[cfg(not(miri))] fn jsonb_from_sql_int() {
1648 let conn = &mut connection();
1649 let res = diesel::select(sql::<Jsonb>("jsonb('42')"))
1650 .get_result::<serde_json::Value>(conn)
1651 .unwrap();
1652 assert_eq!(res, serde_json::json!(42));
1653 }
1654
1655 #[diesel_test_helper::test]
1656 #[cfg(not(miri))] fn jsonb_from_sql_float() {
1658 let conn = &mut connection();
1659 let res = diesel::select(sql::<Jsonb>("jsonb('42.23')"))
1660 .get_result::<serde_json::Value>(conn)
1661 .unwrap();
1662 assert_eq!(res, serde_json::json!(42.23));
1663 }
1664
1665 #[diesel_test_helper::test]
1666 #[cfg(not(miri))] fn jsonb_from_sql_object() {
1668 let conn = &mut connection();
1669 let res = diesel::select(sql::<Jsonb>(r#"jsonb('{"key": "value"}')"#))
1670 .get_result::<serde_json::Value>(conn)
1671 .unwrap();
1672 assert_eq!(res, serde_json::json!({"key": "value"}));
1673 }
1674
1675 #[diesel_test_helper::test]
1676 #[cfg(not(miri))] fn jsonb_from_sql_array() {
1678 let conn = &mut connection();
1679 let res = diesel::select(sql::<Jsonb>("jsonb('[1, 2, 3]')"))
1680 .get_result::<serde_json::Value>(conn)
1681 .unwrap();
1682 assert_eq!(res, serde_json::json!([1, 2, 3]));
1683 }
1684
1685 #[diesel_test_helper::test]
1686 #[cfg(not(miri))] fn jsonb_from_sql_nested_objects() {
1688 let conn = &mut connection();
1689 let res = diesel::select(sql::<Jsonb>(r#"jsonb('{"outer": {"inner": 42}}')"#))
1690 .get_result::<serde_json::Value>(conn)
1691 .unwrap();
1692 assert_eq!(res, serde_json::json!({"outer": {"inner": 42}}));
1693 }
1694
1695 #[diesel_test_helper::test]
1696 #[cfg(not(miri))] fn jsonb_from_sql_nested_arrays() {
1698 let conn = &mut connection();
1699 let res = diesel::select(sql::<Jsonb>("jsonb('[[1, 2], [3, 4]]')"))
1700 .get_result::<serde_json::Value>(conn)
1701 .unwrap();
1702 assert_eq!(res, serde_json::json!([[1, 2], [3, 4]]));
1703 }
1704
1705 #[diesel_test_helper::test]
1706 #[cfg(not(miri))] fn jsonb_from_sql_nested_arrays_in_objects() {
1708 let conn = &mut connection();
1709 let res = diesel::select(sql::<Jsonb>(r#"jsonb('{"array": [1, 2, 3]}')"#))
1710 .get_result::<serde_json::Value>(conn)
1711 .unwrap();
1712 assert_eq!(res, serde_json::json!({"array": [1, 2, 3]}));
1713 }
1714
1715 #[diesel_test_helper::test]
1716 #[cfg(not(miri))] fn jsonb_from_sql_nested_objects_in_arrays() {
1718 let conn = &mut connection();
1719 let res = diesel::select(sql::<Jsonb>(
1720 r#"jsonb('[{"key1": "value1"}, {"key2": "value2"}]')"#,
1721 ))
1722 .get_result::<serde_json::Value>(conn)
1723 .unwrap();
1724 assert_eq!(
1725 res,
1726 serde_json::json!([{"key1": "value1"}, {"key2": "value2"}])
1727 );
1728 }
1729
1730 #[diesel_test_helper::test]
1731 #[cfg(not(miri))] fn jsonb_from_sql_text() {
1733 let conn = &mut connection();
1734 let res = diesel::select(sql::<Jsonb>(r#"jsonb('"hello"')"#))
1735 .get_result::<serde_json::Value>(conn)
1736 .unwrap();
1737 assert_eq!(res, serde_json::json!("hello"));
1738 }
1739
1740 #[diesel_test_helper::test]
1741 #[cfg(not(miri))] fn jsonb_from_sql_textj() {
1743 let conn = &mut connection();
1744 let res = diesel::select(sql::<Jsonb>(r#"jsonb('"hello\nworld"')"#))
1745 .get_result::<serde_json::Value>(conn)
1746 .unwrap();
1747 assert_eq!(res, serde_json::json!("hello\nworld"));
1748 }
1749
1750 #[diesel_test_helper::test]
1751 #[cfg(not(miri))] fn bad_json_from_sql() {
1753 let conn = &mut connection();
1754 let res = diesel::select(json!(true).into_sql::<Json>().eq(&sql("json('boom')")))
1755 .get_result::<bool>(conn);
1756 assert_eq!(res.unwrap_err().to_string(), "malformed JSON");
1757 }
1758
1759 #[diesel_test_helper::test]
1760 #[cfg(not(miri))] fn bad_jsonb_from_sql() {
1762 let conn = &mut connection();
1763 let res = diesel::select(json!(true).into_sql::<Jsonb>().eq(&sql("jsonb('boom')")))
1764 .get_result::<bool>(conn);
1765 assert_eq!(res.unwrap_err().to_string(), "malformed JSON");
1766 }
1767
1768 #[diesel_test_helper::test]
1769 fn no_json_from_sql() {
1770 let uuid: Result<serde_json::Value, _> = FromSql::<Json, Sqlite>::from_nullable_sql(None);
1771 assert_eq!(
1772 uuid.unwrap_err().to_string(),
1773 "Unexpected null for non-null column"
1774 );
1775 }
1776
1777 #[diesel_test_helper::test]
1778 fn no_jsonb_from_sql() {
1779 let uuid: Result<serde_json::Value, _> = FromSql::<Jsonb, Sqlite>::from_nullable_sql(None);
1780 assert_eq!(
1781 uuid.unwrap_err().to_string(),
1782 "Unexpected null for non-null column"
1783 );
1784 }
1785
1786 #[cfg(all(
1787 not(miri),
1788 not(all(target_family = "wasm", target_os = "unknown")),
1789 unix
1790 ))]
1791 const RECURSION_DEPTH: usize = 2000;
1792
1793 #[cfg(all(
1794 not(miri),
1795 any(windows, all(target_family = "wasm", target_os = "unknown"))
1796 ))]
1797 const RECURSION_DEPTH: usize = 1000;
1798
1799 #[cfg(any(
1800 miri,
1801 all(
1802 not(unix),
1803 not(windows),
1804 not(all(target_family = "wasm", target_os = "unknown"))
1805 )
1806 ))]
1807 const RECURSION_DEPTH: usize = 10;
1808
1809 #[diesel_test_helper::test]
1810 fn guard_against_stackoverflow_array() {
1811 let mut value = serde_json::Value::Number(42.into());
1812 for i in 0..RECURSION_DEPTH {
1813 value = serde_json::Value::Array(vec![value, serde_json::Value::Number(i.into())]);
1814 }
1815 let mut expected_buffer = Vec::new();
1818 write_jsonb_value(&value, &mut expected_buffer).unwrap();
1819 let res = read_jsonb_value(&expected_buffer).unwrap().0;
1820
1821 let mut buffer = Vec::new();
1822 write_jsonb_value(&res, &mut buffer).unwrap();
1823 assert_eq!(expected_buffer, buffer);
1824 }
1825
1826 #[diesel_test_helper::test]
1827 fn guard_against_stackoverflow_object() {
1828 let mut value = serde_json::Value::Number(42.into());
1829 for i in 0..RECURSION_DEPTH {
1830 let mut map = serde_json::Map::new();
1831 map.insert(format!("key_{i}"), value);
1832 value = serde_json::Value::Object(map);
1833 }
1834
1835 let mut expected_buffer = Vec::new();
1838 write_jsonb_value(&value, &mut expected_buffer).unwrap();
1839
1840 let res = read_jsonb_value(&expected_buffer).unwrap().0;
1841
1842 let mut buffer = Vec::new();
1843 write_jsonb_value(&res, &mut buffer).unwrap();
1844 assert_eq!(expected_buffer, buffer);
1845 }
1846
1847 #[diesel_test_helper::test]
1848 fn guard_against_stackoverflow_mixed() {
1849 let mut value = serde_json::Value::Number(42.into());
1850 for i in 0_usize..2000 {
1851 if i.is_multiple_of(2) {
1852 let mut map = serde_json::Map::new();
1853 map.insert(format!("key_{i}"), value);
1854 value = serde_json::Value::Object(map);
1855 } else {
1856 value = serde_json::Value::Array(vec![value]);
1857 }
1858 }
1859 let mut expected_buffer = Vec::new();
1862 write_jsonb_value(&value, &mut expected_buffer).unwrap();
1863 let res = read_jsonb_value(&expected_buffer).unwrap().0;
1864 let mut buffer = Vec::new();
1865 write_jsonb_value(&res, &mut buffer).unwrap();
1866 assert_eq!(expected_buffer, buffer);
1867 }
1868
1869 #[diesel_test_helper::test]
1870 #[cfg(not(miri))] fn dangling_bytes_result_in_error() {
1872 let mut value = Vec::<u8>::new();
1873 value.extend(create_jsonb_header(JSONB_INT, 1).unwrap());
1874 value.push(b'1');
1875 value.push(42);
1876 assert_eq!(value.len(), 3);
1877 let conn = &mut connection();
1878 let res = diesel::select(
1879 crate::dsl::sql::<sql_types::Jsonb>("jsonb(?)").bind::<sql_types::Binary, _>(value),
1880 )
1881 .get_result::<serde_json::Value>(conn);
1882 assert!(res.is_err(), "{:?}", res.unwrap());
1883 }
1884
1885 #[diesel_test_helper::test]
1886 fn object_key_without_value_results_in_error() {
1887 let mut value = Vec::new();
1888 value.extend(create_jsonb_header(JSONB_OBJECT, 2).unwrap());
1889 value.extend(create_jsonb_header(JSONB_TEXT, 1).unwrap());
1890 value.push(b'a');
1891 let res = read_jsonb_value(&value);
1892 assert!(res.is_err(), "{:?}", res.unwrap());
1893 }
1894
1895 #[diesel_test_helper::test]
1896 fn check_invalid_size_header() {
1897 let res = read_jsonb_value(&[0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
1900 assert!(res.is_err());
1901 }
1902
1903 #[diesel_test_helper::test]
1904 fn nested_container_cannot_cross_parent_boundary() {
1905 let res = read_jsonb_value(&[0x3B, 0x1B, 0x1B, JSONB_NULL]);
1906 assert!(res.is_err(), "{:?}", res.unwrap());
1907 }
1908
1909 #[diesel_test_helper::test]
1910 fn check_signed_integer() {
1911 let mut buf = Vec::new();
1912 write_jsonb_value(&json!(-42), &mut buf).unwrap();
1913 let mut expected = create_jsonb_header(JSONB_INT, 3).unwrap();
1914 expected.extend(b"-42");
1915 assert_eq!(buf, expected);
1916 }
1917}