use std::borrow::Cow;
use std::fmt;
use std::string::String;
use serde::de::{self, Deserialize, DeserializeSeed, Deserializer, IgnoredAny, MapAccess, Visitor};
use super::skip::whole;
use super::skips::{mark, restore, take, Taken};
use super::Any;
use super::Unfit;
pub(super) const RAW: &str = "$serde_json::private::RawValue";
pub struct Raw<'de>(Cow<'de, str>);
impl Raw<'_> {
pub fn get(&self) -> &str {
&self.0
}
}
impl<'de> Deserialize<'de> for Raw<'de> {
fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
d.deserialize_newtype_struct(RAW, RawText)
}
}
struct RawText;
impl<'de> Visitor<'de> for RawText {
type Value = Raw<'de>;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("a value")
}
fn visit_map<A: MapAccess<'de>>(self, mut a: A) -> Result<Raw<'de>, A::Error> {
a.next_key::<IgnoredAny>()?;
a.next_value_seed(Text).map(Raw)
}
fn visit_newtype_struct<D: Deserializer<'de>>(self, d: D) -> Result<Raw<'de>, D::Error> {
let text = serde_json::to_string(&Any.deserialize(d)?)
.map_err(|e| Unfit::from_json(&e).raise())?;
Ok(Raw(Cow::Owned(text)))
}
}
pub(super) struct Text;
impl<'de> DeserializeSeed<'de> for Text {
type Value = Cow<'de, str>;
fn deserialize<D: Deserializer<'de>>(self, d: D) -> Result<Self::Value, D::Error> {
d.deserialize_any(self)
}
}
impl<'de> Visitor<'de> for Text {
type Value = Cow<'de, str>;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("text")
}
fn visit_borrowed_str<E: de::Error>(self, v: &'de str) -> Result<Self::Value, E> {
Ok(Cow::Borrowed(v))
}
fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
Ok(Cow::Owned(v.into()))
}
fn visit_string<E: de::Error>(self, v: String) -> Result<Self::Value, E> {
Ok(Cow::Owned(v))
}
refuse!("text"; unit none some bool i64 u64 f64 bytes seq map enum newtype);
}
pub mod kind {
pub const NULL: u8 = 1;
pub const BOOL: u8 = 2;
pub const NUMBER: u8 = 4;
pub const TEXT: u8 = 8;
pub const ARRAY: u8 = 16;
pub const OBJECT: u8 = 32;
pub const ANY: u8 = 63;
pub(super) fn of(byte: Option<u8>) -> u8 {
match byte {
Some(b'{') => OBJECT,
Some(b'[') => ARRAY,
Some(b'"') => TEXT,
Some(b't' | b'f') => BOOL,
Some(b'n') => NULL,
Some(b'-' | b'0'..=b'9') => NUMBER,
_ => ANY,
}
}
pub(super) fn expected(mask: u8) -> &'static str {
match mask {
m if m & OBJECT != 0 => "an object",
m if m & ARRAY != 0 => "an array",
m if m & TEXT != 0 => "text",
m if m & NUMBER != 0 => "a number",
m if m & BOOL != 0 => "a boolean",
_ => "null",
}
}
}
pub struct Pick<'t, T> {
text: &'t str,
kind: u8,
held: Option<T>,
first: Option<T>,
skips: (Taken, Taken),
why: Option<Unfit>,
}
impl<'t, T> Pick<'t, T> {
pub fn new(text: &'t str) -> Self {
Pick {
text,
kind: kind::of(text.trim_start().bytes().next()),
held: None,
first: None,
skips: Default::default(),
why: None,
}
}
pub fn branch<S: DeserializeSeed<'t>>(
&mut self,
mask: u8,
seed: S,
wrap: impl FnOnce(S::Value) -> (T, bool),
) {
if self.held.is_some() {
return;
}
if mask & self.kind == 0 {
self.fail(Unfit::kind(kind::expected(mask)));
return;
}
let at = mark();
let mut de = serde_json::Deserializer::from_str(self.text);
let read = whole(|| seed.deserialize(&mut de).and_then(|v| de.end().map(|()| v)));
let noted = take(at);
match read {
Ok(v) => {
let (value, holds) = wrap(v);
match (holds, self.first.is_some()) {
(true, _) => (self.held, self.skips.0) = (Some(value), noted),
(false, false) => (self.first, self.skips.1) = (Some(value), noted),
(false, true) => {}
}
}
Err(e) => self.fail(Unfit::raised().unwrap_or_else(|| Unfit::from_json(&e))),
}
}
fn fail(&mut self, failure: Unfit) {
self.why = Some(Unfit::either(self.why.take(), failure));
}
pub fn finish<E: de::Error>(self) -> Result<T, E> {
let (value, noted) = match self.held {
Some(v) => (Some(v), self.skips.0),
None => (self.first, self.skips.1),
};
match value {
Some(v) => {
restore(noted);
Ok(v)
}
None => Err(self
.why
.unwrap_or_else(|| Unfit::kind("one of the union's branches"))
.raise()),
}
}
}