use alloc::borrow::Cow;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use crate::de::{read_token_tree, DecodeSlot, Decoder, NsonDeserialize};
use crate::error::{FormatError, Result};
use crate::ser::NsonSerialize;
use crate::value::Value;
pub use crate::de::{
Decoder as DecoderReexport, NsonDeserialize as NsonDeserializeReexport, Token,
Token as TokenReexport,
};
pub use crate::encoding::Encoder as EncoderReexport;
pub use crate::ser::NsonSerialize as NsonSerializeReexport;
#[doc(hidden)]
pub struct InitSlot<T> {
slot: DecodeSlot<T>,
}
impl<T> InitSlot<T> {
pub const fn new() -> Self {
InitSlot {
slot: DecodeSlot::new(),
}
}
pub fn nextdecode<'de, D: crate::de::FormatDecoder<'de>>(
&mut self,
decoder: &mut D,
) -> Result<(), D::Error>
where
T: NsonDeserialize<'de>,
{
T::nextdecode_into(decoder, &mut self.slot)?;
if !self.slot.is_initialized() {
return Err(FormatError::custom(
"NsonDeserialize::nextdecode_into returned success without writing a value",
));
}
Ok(())
}
pub fn write(&mut self, value: T) {
self.slot.write(value);
}
pub fn take(&mut self) -> T {
self.slot
.take()
.expect("nextjson derive: uninitialized field slot")
}
}
impl<T> Default for InitSlot<T> {
fn default() -> Self {
Self::new()
}
}
pub fn from_tokens<'de>(tokens: Vec<Token<'de>>) -> Decoder<'de> {
Decoder::from_tokens(tokens)
}
type ObjectMap<'de> = Vec<(Cow<'de, str>, Vec<Token<'de>>)>;
pub fn read_object_map<'de, D: crate::de::FormatDecoder<'de>>(
decoder: &mut D,
) -> Result<ObjectMap<'de>, D::Error> {
let mut entries = Vec::new();
decoder.begin_object()?;
while let Some(key) = decoder.object_key()? {
let value = read_token_tree(decoder)?;
entries.push((key, value));
if !decoder.object_entry_sep()? {
break;
}
}
decoder.end_object()?;
Ok(entries)
}
pub fn tokens_to_object<'de>(
mut entries: Vec<(Cow<'de, str>, Vec<Token<'de>>)>,
) -> Vec<Token<'de>> {
let mut out = Vec::with_capacity(entries.len() * 2 + 2);
out.push(Token::BeginObject);
for (k, v) in entries.drain(..) {
out.push(Token::Str(k));
out.extend(v);
}
out.push(Token::EndObject);
out
}
pub fn token_to_string<'de>(tokens: &[Token<'de>]) -> Result<String> {
match tokens {
[Token::Str(s)] => Ok(s.to_string()),
_ => Err(crate::error::Error::invalid_type(
"a string",
"a non-string value",
)),
}
}
pub fn nextdecode_value<T: for<'de> NsonDeserialize<'de>>(value: Value) -> Result<T> {
let tokens = value_to_tokens(&value);
let mut decoder = Decoder::from_tokens(tokens);
let decoded = T::nextdecode(&mut decoder)?;
decoder.end()?;
Ok(decoded)
}
fn value_to_tokens(v: &Value) -> Vec<Token<'static>> {
let mut out = Vec::new();
value_to_tokens_inner(v, &mut out);
out
}
fn value_to_tokens_inner(v: &Value, out: &mut Vec<Token<'static>>) {
match v {
Value::Null => out.push(Token::Null),
Value::Bool(b) => out.push(Token::Bool(*b)),
Value::Number(n) => out.push(Token::Number(*n)),
Value::String(s) => out.push(Token::Str(Cow::Owned(s.clone()))),
Value::Array(a) => {
out.push(Token::BeginArray);
for x in a {
value_to_tokens_inner(x, out);
}
out.push(Token::EndArray);
}
Value::Object(m) => {
out.push(Token::BeginObject);
for (k, val) in m.iter() {
out.push(Token::Str(Cow::Owned(k.to_string())));
value_to_tokens_inner(val, out);
}
out.push(Token::EndObject);
}
}
}
pub fn write_tagged_object<E: crate::ser::FormatEncoder>(
encoder: &mut E,
tag: &str,
variant_name: &str,
value: Value,
) -> Result<(), E::Error> {
match value {
Value::Object(m) => {
encoder.begin_object()?;
encoder.key(tag)?;
encoder.write_str(variant_name)?;
for (k, v) in m.iter() {
encoder.key(k)?;
NsonSerialize::nextencode(v, encoder)?;
}
encoder.end_object()
}
_ => Err(crate::error::Error::custom(
"internally tagged newtype variant must serialize to an object",
)
.into()),
}
}
fn emit_value<E: crate::ser::FormatEncoder>(
value: &Value,
encoder: &mut E,
) -> Result<(), E::Error> {
match value {
Value::Null => encoder.write_null(),
Value::Bool(b) => encoder.write_bool(*b),
Value::Number(n) => encoder.write_number(n),
Value::String(s) => encoder.write_str(s),
Value::Array(a) => {
encoder.begin_array()?;
for item in a {
encoder.separator()?;
emit_value(item, encoder)?;
}
encoder.end_array()
}
Value::Object(m) => {
encoder.begin_object()?;
for (k, v) in m.iter() {
encoder.key(k)?;
emit_value(v, encoder)?;
}
encoder.end_object()
}
}
}
pub fn flatten_into<E: crate::ser::FormatEncoder>(
json: &[u8],
encoder: &mut E,
) -> Result<(), E::Error> {
let mut decoder = Decoder::new(json);
let value = Value::nextdecode(&mut decoder)?;
decoder.end()?;
match value {
Value::Object(m) => {
for (k, v) in m.iter() {
encoder.key(k)?;
emit_value(v, encoder)?;
}
Ok(())
}
_ => Err(crate::error::Error::custom("flatten: expected an object or map").into()),
}
}
pub use crate::error::Error as ErrorReexport;
pub use crate::error::Result as ResultReexport;
pub use crate::map::Map as MapReexport;
pub use crate::value::Value as ValueReexport;
#[cfg(test)]
mod tests {
use super::*;
use crate::map::Map;
use alloc::vec;
#[test]
fn value_tokens_roundtrip() {
let v = Value::Object(Map::from_iter(vec![
(
"a".to_string(),
Value::Array(vec![Value::Number(1.into()), Value::Null]),
),
("b".to_string(), Value::Bool(true)),
]));
let tokens = value_to_tokens(&v);
let mut d = Decoder::from_tokens(tokens);
let back: Map = NsonDeserialize::nextdecode(&mut d).unwrap();
assert_eq!(
back.get("a").unwrap(),
&Value::Array(vec![Value::Number(1.into()), Value::Null])
);
}
#[test]
fn read_object_map_works() {
let mut d = Decoder::new(br#"{"type":"A","x":1,"y":[2,3]}"#);
let entries = read_object_map(&mut d).unwrap();
assert_eq!(entries.len(), 3);
assert_eq!(entries[0].0.as_ref(), "type");
assert_eq!(token_to_string(&entries[0].1).unwrap(), "A");
}
}