use core::{
fmt::{self, Formatter},
marker::PhantomData,
};
use serde::{
Deserialize, Deserializer, Serialize, Serializer,
de::{self, DeserializeSeed, IntoDeserializer, SeqAccess},
};
use crate::{Parser, config::Config, serde::de::Error, source::Source, span::Span};
pub const TOKEN: &str = "$flexon::Span";
pub struct Builder<'a, 'de, S: Source, C: Config> {
de: &'a mut Parser<'de, S, C>,
state: State,
}
pub enum State {
Start,
Value,
End,
}
impl<'a, 'de, S: Source, C: Config> Builder<'a, 'de, S, C> {
#[inline]
pub fn new(de: &'a mut Parser<'de, S, C>) -> Self {
Self {
de,
state: State::Start,
}
}
}
impl<'a, 'de, S: Source, C: Config> SeqAccess<'de> for Builder<'a, 'de, S, C> {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where
T: DeserializeSeed<'de>,
{
match self.state {
State::Start => {
self.state = State::Value;
self.de.skip_whitespace();
self.de.dec();
seed.deserialize(self.de.idx().wrapping_add(1).into_deserializer())
}
State::Value => {
self.state = State::End;
seed.deserialize(&mut *self.de)
}
State::End => seed.deserialize(self.de.idx().into_deserializer()),
}
.map(Some)
}
}
impl<'a, T: Deserialize<'a>> Deserialize<'a> for Span<T> {
#[inline]
fn deserialize<D: Deserializer<'a>>(de: D) -> Result<Self, D::Error> {
struct Visitor<T>(PhantomData<T>);
impl<'a, T: Deserialize<'a>> de::Visitor<'a> for Visitor<T> {
type Value = Span<T>;
#[cold]
fn expecting(&self, fmt: &mut Formatter) -> fmt::Result {
fmt.write_str("a spanned value")
}
fn visit_seq<A: SeqAccess<'a>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let start = seq.next_element()?;
let data = seq.next_element()?;
let end = seq.next_element()?;
match (start, data, end) {
(Some(start), Some(data), Some(end)) => Ok(Span::with(data, start, end)),
_ => Err(de::Error::custom("invalid spanned value")),
}
}
}
de.deserialize_newtype_struct(TOKEN, Visitor(PhantomData))
}
}
impl<T: Serialize> Serialize for Span<T> {
#[inline]
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.data().serialize(serializer)
}
}