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 use crate::test_helpers::format_error;
649 #[cfg(not(miri))] use crate::{IntoSql, dsl::sql};
651 use serde_json::{Value, json};
652 use sql_types::{Json, Jsonb};
653
654 pub(super) fn create_jsonb_header(
656 element_type: u8,
657 payload_size: usize,
658 ) -> Result<Vec<u8>, Box<dyn core::error::Error + Send + Sync>> {
659 let mut buffer = Vec::new();
660 jsonb::write_jsonb_header(&mut buffer, element_type, payload_size)?;
661 Ok(buffer)
662 }
663
664 fn value_with_payload(element_type: u8, payload: &[u8]) -> Vec<u8> {
665 let mut buffer = create_jsonb_header(element_type, payload.len()).unwrap();
666 buffer.extend_from_slice(payload);
667 buffer
668 }
669
670 #[diesel_test_helper::test]
671 fn regression_a_constant_reads_its_declared_size() {
672 let blobs: Vec<Vec<u8>> = vec![
673 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], {
682 let mut blob = create_jsonb_header(JSONB_ARRAY, 2).unwrap();
684 blob.extend_from_slice(&[0xC1, 0x00]);
685 blob
686 },
687 {
688 let mut blob = create_jsonb_header(JSONB_OBJECT, 4).unwrap();
690 blob.extend(create_jsonb_header(JSONB_TEXT, 1).unwrap());
691 blob.extend_from_slice(b"a");
692 blob.extend_from_slice(&[0xC1, 0x00]);
693 blob
694 },
695 ];
696 for blob in blobs {
697 let blob: &[u8] = &blob;
698 assert!(
699 read_jsonb_value(blob).is_err(),
700 "{blob:02X?} decoded to {:?}",
701 read_jsonb_value(blob).map(|value| value.0)
702 );
703 }
704
705 let mut blob = create_jsonb_header(JSONB_ARRAY, 2).unwrap();
707 blob.extend(create_jsonb_header(JSONB_TRUE, 0).unwrap());
708 blob.extend(create_jsonb_header(JSONB_NULL, 0).unwrap());
709 assert_eq!(read_jsonb_value(&blob).unwrap().0, json!([true, null]));
710 }
711
712 #[diesel_test_helper::test]
713 #[cfg(not(miri))] fn regression_json_text_float_survives_a_round_trip() {
715 let conn = &mut connection();
716 for float in [
717 8.829872855928286e-308f64,
718 -0.20221894534048165,
719 1.7383394626966921e-307,
720 6.178787134922198e305,
721 ] {
722 let value = json!(float);
723 let text = diesel::select(sql::<sql_types::Text>("").bind::<sql_types::Json, _>(value))
724 .get_result::<String>(conn)
725 .unwrap();
726 let back = diesel::select(sql::<sql_types::Json>("").bind::<sql_types::Text, _>(text))
727 .get_result::<Value>(conn)
728 .unwrap();
729 assert_eq!(back.as_f64().map(f64::to_bits), Some(float.to_bits()));
730 }
731 }
732
733 #[diesel_test_helper::test]
734 #[cfg(not(miri))] fn regression_float_keeps_its_bits_through_the_writers_text() {
736 let conn = &mut connection();
737 let mut assert_roundtrip = |value: Value| {
738 let expected = value.as_f64().unwrap();
739 let blob = diesel::select(sql::<sql_types::Binary>("").bind::<Jsonb, _>(value))
740 .get_result::<Vec<u8>>(conn)
741 .unwrap();
742 let back = diesel::select(sql::<Jsonb>("").bind::<sql_types::Binary, _>(blob))
743 .get_result::<Value>(conn)
744 .unwrap();
745 assert_eq!(
746 back.as_f64().unwrap().to_bits(),
747 expected.to_bits(),
748 "{expected:?} came back as {back}"
749 );
750 };
751
752 assert_roundtrip(serde_json::from_str("-922333372720360.5975808").unwrap());
754
755 for f in [
756 -0.20221894534048165,
758 6.178787134922198e305,
759 -5.276099561814224e214,
760 3.587959730897931e-246,
761 9.136353238902674e-45,
762 2.4261860608815182e-160,
763 -2.5496151068102186e-175,
764 5.0513463356317975e-231,
765 0.1,
767 1e-7,
768 5e-324,
769 -0.0,
770 f64::MAX,
771 f64::MIN_POSITIVE,
772 ] {
773 assert_roundtrip(json!(f));
774 }
775 }
776
777 #[diesel_test_helper::test]
778 fn regression_every_float_text_reads_back_as_the_same_double() {
779 let mut drifted = Vec::new();
780 let mut check = |bits: u64| {
781 let f = f64::from_bits(bits);
782 if !f.is_finite() {
783 return;
784 }
785 let mut buffer = Vec::new();
786 write_jsonb_number(&json!(f), &mut buffer).unwrap();
787 let back = read_jsonb_value(&buffer).unwrap().0;
788 if back.as_f64().map(f64::to_bits) != Some(bits) {
789 drifted.push(alloc::format!("{bits:#018x} {f:?} -> {back}"));
790 }
791 };
792
793 for exponent in [0, 1, 2, 512, 1021, 1022, 1023, 1024, 1075, 2045, 2046] {
794 for mantissa in [0, 1, 2, 1 << 26, 1 << 51, (1 << 52) - 2, (1 << 52) - 1] {
795 for sign in [0, 1u64 << 63] {
796 check(sign | (exponent << 52) | mantissa);
797 }
798 }
799 }
800
801 let witness = serde_json::from_str::<Value>("-922333372720360.5975808")
803 .unwrap()
804 .as_f64()
805 .unwrap()
806 .to_bits();
807 for bits in witness - 2..=witness + 2 {
808 check(bits);
809 }
810
811 let mut state: u64 = 0x2545F4914F6CDD1D;
813 for _ in 0..256 {
814 state ^= state << 13;
815 state ^= state >> 7;
816 state ^= state << 17;
817 check(state);
818 }
819
820 assert!(
821 drifted.is_empty(),
822 "{} floats drifted, first {:?}",
823 drifted.len(),
824 &drifted[..drifted.len().min(4)]
825 );
826 }
827
828 #[diesel_test_helper::test]
829 #[cfg(not(miri))] fn every_jsonb_number_is_written_valid_and_round_trips() {
831 let conn = &mut connection();
832
833 let numbers = [
836 (json!(0), JSONB_INT),
837 (json!(1), JSONB_INT),
838 (json!(-1), JSONB_INT),
839 (json!(-5), JSONB_INT),
840 (json!(u64::from(u32::MAX)), JSONB_INT),
841 (json!(i64::MAX), JSONB_INT),
842 (json!(i64::MIN), JSONB_INT),
843 (json!(1u64 << 63), JSONB_INT),
844 (json!(u64::MAX), JSONB_INT),
845 (json!(3.0), JSONB_FLOAT),
846 (json!(-0.0), JSONB_FLOAT),
847 (json!(-2.5), JSONB_FLOAT),
848 (json!(1e-7), JSONB_FLOAT),
849 (json!(1e300), JSONB_FLOAT),
850 (json!(-1e300), JSONB_FLOAT),
851 (json!(1.5e300), JSONB_FLOAT),
852 (json!(1e21), JSONB_FLOAT),
853 (json!(f64::MIN), JSONB_FLOAT),
854 (json!(f64::MAX), JSONB_FLOAT),
855 (json!(f64::MIN_POSITIVE), JSONB_FLOAT),
856 ];
857
858 for (value, element_type) in numbers {
859 let blob = diesel::select(sql::<sql_types::Binary>("").bind::<Jsonb, _>(value.clone()))
860 .get_result::<Vec<u8>>(conn)
861 .unwrap();
862 assert_eq!(
863 blob[0] & 0x0F,
864 element_type,
865 "{value} was written with the wrong element type: {blob:02X?}"
866 );
867 let valid = diesel::select(json_valid_with_flags::<sql_types::Binary, _, _>(
868 blob.as_slice(),
869 JsonValidFlag::JsonbStrict,
870 ))
871 .get_result::<bool>(conn)
872 .unwrap();
873 assert!(
874 valid,
875 "sqlite rejects the blob written for {value}: {blob:02X?}"
876 );
877 let back = diesel::select(sql::<Jsonb>("").bind::<sql_types::Binary, _>(blob.clone()))
878 .get_result::<Value>(conn)
879 .unwrap_or_else(|error| panic!("{value} does not read back: {error}"));
880 assert_eq!(back, value, "{blob:02X?}");
881 }
882 }
883
884 #[cfg(not(miri))] fn jsonb_survives(conn: &mut crate::SqliteConnection, value: &Value) -> Result<(), String> {
887 let blob = diesel::select(sql::<sql_types::Binary>("").bind::<Jsonb, _>(value.clone()))
888 .get_result::<Vec<u8>>(conn)
889 .unwrap();
890 let valid = diesel::select(json_valid_with_flags::<sql_types::Binary, _, _>(
891 blob.as_slice(),
892 JsonValidFlag::JsonbStrict,
893 ))
894 .get_result::<bool>(conn)
895 .unwrap();
896 let back = diesel::select(sql::<Jsonb>("").bind::<sql_types::Binary, _>(blob.clone()))
897 .get_result::<Value>(conn);
898 if !valid {
899 return Err(alloc::format!(
900 "sqlite calls {value} malformed as {blob:02X?}"
901 ));
902 }
903 match back {
904 Ok(ref back) if back == value => Ok(()),
905 Ok(back) => Err(alloc::format!("{value} came back as {back}")),
906 Err(e) => Err(alloc::format!("{value} came back as {e}")),
907 }
908 }
909
910 #[diesel_test_helper::test]
911 #[cfg(not(miri))] fn regression_string_needing_an_escape_is_written_valid() {
913 let conn = &mut connection();
914 for value in [
915 json!(r#"a"b"#),
916 json!(r#"a\b"#),
917 json!(r#"a"\b"#),
918 json!(r#"""#),
919 json!(r#"\"#),
920 json!(r#"\""#),
921 json!(r#""leading"#),
922 json!(r#"trailing""#),
923 json!(r#"aaaaaaaaaaaa"bbbbbbbbbbbb"#),
924 json!({ "k": r#"a"b"# }),
925 json!([r#"a\b"#]),
926 json!({ r#"a"b"#: 1 }),
927 json!(""),
928 json!("abc"),
929 json!("a\nb"),
930 json!("a\"\nb"),
931 ] {
932 jsonb_survives(conn, &value).unwrap_or_else(|e| panic!("{e}"));
933 }
934 }
935
936 #[diesel_test_helper::test]
937 fn test_write_jsonb_number_classifies_by_integer_text() {
938 for (value, element_type, payload) in [
940 (json!(0), JSONB_INT, "0"),
941 (json!(-1), JSONB_INT, "-1"),
942 (json!(i64::MIN), JSONB_INT, "-9223372036854775808"),
943 (json!(u64::MAX), JSONB_INT, "18446744073709551615"),
944 (json!(3.0), JSONB_FLOAT, "3.0"),
945 (json!(-0.0), JSONB_FLOAT, "-0.0"),
946 (json!(-2.5), JSONB_FLOAT, "-2.5"),
947 (json!(1e-7), JSONB_FLOAT, "1e-7"),
948 (json!(1e300), JSONB_FLOAT, "1e+300"),
949 ] {
950 let mut buffer = Vec::new();
951 write_jsonb_value(&value, &mut buffer).unwrap();
952
953 let mut expected = create_jsonb_header(element_type, payload.len()).unwrap();
954 expected.extend_from_slice(payload.as_bytes());
955
956 assert_eq!(buffer, expected, "{value} was not written as {payload}");
957 }
958 }
959
960 #[diesel_test_helper::test]
961 #[cfg(not(miri))] fn numbers_nested_in_containers_are_written_valid() {
963 let conn = &mut connection();
964 let value = json!({"a": -1, "b": [-2, -2.5, 1e-7, 0, u64::MAX], "c": {"d": i64::MIN}});
965
966 let blob = diesel::select(sql::<sql_types::Binary>("").bind::<Jsonb, _>(value.clone()))
967 .get_result::<Vec<u8>>(conn)
968 .unwrap();
969 let valid = diesel::select(
970 sql::<sql_types::Integer>("json_valid(")
971 .bind::<sql_types::Binary, _>(blob.clone())
972 .sql(", 8)"),
973 )
974 .get_result::<i32>(conn)
975 .unwrap();
976 assert_eq!(valid, 1, "sqlite rejects {blob:02X?}");
977
978 let back = diesel::select(sql::<Jsonb>("").bind::<sql_types::Binary, _>(blob))
979 .get_result::<Value>(conn)
980 .unwrap();
981 assert_eq!(back, value);
982 }
983
984 #[diesel_test_helper::test]
985 fn test_read_jsonb_int_decodes_the_whole_representable_range() {
986 for (payload, expected) in [
987 (&b"0"[..], json!(0)),
988 (&b"1"[..], json!(1)),
989 (&b"-1"[..], json!(-1)),
990 (&b"-0"[..], json!(0)),
992 (&b"9223372036854775807"[..], json!(i64::MAX)),
993 (&b"-9223372036854775808"[..], json!(i64::MIN)),
994 (&b"9223372036854775808"[..], json!(1u64 << 63)),
995 (&b"18446744073709551615"[..], json!(u64::MAX)),
996 ] {
997 let mut data = create_jsonb_header(JSONB_INT, payload.len()).unwrap();
998 data.extend_from_slice(payload);
999
1000 let payload = core::str::from_utf8(payload).unwrap();
1001 assert_eq!(
1002 read_jsonb_value(&data).unwrap().0,
1003 expected,
1004 "{payload} did not decode to itself"
1005 );
1006 }
1007 }
1008
1009 #[diesel_test_helper::test]
1010 #[cfg(not(miri))] fn regression_every_char_is_written_valid() {
1012 let conn = &mut connection();
1013 let mut offenders = Vec::new();
1014 let mut chunk = Vec::new();
1016 for code in 0u32..=0x10FFFF {
1017 if let Some(c) = char::from_u32(code) {
1018 let mut s = alloc::string::String::from('a');
1019 s.push(c);
1020 s.push('b');
1021 chunk.push(json!(s));
1022 }
1023 if chunk.len() < 2048 && code != 0x10FFFF {
1024 continue;
1025 }
1026 let batch = Value::Array(core::mem::take(&mut chunk));
1027 if let Err(batch_error) = jsonb_survives(conn, &batch) {
1028 let Value::Array(values) = batch else {
1029 unreachable!()
1030 };
1031 let known = offenders.len();
1032 for value in values {
1033 if let Err(e) = jsonb_survives(conn, &value) {
1034 offenders.push(e);
1035 }
1036 }
1037 if offenders.len() == known {
1039 offenders.push(batch_error);
1040 }
1041 }
1042 }
1043 assert!(
1044 offenders.is_empty(),
1045 "{} values broke the blob, first {:?}",
1046 offenders.len(),
1047 &offenders[..offenders.len().min(4)]
1048 );
1049 }
1050
1051 #[diesel_test_helper::test]
1052 fn test_read_jsonb_int_rejects_non_integer_payloads() {
1053 for payload in [
1054 &b"1.5"[..],
1056 &b"1e5"[..],
1057 &b"1e999"[..],
1059 &b"+1"[..],
1061 &b"01"[..],
1062 &b""[..],
1063 &b"-"[..],
1064 &b"0x10"[..],
1065 &b"nan"[..],
1066 &b"Infinity"[..],
1067 ] {
1068 let mut data = create_jsonb_header(JSONB_INT, payload.len()).unwrap();
1069 data.extend_from_slice(payload);
1070
1071 let payload = core::str::from_utf8(payload).unwrap();
1072 assert!(
1073 read_jsonb_value(&data).is_err(),
1074 "{payload} is not a JSONB integer"
1075 );
1076 }
1077 }
1078
1079 #[diesel_test_helper::test]
1080 fn test_read_jsonb_int_decodes_a_wide_integer_exactly_or_not_at_all() {
1081 for payload in [
1085 &b"18446744073709551616"[..],
1086 &b"123456789012345678901234567890"[..],
1087 ] {
1088 let mut data = create_jsonb_header(JSONB_INT, payload.len()).unwrap();
1089 data.extend_from_slice(payload);
1090
1091 let payload = core::str::from_utf8(payload).unwrap();
1092 let exact = serde_json::Number::from_u128(payload.parse().unwrap()).map(Value::Number);
1093 let decoded = read_jsonb_value(&data);
1094
1095 match exact {
1096 Some(expected) => assert_eq!(
1097 decoded.unwrap().0,
1098 expected,
1099 "{payload} is representable and must decode"
1100 ),
1101 None => assert!(decoded.is_err(), "{payload} would decode rounded"),
1102 }
1103 }
1104 }
1105
1106 #[diesel_test_helper::test]
1107 fn test_read_jsonb_int_above_i64_max_inside_containers() {
1108 let mut element = create_jsonb_header(JSONB_INT, 20).unwrap();
1109 element.extend_from_slice(b"18446744073709551615");
1110
1111 let mut array = create_jsonb_header(JSONB_ARRAY, element.len()).unwrap();
1112 array.extend_from_slice(&element);
1113 assert_eq!(read_jsonb_value(&array).unwrap().0, json!([u64::MAX]));
1114
1115 let mut key = create_jsonb_header(JSONB_TEXT, 1).unwrap();
1116 key.extend_from_slice(b"a");
1117 let mut object = create_jsonb_header(JSONB_OBJECT, key.len() + element.len()).unwrap();
1118 object.extend_from_slice(&key);
1119 object.extend_from_slice(&element);
1120 assert_eq!(read_jsonb_value(&object).unwrap().0, json!({"a": u64::MAX}));
1121 }
1122
1123 #[diesel_test_helper::test]
1124 #[cfg(not(miri))] fn regression_unsigned_above_i64_reads_a_blob_sqlite_wrote() {
1126 let conn = &mut connection();
1127
1128 let back = diesel::select(sql::<Jsonb>("jsonb('18446744073709551615')"))
1129 .get_result::<Value>(conn)
1130 .unwrap();
1131
1132 assert_eq!(back, json!(u64::MAX));
1133 }
1134
1135 #[diesel_test_helper::test]
1136 #[cfg(not(miri))] fn regression_negative_zero_reads_a_blob_sqlite_wrote() {
1138 let conn = &mut connection();
1139
1140 let back = diesel::select(sql::<Jsonb>("jsonb('-0')"))
1141 .get_result::<Value>(conn)
1142 .unwrap();
1143
1144 assert_eq!(back, json!(0));
1145 }
1146
1147 #[diesel_test_helper::test]
1148 #[cfg(not(miri))] fn json_to_sql() {
1150 let conn = &mut connection();
1151 let res = diesel::select(json!(true).into_sql::<Json>().eq(&sql("json('true')")))
1152 .get_result::<bool>(conn)
1153 .unwrap();
1154 assert!(res);
1155 }
1156
1157 #[diesel_test_helper::test]
1158 fn test_read_jsonb_null() {
1159 let data = vec![JSONB_NULL];
1160 let result = read_jsonb_value(&data).unwrap().0;
1161 assert_eq!(result, Value::Null);
1162 }
1163
1164 #[diesel_test_helper::test]
1165 fn test_read_jsonb_true() {
1166 let data = vec![JSONB_TRUE];
1167 let result = read_jsonb_value(&data).unwrap().0;
1168 assert_eq!(result, Value::Bool(true));
1169 }
1170
1171 #[diesel_test_helper::test]
1172 fn test_read_jsonb_false() {
1173 let data = vec![JSONB_FALSE];
1174 let result = read_jsonb_value(&data).unwrap().0;
1175 assert_eq!(result, Value::Bool(false));
1176 }
1177
1178 #[diesel_test_helper::test]
1179 fn test_read_jsonb_int() {
1180 let mut data = Vec::new();
1182 data.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
1183 data.push(b'1'); let result = read_jsonb_value(&data).unwrap().0;
1186 assert_eq!(result, json!(1));
1187 }
1188
1189 #[diesel_test_helper::test]
1190 fn test_read_jsonb_float() {
1191 let mut data = Vec::new();
1193 data.extend(create_jsonb_header(JSONB_FLOAT, 0x03).unwrap());
1194 data.extend_from_slice(b"1.5"); let result = read_jsonb_value(&data).unwrap().0;
1197 assert_eq!(result, json!(1.5));
1198 }
1199
1200 #[diesel_test_helper::test]
1201 fn test_read_jsonb_text() {
1202 let mut data = Vec::new();
1204 data.extend(create_jsonb_header(JSONB_TEXT, 0x03).unwrap());
1205 data.extend_from_slice(b"foo"); let result = read_jsonb_value(&data).unwrap().0;
1208 assert_eq!(result, json!("foo"));
1209 }
1210
1211 #[diesel_test_helper::test]
1212 fn test_read_jsonb_textraw() {
1213 let mut data = Vec::new();
1215 data.extend(create_jsonb_header(JSONB_TEXTRAW, 0x03).unwrap());
1216 data.extend_from_slice(b"foo");
1217
1218 let result = read_jsonb_value(&data).unwrap().0;
1219 assert_eq!(result, json!("foo"));
1220 }
1221
1222 #[diesel_test_helper::test]
1223 fn test_read_jsonb_object_with_textraw_key() {
1224 let mut data = Vec::new();
1226 data.extend(create_jsonb_header(JSONB_OBJECT, 0x06).unwrap());
1227 data.extend(create_jsonb_header(JSONB_TEXTRAW, 0x01).unwrap());
1228 data.extend_from_slice(b"a");
1229 data.extend(create_jsonb_header(JSONB_TEXTRAW, 0x03).unwrap());
1230 data.extend_from_slice(b"bar");
1231
1232 let result = read_jsonb_value(&data).unwrap().0;
1233 assert_eq!(result, json!({"a": "bar"}));
1234 }
1235
1236 #[diesel_test_helper::test]
1237 fn test_read_jsonb_array() {
1238 let mut data = Vec::new();
1240 data.extend(create_jsonb_header(JSONB_ARRAY, 0x03).unwrap()); data.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
1244 data.push(b'1');
1245
1246 data.extend(create_jsonb_header(JSONB_TRUE, 0x00).unwrap());
1248
1249 let result = read_jsonb_value(&data).unwrap().0;
1250 assert_eq!(result, json!([1, true]));
1251 }
1252
1253 #[diesel_test_helper::test]
1254 fn test_read_jsonb_object() {
1255 let mut data = Vec::new();
1257 data.extend(create_jsonb_header(JSONB_OBJECT, 0x07).unwrap()); data.extend(create_jsonb_header(JSONB_TEXT, 0x03).unwrap());
1261 data.extend_from_slice(b"key"); data.extend(create_jsonb_header(JSONB_INT, 0x02).unwrap());
1265 data.extend_from_slice(b"42"); let result = read_jsonb_value(&data).unwrap().0;
1268 assert_eq!(result, json!({"key": 42}));
1269 }
1270
1271 #[diesel_test_helper::test]
1272 fn test_read_jsonb_nested_object() {
1273 let mut data = Vec::new();
1274
1275 data.extend(create_jsonb_header(JSONB_OBJECT, 42).unwrap());
1276
1277 data.extend(create_jsonb_header(JSONB_TEXT, 9).unwrap());
1278 data.extend_from_slice(b"outer_key");
1279
1280 data.extend(create_jsonb_header(JSONB_OBJECT, 13).unwrap());
1281
1282 data.extend(create_jsonb_header(JSONB_TEXT, 9).unwrap());
1283 data.extend_from_slice(b"inner_key");
1284
1285 data.extend(create_jsonb_header(JSONB_INT, 2).unwrap());
1286 data.extend_from_slice(b"42");
1287
1288 data.extend(create_jsonb_header(JSONB_TEXT, 14).unwrap());
1289 data.extend_from_slice(b"additional_key");
1290
1291 data.extend(create_jsonb_header(JSONB_TRUE, 0).unwrap());
1292
1293 let result = read_jsonb_value(&data).unwrap().0;
1294 assert_eq!(
1295 result,
1296 json!({
1297 "additional_key": true,
1298 "outer_key": {
1299 "inner_key": 42
1300 },
1301 })
1302 );
1303 }
1304
1305 #[diesel_test_helper::test]
1306 fn test_write_jsonb_null() {
1307 let value = serde_json::Value::Null;
1308 let mut buffer = Vec::new();
1309 write_jsonb_value(&value, &mut buffer).unwrap();
1310 assert_eq!(buffer, vec![JSONB_NULL]);
1311 }
1312
1313 #[diesel_test_helper::test]
1314 fn test_write_jsonb_true() {
1315 let value = serde_json::Value::Bool(true);
1316 let mut buffer = Vec::new();
1317 write_jsonb_value(&value, &mut buffer).unwrap();
1318 assert_eq!(buffer, vec![JSONB_TRUE]);
1319 }
1320
1321 #[diesel_test_helper::test]
1322 fn test_write_jsonb_false() {
1323 let value = serde_json::Value::Bool(false);
1324 let mut buffer = Vec::new();
1325 write_jsonb_value(&value, &mut buffer).unwrap();
1326 assert_eq!(buffer, vec![JSONB_FALSE]);
1327 }
1328
1329 #[diesel_test_helper::test]
1330 fn test_write_jsonb_int() {
1331 let value = serde_json::Value::Number(serde_json::Number::from(1));
1332 let mut buffer = Vec::new();
1333 write_jsonb_value(&value, &mut buffer).unwrap();
1334
1335 let mut expected_buffer = Vec::new();
1336 expected_buffer.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
1337 expected_buffer.push(b'1'); assert_eq!(buffer, expected_buffer);
1340 }
1341
1342 #[diesel_test_helper::test]
1343 fn test_write_jsonb_float() {
1344 let value = serde_json::Value::Number(serde_json::Number::from_f64(1.5).unwrap());
1345 let mut buffer = Vec::new();
1346 write_jsonb_value(&value, &mut buffer).unwrap();
1347
1348 let mut expected_buffer = Vec::new();
1349 expected_buffer.extend(create_jsonb_header(JSONB_FLOAT, 0x03).unwrap());
1350 expected_buffer.extend_from_slice(b"1.5"); assert_eq!(buffer, expected_buffer);
1353 }
1354
1355 #[diesel_test_helper::test]
1356 fn test_write_jsonb_text() {
1357 let mut buffer = Vec::new();
1358 let input_string = "hello";
1359 write_jsonb_string(input_string, &mut buffer).unwrap();
1360
1361 let mut expected_buffer = Vec::new();
1362 expected_buffer.extend(create_jsonb_header(JSONB_TEXT, 0x05).unwrap());
1363 expected_buffer.extend_from_slice(b"hello");
1364
1365 assert_eq!(buffer, expected_buffer);
1366 }
1367
1368 #[diesel_test_helper::test]
1369 fn test_write_jsonb_textj() {
1370 let mut buffer = Vec::new();
1371 let input_string = "hello\nworld"; write_jsonb_string(input_string, &mut buffer).unwrap();
1373
1374 let mut expected_buffer = Vec::new();
1375 expected_buffer.extend(create_jsonb_header(JSONB_TEXTJ, 12).unwrap());
1376 expected_buffer.extend_from_slice(b"hello\\nworld");
1377
1378 assert_eq!(buffer, expected_buffer);
1379 }
1380
1381 #[diesel_test_helper::test]
1382 fn test_write_jsonb_textj_quote_and_backslash() {
1383 let mut buffer = Vec::new();
1384 let input_string = r#"a"b\c"#;
1385 write_jsonb_string(input_string, &mut buffer).unwrap();
1386
1387 let mut expected_buffer = Vec::new();
1388 expected_buffer.extend(create_jsonb_header(JSONB_TEXTJ, 7).unwrap());
1389 expected_buffer.extend_from_slice(br#"a\"b\\c"#);
1390
1391 assert_eq!(buffer, expected_buffer);
1392 }
1393
1394 #[diesel_test_helper::test]
1395 fn test_write_jsonb_text_keeps_high_control_free_text() {
1396 let mut buffer = Vec::new();
1398 write_jsonb_string("a\u{7f}b", &mut buffer).unwrap();
1399
1400 let mut expected_buffer = Vec::new();
1401 expected_buffer.extend(create_jsonb_header(JSONB_TEXT, 3).unwrap());
1402 expected_buffer.extend_from_slice("a\u{7f}b".as_bytes());
1403
1404 assert_eq!(buffer, expected_buffer);
1405 }
1406
1407 #[diesel_test_helper::test]
1408 fn test_write_jsonb_array() {
1409 let value = json!([1, true]);
1410 let mut buffer = Vec::new();
1411 write_jsonb_value(&value, &mut buffer).unwrap();
1412
1413 let mut expected_buffer = Vec::new();
1414 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);
1420 }
1421
1422 #[diesel_test_helper::test]
1423 fn test_write_jsonb_object() {
1424 let value = json!({"key": 42});
1425 let mut buffer = Vec::new();
1426 write_jsonb_value(&value, &mut buffer).unwrap();
1427
1428 let mut expected = Vec::new();
1429 expected.extend(create_jsonb_header(JSONB_OBJECT, 7).unwrap());
1430 expected.extend(create_jsonb_header(JSONB_TEXT, 3).unwrap());
1431 expected.extend_from_slice(b"key");
1432 expected.extend(create_jsonb_header(JSONB_INT, 2).unwrap());
1433 expected.extend_from_slice(b"42");
1434
1435 assert_eq!(buffer, expected,);
1436 }
1437
1438 #[diesel_test_helper::test]
1439 #[cfg(not(miri))] fn jsonb_to_sql_bool() {
1441 let conn = &mut connection();
1442 let res = diesel::select(json!(true).into_sql::<Jsonb>().eq(&sql("jsonb('true')")))
1443 .get_result::<bool>(conn)
1444 .unwrap();
1445 assert!(res);
1446 }
1447
1448 #[diesel_test_helper::test]
1449 #[cfg(not(miri))] fn jsonb_to_sql_null() {
1451 let conn = &mut connection();
1452 let res = diesel::select(json!(null).into_sql::<Jsonb>().eq(&sql("jsonb('null')")))
1453 .get_result::<bool>(conn)
1454 .unwrap();
1455 assert!(res);
1456 }
1457
1458 #[diesel_test_helper::test]
1459 #[cfg(not(miri))] fn jsonb_to_sql_integer() {
1461 let conn = &mut connection();
1462 let res = diesel::select(json!(42).into_sql::<Jsonb>().eq(&sql("jsonb('42')")))
1463 .get_result::<bool>(conn)
1464 .unwrap();
1465 assert!(res);
1466 }
1467
1468 #[diesel_test_helper::test]
1469 #[cfg(not(miri))] fn jsonb_to_sql_float() {
1471 let conn = &mut connection();
1472 let res = diesel::select(json!(42.23).into_sql::<Jsonb>().eq(&sql("jsonb('42.23')")))
1473 .get_result::<bool>(conn)
1474 .unwrap();
1475 assert!(res);
1476 }
1477
1478 #[diesel_test_helper::test]
1479 #[cfg(not(miri))] fn jsonb_to_sql_text() {
1481 let conn = &mut connection();
1482
1483 let res = diesel::select(
1485 json!("hello")
1486 .into_sql::<Jsonb>()
1487 .eq(&sql(r#"jsonb('"hello"')"#)),
1488 )
1489 .get_result::<bool>(conn)
1490 .unwrap();
1491
1492 assert!(res);
1493 }
1494
1495 #[diesel_test_helper::test]
1496 #[cfg(not(miri))] fn jsonb_to_sql_textj() {
1498 let conn = &mut connection();
1499
1500 let res = diesel::select(
1502 json!("hello\nworld")
1503 .into_sql::<Jsonb>()
1504 .eq(&sql(r#"jsonb('"hello\nworld"')"#)), )
1506 .get_result::<bool>(conn)
1507 .unwrap();
1508
1509 assert!(res);
1510 }
1511
1512 #[diesel_test_helper::test]
1513 #[cfg(not(miri))] fn jsonb_to_sql_textj_quote_and_backslash() {
1515 let conn = &mut connection();
1516
1517 let res = diesel::select(
1519 json!(r#"a"b\c"#)
1520 .into_sql::<Jsonb>()
1521 .eq(&sql(r#"jsonb('"a\"b\\c"')"#)),
1522 )
1523 .get_result::<bool>(conn)
1524 .unwrap();
1525
1526 assert!(res);
1527 }
1528
1529 #[diesel_test_helper::test]
1530 #[cfg(not(miri))] fn jsonb_to_sql_array() {
1532 let conn = &mut connection();
1533 let res = diesel::select(
1534 json!([1, true, "foo"])
1535 .into_sql::<Jsonb>()
1536 .eq(&sql(r#"jsonb('[1, true, "foo"]')"#)),
1537 )
1538 .get_result::<bool>(conn)
1539 .unwrap();
1540 assert!(res);
1541 }
1542
1543 #[diesel_test_helper::test]
1544 #[cfg(not(miri))] fn jsonb_to_sql_object() {
1546 let conn = &mut connection();
1547 let res = diesel::select(
1548 json!({"key": "value"})
1549 .into_sql::<Jsonb>()
1550 .eq(&sql(r#"jsonb('{"key": "value"}')"#)),
1551 )
1552 .get_result::<bool>(conn)
1553 .unwrap();
1554 assert!(res);
1555 }
1556
1557 #[diesel_test_helper::test]
1558 #[cfg(not(miri))] fn jsonb_to_sql_object_in_object() {
1560 let conn = &mut connection();
1561 let json_value = json!({
1562 "outer_key": {
1563 "additional_key": true,
1564 "inner_key": {
1565 "nested_key": 42
1566 },
1567 }
1568 });
1569
1570 let res = diesel::select(json_value.into_sql::<Jsonb>().eq(&sql(
1571 r#"jsonb('{"outer_key": {"additional_key": true, "inner_key": {"nested_key": 42}}}')"#,
1572 )))
1573 .get_result::<bool>(conn)
1574 .unwrap();
1575 assert!(res);
1576 }
1577
1578 #[diesel_test_helper::test]
1579 #[cfg(not(miri))] fn jsonb_to_sql_array_in_object() {
1581 let conn = &mut connection();
1582 let json_value = json!({
1583 "is_valid": false,
1584 "key": [1, 2, 3],
1585 });
1586 let res = diesel::select(
1587 json_value
1588 .into_sql::<Jsonb>()
1589 .eq(&sql(r#"jsonb('{"is_valid": false, "key": [1, 2, 3]}')"#)),
1590 )
1591 .get_result::<bool>(conn)
1592 .unwrap();
1593 assert!(res);
1594 }
1595
1596 #[diesel_test_helper::test]
1597 #[cfg(not(miri))] fn jsonb_to_sql_object_in_array() {
1599 let conn = &mut connection();
1600 let json_value = json!([
1601 {
1602 "nested_key": "nested_value"
1603 },
1604 {
1605 "int_value": 99
1606 }
1607 ]);
1608 let res = diesel::select(json_value.into_sql::<Jsonb>().eq(&sql(
1609 r#"jsonb('[{"nested_key": "nested_value"}, {"int_value": 99}]')"#,
1610 )))
1611 .get_result::<bool>(conn)
1612 .unwrap();
1613 assert!(res);
1614 }
1615
1616 #[diesel_test_helper::test]
1617 #[cfg(not(miri))] fn jsonb_from_sql_null() {
1619 let conn = &mut connection();
1620 let res = diesel::select(sql::<Jsonb>("jsonb('null')"))
1621 .get_result::<serde_json::Value>(conn)
1622 .unwrap();
1623 assert_eq!(res, serde_json::json!(null));
1624 }
1625
1626 #[diesel_test_helper::test]
1627 #[cfg(not(miri))] fn jsonb_from_sql_true() {
1629 let conn = &mut connection();
1630 let res = diesel::select(sql::<Jsonb>("jsonb('true')"))
1631 .get_result::<serde_json::Value>(conn)
1632 .unwrap();
1633 assert_eq!(res, serde_json::json!(true));
1634 }
1635
1636 #[diesel_test_helper::test]
1637 #[cfg(not(miri))] fn jsonb_from_sql_false() {
1639 let conn = &mut connection();
1640 let res = diesel::select(sql::<Jsonb>("jsonb('false')"))
1641 .get_result::<serde_json::Value>(conn)
1642 .unwrap();
1643 assert_eq!(res, serde_json::json!(false));
1644 }
1645
1646 #[diesel_test_helper::test]
1647 #[cfg(not(miri))] fn jsonb_from_sql_int() {
1649 let conn = &mut connection();
1650 let res = diesel::select(sql::<Jsonb>("jsonb('42')"))
1651 .get_result::<serde_json::Value>(conn)
1652 .unwrap();
1653 assert_eq!(res, serde_json::json!(42));
1654 }
1655
1656 #[diesel_test_helper::test]
1657 #[cfg(not(miri))] fn jsonb_from_sql_float() {
1659 let conn = &mut connection();
1660 let res = diesel::select(sql::<Jsonb>("jsonb('42.23')"))
1661 .get_result::<serde_json::Value>(conn)
1662 .unwrap();
1663 assert_eq!(res, serde_json::json!(42.23));
1664 }
1665
1666 #[diesel_test_helper::test]
1667 #[cfg(not(miri))] fn jsonb_from_sql_object() {
1669 let conn = &mut connection();
1670 let res = diesel::select(sql::<Jsonb>(r#"jsonb('{"key": "value"}')"#))
1671 .get_result::<serde_json::Value>(conn)
1672 .unwrap();
1673 assert_eq!(res, serde_json::json!({"key": "value"}));
1674 }
1675
1676 #[diesel_test_helper::test]
1677 #[cfg(not(miri))] fn jsonb_from_sql_array() {
1679 let conn = &mut connection();
1680 let res = diesel::select(sql::<Jsonb>("jsonb('[1, 2, 3]')"))
1681 .get_result::<serde_json::Value>(conn)
1682 .unwrap();
1683 assert_eq!(res, serde_json::json!([1, 2, 3]));
1684 }
1685
1686 #[diesel_test_helper::test]
1687 #[cfg(not(miri))] fn jsonb_from_sql_nested_objects() {
1689 let conn = &mut connection();
1690 let res = diesel::select(sql::<Jsonb>(r#"jsonb('{"outer": {"inner": 42}}')"#))
1691 .get_result::<serde_json::Value>(conn)
1692 .unwrap();
1693 assert_eq!(res, serde_json::json!({"outer": {"inner": 42}}));
1694 }
1695
1696 #[diesel_test_helper::test]
1697 #[cfg(not(miri))] fn jsonb_from_sql_nested_arrays() {
1699 let conn = &mut connection();
1700 let res = diesel::select(sql::<Jsonb>("jsonb('[[1, 2], [3, 4]]')"))
1701 .get_result::<serde_json::Value>(conn)
1702 .unwrap();
1703 assert_eq!(res, serde_json::json!([[1, 2], [3, 4]]));
1704 }
1705
1706 #[diesel_test_helper::test]
1707 #[cfg(not(miri))] fn jsonb_from_sql_nested_arrays_in_objects() {
1709 let conn = &mut connection();
1710 let res = diesel::select(sql::<Jsonb>(r#"jsonb('{"array": [1, 2, 3]}')"#))
1711 .get_result::<serde_json::Value>(conn)
1712 .unwrap();
1713 assert_eq!(res, serde_json::json!({"array": [1, 2, 3]}));
1714 }
1715
1716 #[diesel_test_helper::test]
1717 #[cfg(not(miri))] fn jsonb_from_sql_nested_objects_in_arrays() {
1719 let conn = &mut connection();
1720 let res = diesel::select(sql::<Jsonb>(
1721 r#"jsonb('[{"key1": "value1"}, {"key2": "value2"}]')"#,
1722 ))
1723 .get_result::<serde_json::Value>(conn)
1724 .unwrap();
1725 assert_eq!(
1726 res,
1727 serde_json::json!([{"key1": "value1"}, {"key2": "value2"}])
1728 );
1729 }
1730
1731 #[diesel_test_helper::test]
1732 #[cfg(not(miri))] fn jsonb_from_sql_text() {
1734 let conn = &mut connection();
1735 let res = diesel::select(sql::<Jsonb>(r#"jsonb('"hello"')"#))
1736 .get_result::<serde_json::Value>(conn)
1737 .unwrap();
1738 assert_eq!(res, serde_json::json!("hello"));
1739 }
1740
1741 #[diesel_test_helper::test]
1742 #[cfg(not(miri))] fn jsonb_from_sql_textj() {
1744 let conn = &mut connection();
1745 let res = diesel::select(sql::<Jsonb>(r#"jsonb('"hello\nworld"')"#))
1746 .get_result::<serde_json::Value>(conn)
1747 .unwrap();
1748 assert_eq!(res, serde_json::json!("hello\nworld"));
1749 }
1750
1751 #[diesel_test_helper::test]
1752 #[cfg(not(miri))] fn bad_json_from_sql() {
1754 let conn = &mut connection();
1755 let res = diesel::select(json!(true).into_sql::<Json>().eq(&sql("json('boom')")))
1756 .get_result::<bool>(conn);
1757 assert_eq!(format_error(&res.unwrap_err()), "malformed JSON");
1758 }
1759
1760 #[diesel_test_helper::test]
1761 #[cfg(not(miri))] fn bad_jsonb_from_sql() {
1763 let conn = &mut connection();
1764 let res = diesel::select(json!(true).into_sql::<Jsonb>().eq(&sql("jsonb('boom')")))
1765 .get_result::<bool>(conn);
1766 assert_eq!(format_error(&res.unwrap_err()), "malformed JSON");
1767 }
1768
1769 #[diesel_test_helper::test]
1770 fn no_json_from_sql() {
1771 let uuid: Result<serde_json::Value, _> = FromSql::<Json, Sqlite>::from_nullable_sql(None);
1772 assert_eq!(
1773 format_error(&*uuid.unwrap_err()),
1774 "Unexpected null for non-null column"
1775 );
1776 }
1777
1778 #[diesel_test_helper::test]
1779 fn no_jsonb_from_sql() {
1780 let uuid: Result<serde_json::Value, _> = FromSql::<Jsonb, Sqlite>::from_nullable_sql(None);
1781 assert_eq!(
1782 format_error(&*uuid.unwrap_err()),
1783 "Unexpected null for non-null column"
1784 );
1785 }
1786
1787 #[cfg(all(
1788 not(miri),
1789 not(all(target_family = "wasm", target_os = "unknown")),
1790 unix
1791 ))]
1792 const RECURSION_DEPTH: usize = 2000;
1793
1794 #[cfg(all(
1795 not(miri),
1796 any(windows, all(target_family = "wasm", target_os = "unknown"))
1797 ))]
1798 const RECURSION_DEPTH: usize = 1000;
1799
1800 #[cfg(any(
1801 miri,
1802 all(
1803 not(unix),
1804 not(windows),
1805 not(all(target_family = "wasm", target_os = "unknown"))
1806 )
1807 ))]
1808 const RECURSION_DEPTH: usize = 10;
1809
1810 #[diesel_test_helper::test]
1811 fn guard_against_stackoverflow_array() {
1812 let mut value = serde_json::Value::Number(42.into());
1813 for i in 0..RECURSION_DEPTH {
1814 value = serde_json::Value::Array(vec![value, serde_json::Value::Number(i.into())]);
1815 }
1816 let mut expected_buffer = Vec::new();
1819 write_jsonb_value(&value, &mut expected_buffer).unwrap();
1820 let res = read_jsonb_value(&expected_buffer).unwrap().0;
1821
1822 let mut buffer = Vec::new();
1823 write_jsonb_value(&res, &mut buffer).unwrap();
1824 assert_eq!(expected_buffer, buffer);
1825 }
1826
1827 #[diesel_test_helper::test]
1828 fn guard_against_stackoverflow_object() {
1829 let mut value = serde_json::Value::Number(42.into());
1830 for i in 0..RECURSION_DEPTH {
1831 let mut map = serde_json::Map::new();
1832 map.insert(format!("key_{i}"), value);
1833 value = serde_json::Value::Object(map);
1834 }
1835
1836 let mut expected_buffer = Vec::new();
1839 write_jsonb_value(&value, &mut expected_buffer).unwrap();
1840
1841 let res = read_jsonb_value(&expected_buffer).unwrap().0;
1842
1843 let mut buffer = Vec::new();
1844 write_jsonb_value(&res, &mut buffer).unwrap();
1845 assert_eq!(expected_buffer, buffer);
1846 }
1847
1848 #[diesel_test_helper::test]
1849 fn guard_against_stackoverflow_mixed() {
1850 #[cfg(not(miri))]
1852 const SIZE: usize = 2000;
1853 #[cfg(miri)]
1854 const SIZE: usize = 20;
1855
1856 let mut value = serde_json::Value::Number(42.into());
1857 for i in 0_usize..SIZE {
1858 if i.is_multiple_of(2) {
1859 let mut map = serde_json::Map::new();
1860 map.insert(format!("key_{i}"), value);
1861 value = serde_json::Value::Object(map);
1862 } else {
1863 value = serde_json::Value::Array(vec![value]);
1864 }
1865 }
1866 let mut expected_buffer = Vec::new();
1869 write_jsonb_value(&value, &mut expected_buffer).unwrap();
1870 let res = read_jsonb_value(&expected_buffer).unwrap().0;
1871 let mut buffer = Vec::new();
1872 write_jsonb_value(&res, &mut buffer).unwrap();
1873 assert_eq!(expected_buffer, buffer);
1874 }
1875
1876 #[diesel_test_helper::test]
1877 #[cfg(not(miri))] fn dangling_bytes_result_in_error() {
1879 let mut value = Vec::<u8>::new();
1880 value.extend(create_jsonb_header(JSONB_INT, 1).unwrap());
1881 value.push(b'1');
1882 value.push(42);
1883 assert_eq!(value.len(), 3);
1884 let conn = &mut connection();
1885 let res = diesel::select(
1886 crate::dsl::sql::<sql_types::Jsonb>("jsonb(?)").bind::<sql_types::Binary, _>(value),
1887 )
1888 .get_result::<serde_json::Value>(conn);
1889 assert!(res.is_err(), "{:?}", res.unwrap());
1890 }
1891
1892 #[diesel_test_helper::test]
1893 fn object_key_without_value_results_in_error() {
1894 let mut value = Vec::new();
1895 value.extend(create_jsonb_header(JSONB_OBJECT, 2).unwrap());
1896 value.extend(create_jsonb_header(JSONB_TEXT, 1).unwrap());
1897 value.push(b'a');
1898 let res = read_jsonb_value(&value);
1899 assert!(res.is_err(), "{:?}", res.unwrap());
1900 }
1901
1902 #[diesel_test_helper::test]
1903 fn check_invalid_size_header() {
1904 let res = read_jsonb_value(&[0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
1907 assert!(res.is_err());
1908 }
1909
1910 #[diesel_test_helper::test]
1911 fn nested_container_cannot_cross_parent_boundary() {
1912 let res = read_jsonb_value(&[0x3B, 0x1B, 0x1B, JSONB_NULL]);
1913 assert!(res.is_err(), "{:?}", res.unwrap());
1914 }
1915
1916 #[diesel_test_helper::test]
1917 fn check_signed_integer() {
1918 let mut buf = Vec::new();
1919 write_jsonb_value(&json!(-42), &mut buf).unwrap();
1920 let mut expected = create_jsonb_header(JSONB_INT, 3).unwrap();
1921 expected.extend(b"-42");
1922 assert_eq!(buf, expected);
1923 }
1924}