1#![warn(missing_docs)]
2#![cfg_attr(not(feature = "cranelift"), deny(unsafe_code))]
4#![doc = include_str!("../README.md")]
5
6extern crate alloc;
7
8pub use facet_reflect::{Span, Spanned};
10
11mod deserialize;
12pub use deserialize::{
13 JsonDeserializer, JsonError, JsonErrorKind, from_slice, from_slice_borrowed, from_str,
14 from_str_borrowed,
15};
16
17mod serialize;
18pub use serialize::*;
19
20mod scanner;
21pub use scanner::{
22 NumberHint, ScanError, ScanErrorKind, Scanner, SpannedToken, Token as ScanToken,
23};
24
25mod adapter;
26pub use adapter::{
27 AdapterError, AdapterErrorKind, SliceAdapter, SpannedAdapterToken, Token as AdapterToken,
28 TokenSource,
29};
30
31#[cfg(feature = "streaming")]
32mod streaming;
33#[cfg(feature = "futures-io")]
34pub use streaming::from_async_reader_futures;
35#[cfg(feature = "tokio")]
36pub use streaming::from_async_reader_tokio;
37#[cfg(feature = "streaming")]
38pub use streaming::{StreamingAdapter, from_reader};
39
40mod scan_buffer;
41pub use scan_buffer::ScanBuffer;
42
43#[cfg(feature = "std")]
44mod reader;
45#[cfg(feature = "tokio")]
46pub use reader::AsyncJsonReader;
47#[cfg(feature = "futures-io")]
48pub use reader::FuturesJsonReader;
49#[cfg(feature = "std")]
50pub use reader::{JsonReader, JsonToken, ReaderError, SpannedJsonToken};
51
52mod raw_json;
53pub use raw_json::RawJson;
54
55mod json;
56pub use json::Json;
57
58#[cfg(feature = "cranelift")]
77pub mod cranelift;
78
79#[cfg(feature = "axum")]
80mod axum;
81#[cfg(feature = "axum")]
82pub use self::axum::JsonRejection;
83
84pub use facet_core::Write as JsonWrite;
89
90#[inline]
92fn write_json_string<W: JsonWrite>(writer: &mut W, s: &str) {
93 const STEP_SIZE: usize = Window::BITS as usize / 8;
106 type Window = u128;
107 type Chunk = [u8; STEP_SIZE];
108
109 writer.write(b"\"");
110
111 let mut s = s;
112 while let Some(Ok(chunk)) = s.as_bytes().get(..STEP_SIZE).map(Chunk::try_from) {
113 let window = Window::from_ne_bytes(chunk);
114 let completely_ascii = window & 0x80808080808080808080808080808080 == 0;
121 let quote_free = !contains_0x22(window);
122 let backslash_free = !contains_0x5c(window);
123 let control_char_free = top_three_bits_set(window);
124 if completely_ascii && quote_free && backslash_free && control_char_free {
125 writer.write(&chunk);
127 s = &s[STEP_SIZE..];
128 } else {
129 let mut chars = s.chars();
132 let mut count = STEP_SIZE;
133 for c in &mut chars {
134 write_json_escaped_char(writer, c);
135 count = count.saturating_sub(c.len_utf8());
136 if count == 0 {
137 break;
139 }
140 }
141 s = chars.as_str();
142 }
143 }
144
145 for c in s.chars() {
149 write_json_escaped_char(writer, c);
150 }
151
152 writer.write(b"\"")
153}
154
155#[inline]
157fn write_json_escaped_char<W: JsonWrite>(writer: &mut W, c: char) {
158 match c {
159 '"' => writer.write(b"\\\""),
160 '\\' => writer.write(b"\\\\"),
161 '\n' => writer.write(b"\\n"),
162 '\r' => writer.write(b"\\r"),
163 '\t' => writer.write(b"\\t"),
164 '\u{08}' => writer.write(b"\\b"),
165 '\u{0C}' => writer.write(b"\\f"),
166 c if c.is_ascii_control() => {
167 let code_point = c as u32;
168 let to_hex = |d: u32| char::from_digit(d, 16).unwrap() as u8;
170 let buf = [
171 b'\\',
172 b'u',
173 to_hex((code_point >> 12) & 0xF),
174 to_hex((code_point >> 8) & 0xF),
175 to_hex((code_point >> 4) & 0xF),
176 to_hex(code_point & 0xF),
177 ];
178 writer.write(&buf);
179 }
180 c if c.is_ascii() => {
181 writer.write(&[c as u8]);
182 }
183 c => {
184 let mut buf = [0; 4];
185 let len = c.encode_utf8(&mut buf).len();
186 writer.write(&buf[..len])
187 }
188 }
189}
190
191#[inline]
192fn contains_0x22(val: u128) -> bool {
193 let xor_result = val ^ 0x22222222222222222222222222222222;
194 let has_zero = (xor_result.wrapping_sub(0x01010101010101010101010101010101))
195 & !xor_result
196 & 0x80808080808080808080808080808080;
197 has_zero != 0
198}
199
200#[inline]
201fn contains_0x5c(val: u128) -> bool {
202 let xor_result = val ^ 0x5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c;
203 let has_zero = (xor_result.wrapping_sub(0x01010101010101010101010101010101))
204 & !xor_result
205 & 0x80808080808080808080808080808080;
206 has_zero != 0
207}
208
209#[inline]
211fn top_three_bits_set(value: u128) -> bool {
212 let xor_result = value & 0xe0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0;
213 let has_zero = (xor_result.wrapping_sub(0x01010101010101010101010101010101))
214 & !xor_result
215 & 0x80808080808080808080808080808080;
216 has_zero == 0
217}
218
219#[macro_export]
267#[cfg(all(feature = "streaming", feature = "cranelift"))]
268macro_rules! test_modes {
269 ($($content:tt)*) => {
270 mod slice {
272 #[allow(unused_imports)]
273 use super::*;
274
275 #[allow(dead_code)]
276 fn deserialize<T: ::facet::Facet<'static>>(input: &str) -> Result<T, $crate::JsonError> {
277 $crate::from_str(input)
278 }
279
280 $crate::__test_modes_inner!(@skip_none $($content)*);
281 }
282
283 mod streaming {
285 #[allow(unused_imports)]
286 use super::*;
287
288 #[allow(dead_code)]
289 fn deserialize<T: ::facet::Facet<'static>>(input: &str) -> Result<T, $crate::JsonError> {
290 $crate::from_reader(::std::io::Cursor::new(input))
291 }
292
293 $crate::__test_modes_inner!(@skip_streaming $($content)*);
294 }
295
296 mod cranelift {
298 #[allow(unused_imports)]
299 use super::*;
300
301 #[allow(dead_code)]
302 fn deserialize<T: ::facet::Facet<'static>>(input: &str) -> Result<T, $crate::JsonError> {
303 $crate::cranelift::from_str(input)
304 }
305
306 $crate::__test_modes_inner!(@skip_none $($content)*);
307 }
308 };
309}
310
311#[macro_export]
312#[cfg(all(feature = "streaming", feature = "cranelift"))]
313#[doc(hidden)]
314macro_rules! __test_modes_inner {
315 (@skip_streaming #[skip_streaming] #[test] fn $name:ident() $body:block $($rest:tt)*) => {
317 $crate::__test_modes_inner!(@skip_streaming $($rest)*);
318 };
319
320 (@skip_none #[skip_streaming] #[test] fn $name:ident() $body:block $($rest:tt)*) => {
322 #[test]
323 fn $name() {
324 ::facet_testhelpers::setup();
325 $body
326 }
327 $crate::__test_modes_inner!(@skip_none $($rest)*);
328 };
329
330 (@$mode:ident #[test] fn $name:ident() $body:block $($rest:tt)*) => {
332 #[test]
333 fn $name() {
334 ::facet_testhelpers::setup();
335 $body
336 }
337 $crate::__test_modes_inner!(@$mode $($rest)*);
338 };
339
340 (@$mode:ident) => {};
342}
343
344#[macro_export]
349#[cfg(all(feature = "streaming", not(feature = "cranelift")))]
350macro_rules! test_modes {
351 ($($content:tt)*) => {
352 mod slice {
354 #[allow(unused_imports)]
355 use super::*;
356
357 #[allow(dead_code)]
358 fn deserialize<T: ::facet::Facet<'static>>(input: &str) -> Result<T, $crate::JsonError> {
359 $crate::from_str(input)
360 }
361
362 $crate::__test_modes_inner!(@skip_none $($content)*);
363 }
364
365 mod streaming {
367 #[allow(unused_imports)]
368 use super::*;
369
370 #[allow(dead_code)]
371 fn deserialize<T: ::facet::Facet<'static>>(input: &str) -> Result<T, $crate::JsonError> {
372 $crate::from_reader(::std::io::Cursor::new(input))
373 }
374
375 $crate::__test_modes_inner!(@skip_streaming $($content)*);
376 }
377 };
378}
379
380#[macro_export]
381#[cfg(all(feature = "streaming", not(feature = "cranelift")))]
382#[doc(hidden)]
383macro_rules! __test_modes_inner {
384 (@skip_streaming #[skip_streaming] #[test] fn $name:ident() $body:block $($rest:tt)*) => {
386 $crate::__test_modes_inner!(@skip_streaming $($rest)*);
387 };
388
389 (@skip_none #[skip_streaming] #[test] fn $name:ident() $body:block $($rest:tt)*) => {
391 #[test]
392 fn $name() {
393 ::facet_testhelpers::setup();
394 $body
395 }
396 $crate::__test_modes_inner!(@skip_none $($rest)*);
397 };
398
399 (@$mode:ident #[test] fn $name:ident() $body:block $($rest:tt)*) => {
401 #[test]
402 fn $name() {
403 ::facet_testhelpers::setup();
404 $body
405 }
406 $crate::__test_modes_inner!(@$mode $($rest)*);
407 };
408
409 (@$mode:ident) => {};
411}
412
413#[macro_export]
418#[cfg(all(not(feature = "streaming"), feature = "cranelift"))]
419macro_rules! test_modes {
420 ($($content:tt)*) => {
421 mod slice {
423 #[allow(unused_imports)]
424 use super::*;
425
426 #[allow(dead_code)]
427 fn deserialize<T: ::facet::Facet<'static>>(input: &str) -> Result<T, $crate::JsonError> {
428 $crate::from_str(input)
429 }
430
431 $crate::__test_modes_inner!(@skip_none $($content)*);
432 }
433
434 mod cranelift {
436 #[allow(unused_imports)]
437 use super::*;
438
439 #[allow(dead_code)]
440 fn deserialize<T: ::facet::Facet<'static>>(input: &str) -> Result<T, $crate::JsonError> {
441 $crate::cranelift::from_str(input)
442 }
443
444 $crate::__test_modes_inner!(@skip_none $($content)*);
445 }
446 };
447}
448
449#[macro_export]
450#[cfg(all(not(feature = "streaming"), feature = "cranelift"))]
451#[doc(hidden)]
452macro_rules! __test_modes_inner {
453 (@skip_none #[skip_streaming] #[test] fn $name:ident() $body:block $($rest:tt)*) => {
455 #[test]
456 fn $name() {
457 ::facet_testhelpers::setup();
458 $body
459 }
460 $crate::__test_modes_inner!(@skip_none $($rest)*);
461 };
462
463 (@$mode:ident #[test] fn $name:ident() $body:block $($rest:tt)*) => {
465 #[test]
466 fn $name() {
467 ::facet_testhelpers::setup();
468 $body
469 }
470 $crate::__test_modes_inner!(@$mode $($rest)*);
471 };
472
473 (@$mode:ident) => {};
475}
476
477#[macro_export]
482#[cfg(all(not(feature = "streaming"), not(feature = "cranelift")))]
483macro_rules! test_modes {
484 ($($content:tt)*) => {
485 mod slice {
487 #[allow(unused_imports)]
488 use super::*;
489
490 #[allow(dead_code)]
491 fn deserialize<T: ::facet::Facet<'static>>(input: &str) -> Result<T, $crate::JsonError> {
492 $crate::from_str(input)
493 }
494
495 $crate::__test_modes_inner!(@skip_none $($content)*);
496 }
497 };
498}
499
500#[macro_export]
501#[cfg(all(not(feature = "streaming"), not(feature = "cranelift")))]
502#[doc(hidden)]
503macro_rules! __test_modes_inner {
504 (@skip_none #[skip_streaming] #[test] fn $name:ident() $body:block $($rest:tt)*) => {
506 #[test]
507 fn $name() {
508 ::facet_testhelpers::setup();
509 $body
510 }
511 $crate::__test_modes_inner!(@skip_none $($rest)*);
512 };
513
514 (@$mode:ident #[test] fn $name:ident() $body:block $($rest:tt)*) => {
516 #[test]
517 fn $name() {
518 ::facet_testhelpers::setup();
519 $body
520 }
521 $crate::__test_modes_inner!(@$mode $($rest)*);
522 };
523
524 (@$mode:ident) => {};
526}