#![no_std]
#![deny(unsafe_code)]
#![deny(missing_docs)]
#![doc(html_root_url = "https://docs.rs/nextjson")]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
#[cfg(feature = "derive")]
pub use nextjson_derive::{NsonDeserialize, NsonSerialize};
pub use crate::bytes::Bytes;
pub use crate::de::{
DecodeConfig, DecodeSlot, Decoder, FormatDecoder, NsonDeserialize, OptionTag, Token,
};
pub use crate::encoding::{EncodeConfig, Encoder, FastEncoder};
pub use crate::error::{Error, FormatError, Result};
pub use crate::map::Map;
pub use crate::number::Number;
pub use crate::schema::{
EnumSchema, FieldSchema, NsonSchema, StructSchema, TypeSchema, VariantSchema,
};
pub use crate::ser::{FormatEncoder, NsonSerialize};
#[cfg(feature = "std")]
pub use crate::stream::StreamDecoder;
pub use crate::value::Value;
pub use crate::write::Write;
mod bytes;
pub mod cross_format;
pub mod de;
pub mod encoding;
pub mod error;
mod event_state;
pub mod formats;
mod json_schema;
mod lex;
pub mod map;
mod number;
#[doc(hidden)]
pub mod private;
mod schema;
mod ser;
#[cfg(feature = "std")]
pub mod stream;
mod value;
mod write;
#[doc(hidden)]
pub mod __private {
pub use alloc::borrow::Cow;
pub use alloc::boxed::Box;
pub use alloc::collections::{BTreeMap, BTreeSet, VecDeque};
pub use alloc::format;
pub use alloc::string::{String, ToString};
pub use alloc::vec;
pub use alloc::vec::Vec;
}
use alloc::format;
use alloc::string::String;
use alloc::vec::Vec;
pub fn nextencode<T: NsonSerialize + ?Sized>(value: &T) -> Result<Vec<u8>> {
let mut encoder = FastEncoder::for_vec(EncodeConfig::compact());
NsonSerialize::nextencode(value, &mut encoder)?;
encoder.finish_vec()
}
pub fn to_string<T: NsonSerialize + ?Sized>(value: &T) -> Result<String> {
let bytes = nextencode(value)?;
String::from_utf8(bytes).map_err(|e| Error::custom(format!("invalid utf-8: {e}")))
}
pub fn to_vec<T: NsonSerialize + ?Sized>(value: &T) -> Result<Vec<u8>> {
nextencode(value)
}
pub fn to_string_pretty<T: NsonSerialize + ?Sized>(value: &T) -> Result<String> {
let bytes = to_vec_pretty(value)?;
String::from_utf8(bytes).map_err(|e| Error::custom(format!("invalid utf-8: {e}")))
}
pub fn to_vec_pretty<T: NsonSerialize + ?Sized>(value: &T) -> Result<Vec<u8>> {
let mut encoder = FastEncoder::for_vec(EncodeConfig::pretty());
NsonSerialize::nextencode(value, &mut encoder)?;
encoder.finish_vec()
}
pub fn to_writer<W, T>(writer: W, value: &T) -> Result<()>
where
W: Write,
T: NsonSerialize + ?Sized,
{
let mut encoder = FastEncoder::new(writer);
NsonSerialize::nextencode(value, &mut encoder)?;
encoder.finish()?;
Ok(())
}
pub fn to_writer_pretty<W, T>(writer: W, value: &T) -> Result<()>
where
W: Write,
T: NsonSerialize + ?Sized,
{
let mut encoder = FastEncoder::with_config(writer, EncodeConfig::pretty());
NsonSerialize::nextencode(value, &mut encoder)?;
encoder.finish()?;
Ok(())
}
#[cfg(feature = "std")]
pub fn to_io_writer<W, T>(writer: W, value: &T) -> Result<()>
where
W: std::io::Write,
T: NsonSerialize + ?Sized,
{
let mut encoder = FastEncoder::new(crate::write::StdWriter(writer));
NsonSerialize::nextencode(value, &mut encoder)?;
encoder.finish()?;
Ok(())
}
pub fn nextdecode<'de, T: NsonDeserialize<'de>>(input: &'de [u8]) -> Result<T> {
let mut decoder = Decoder::new(input);
let value = T::nextdecode(&mut decoder)?;
decoder.end()?;
Ok(value)
}
pub fn from_str<'de, T: NsonDeserialize<'de>>(s: &'de str) -> Result<T> {
nextdecode(s.as_bytes())
}
pub fn from_slice<'de, T: NsonDeserialize<'de>>(slice: &'de [u8]) -> Result<T> {
nextdecode(slice)
}
#[cfg(feature = "std")]
pub fn from_reader<R, T>(reader: R) -> Result<T>
where
R: std::io::Read,
T: for<'de> NsonDeserialize<'de>,
{
let mut decoder = StreamDecoder::new(reader);
let value = T::nextdecode(&mut decoder)?;
decoder.end()?;
Ok(value)
}
pub fn to_value<T: NsonSerialize + ?Sized>(value: &T) -> Result<Value> {
from_slice(&to_vec(value)?)
}
pub fn from_value<T>(value: Value) -> Result<T>
where
T: for<'de> NsonDeserialize<'de>,
{
private::nextdecode_value(value)
}
pub fn schema_of<T: NsonSchema>() -> TypeSchema {
T::SCHEMA
}
pub fn to_json_schema<T: NsonSchema>() -> Value {
json_schema::from_schema(T::SCHEMA)
}
#[macro_export]
macro_rules! json {
($($json:tt)+) => {
$crate::json_internal!($($json)+)
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! json_internal {
(null) => {
$crate::Value::Null
};
(true) => {
$crate::Value::Bool(true)
};
(false) => {
$crate::Value::Bool(false)
};
([]) => {
$crate::Value::Array($crate::__private::Vec::new())
};
([$($tt:tt)+]) => {
$crate::Value::Array($crate::json_internal!(@array [] $($tt)+))
};
({}) => {
$crate::Value::Object($crate::Map::new())
};
({ $($tt:tt)+ }) => {
$crate::Value::Object({
let mut __object = $crate::Map::new();
$crate::json_internal!(@object __object () ($($tt)+));
__object
})
};
($other:expr) => {
$crate::to_value(&$other).expect("json! interpolation: value must be serializable")
};
(@array [$($elems:expr,)*]) => {
$crate::__private::vec![$($elems,)*]
};
(@array [$($elems:expr),*]) => {
$crate::__private::vec![$($elems),*]
};
(@array [$($elems:expr,)*] null $($rest:tt)*) => {
$crate::json_internal!(@array [$($elems,)* $crate::json_internal!(null)] $($rest)*)
};
(@array [$($elems:expr,)*] true $($rest:tt)*) => {
$crate::json_internal!(@array [$($elems,)* $crate::json_internal!(true)] $($rest)*)
};
(@array [$($elems:expr,)*] false $($rest:tt)*) => {
$crate::json_internal!(@array [$($elems,)* $crate::json_internal!(false)] $($rest)*)
};
(@array [$($elems:expr,)*] [$($sub:tt)*] $($rest:tt)*) => {
$crate::json_internal!(@array [$($elems,)* $crate::json_internal!([$($sub)*])] $($rest)*)
};
(@array [$($elems:expr,)*] {$($sub:tt)*} $($rest:tt)*) => {
$crate::json_internal!(@array [$($elems,)* $crate::json_internal!({$($sub)*})] $($rest)*)
};
(@array [$($elems:expr,)*] $next:expr , $($rest:tt)*) => {
$crate::json_internal!(@array [$($elems,)* $crate::json_internal!($next),] $($rest)*)
};
(@array [$($elems:expr,)*] $last:expr) => {
$crate::json_internal!(@array [$($elems,)* $crate::json_internal!($last)])
};
(@array [$($elems:expr),*] , $($rest:tt)*) => {
$crate::json_internal!(@array [$($elems,)*] $($rest)*)
};
(@object $object:ident () ()) => {};
(@object $object:ident [$($key:tt)+] ($value:expr) , $($rest:tt)*) => {
let _ = $object.insert($crate::json_key!(($($key)+)), $value);
$crate::json_internal!(@object $object () ($($rest)*));
};
(@object $object:ident [$($key:tt)+] ($value:expr)) => {
let _ = $object.insert($crate::json_key!(($($key)+)), $value);
};
(@object $object:ident ($($key:tt)+) (: null $($rest:tt)*)) => {
$crate::json_internal!(@object $object [$($key)+] ($crate::json_internal!(null)) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: true $($rest:tt)*)) => {
$crate::json_internal!(@object $object [$($key)+] ($crate::json_internal!(true)) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: false $($rest:tt)*)) => {
$crate::json_internal!(@object $object [$($key)+] ($crate::json_internal!(false)) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: [$($sub:tt)*] $($rest:tt)*)) => {
$crate::json_internal!(@object $object [$($key)+] ($crate::json_internal!([$($sub)*])) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: {$($sub:tt)*} $($rest:tt)*)) => {
$crate::json_internal!(@object $object [$($key)+] ($crate::json_internal!({$($sub)*})) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: $value:expr , $($rest:tt)*)) => {
$crate::json_internal!(@object $object [$($key)+] ($crate::json_internal!($value)) , $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: $value:expr)) => {
$crate::json_internal!(@object $object [$($key)+] ($crate::json_internal!($value)));
};
(@object $object:ident ($($key:tt)*) ($tt:tt $($rest:tt)*)) => {
$crate::json_internal!(@object $object ($($key)* $tt) ($($rest)*));
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! json_key {
(($s:literal)) => {
$crate::__private::String::from($s)
};
(($i:ident)) => {
$crate::__private::String::from(stringify!($i))
};
(($e:expr)) => {
$crate::__private::String::from($crate::__private::format!("{}", $e))
};
}