use std::{convert::Infallible, error::Error};
use crate::{BareItemFromInput, KeyRef};
pub trait ParameterVisitor<'de> {
type Out;
type Error: Error;
fn parameter(
&mut self,
key: &'de KeyRef,
value: BareItemFromInput<'de>,
) -> Result<(), Self::Error>;
fn finish(self) -> Result<Self::Out, Self::Error>;
}
pub trait ItemVisitor<'de> {
type Out;
type Error: Error;
fn bare_item(
self,
bare_item: BareItemFromInput<'de>,
) -> Result<impl ParameterVisitor<'de, Out = Self::Out>, Self::Error>;
}
impl<'de, F, V, E> ItemVisitor<'de> for F
where
F: FnOnce(BareItemFromInput<'de>) -> Result<V, E>,
V: ParameterVisitor<'de>,
E: Error,
{
type Out = V::Out;
type Error = E;
fn bare_item(
self,
bare_item: BareItemFromInput<'de>,
) -> Result<impl ParameterVisitor<'de, Out = Self::Out>, Self::Error> {
self(bare_item)
}
}
pub trait InnerListVisitor<'de> {
type Error: Error;
fn item(&mut self) -> Result<impl ItemVisitor<'de>, Self::Error>;
fn finish(self) -> Result<impl ParameterVisitor<'de>, Self::Error>;
}
pub trait EntryVisitor<'de> {
type Error: Error;
fn item(self) -> Result<impl ItemVisitor<'de>, Self::Error>;
fn inner_list(self) -> Result<impl InnerListVisitor<'de>, Self::Error>;
}
pub trait DictionaryVisitor<'de> {
type Out;
type Error: Error;
fn entry(&mut self, key: &'de KeyRef) -> Result<impl EntryVisitor<'de>, Self::Error>;
fn finish(self) -> Result<Self::Out, Self::Error>;
}
pub trait ListVisitor<'de> {
type Out;
type Error: Error;
fn entry(&mut self) -> Result<impl EntryVisitor<'de>, Self::Error>;
fn finish(self) -> Result<Self::Out, Self::Error>;
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Ignored;
impl<'de> ParameterVisitor<'de> for Ignored {
type Out = ();
type Error = Infallible;
fn parameter(
&mut self,
_key: &'de KeyRef,
_value: BareItemFromInput<'de>,
) -> Result<(), Self::Error> {
Ok(())
}
fn finish(self) -> Result<Self::Out, Self::Error> {
Ok(())
}
}
impl<'de> ItemVisitor<'de> for Ignored {
type Out = ();
type Error = Infallible;
fn bare_item(
self,
_bare_item: BareItemFromInput<'de>,
) -> Result<impl ParameterVisitor<'de, Out = Self::Out>, Self::Error> {
Ok(Ignored)
}
}
impl<'de> EntryVisitor<'de> for Ignored {
type Error = Infallible;
fn item(self) -> Result<impl ItemVisitor<'de>, Self::Error> {
Ok(Ignored)
}
fn inner_list(self) -> Result<impl InnerListVisitor<'de>, Self::Error> {
Ok(Ignored)
}
}
impl<'de> InnerListVisitor<'de> for Ignored {
type Error = Infallible;
fn item(&mut self) -> Result<impl ItemVisitor<'de>, Self::Error> {
Ok(Ignored)
}
fn finish(self) -> Result<impl ParameterVisitor<'de>, Self::Error> {
Ok(Ignored)
}
}
impl<'de> DictionaryVisitor<'de> for Ignored {
type Out = ();
type Error = Infallible;
fn entry(&mut self, _key: &'de KeyRef) -> Result<impl EntryVisitor<'de>, Self::Error> {
Ok(Ignored)
}
fn finish(self) -> Result<Self::Out, Self::Error> {
Ok(())
}
}
impl<'de> ListVisitor<'de> for Ignored {
type Out = ();
type Error = Infallible;
fn entry(&mut self) -> Result<impl EntryVisitor<'de>, Self::Error> {
Ok(Ignored)
}
fn finish(self) -> Result<Self::Out, Self::Error> {
Ok(())
}
}
fn map_visitor<V, T, E>(
visitor: Option<V>,
f: impl FnOnce(V) -> Result<T, E>,
) -> Result<Option<T>, E> {
match visitor {
None => Ok(None),
Some(visitor) => f(visitor).map(Some),
}
}
impl<'de, V: ParameterVisitor<'de>> ParameterVisitor<'de> for Option<V> {
type Out = Option<V::Out>;
type Error = V::Error;
fn parameter(
&mut self,
key: &'de KeyRef,
value: BareItemFromInput<'de>,
) -> Result<(), Self::Error> {
match *self {
None => Ok(()),
Some(ref mut visitor) => visitor.parameter(key, value),
}
}
fn finish(self) -> Result<Self::Out, Self::Error> {
map_visitor(self, V::finish)
}
}
impl<'de, V: ItemVisitor<'de>> ItemVisitor<'de> for Option<V> {
type Out = Option<V::Out>;
type Error = V::Error;
fn bare_item(
self,
bare_item: BareItemFromInput<'de>,
) -> Result<impl ParameterVisitor<'de, Out = Self::Out>, Self::Error> {
map_visitor(self, |visitor| visitor.bare_item(bare_item))
}
}
impl<'de, V: EntryVisitor<'de>> EntryVisitor<'de> for Option<V> {
type Error = V::Error;
fn item(self) -> Result<impl ItemVisitor<'de>, Self::Error> {
map_visitor(self, V::item)
}
fn inner_list(self) -> Result<impl InnerListVisitor<'de>, Self::Error> {
map_visitor(self, V::inner_list)
}
}
impl<'de, V: InnerListVisitor<'de>> InnerListVisitor<'de> for Option<V> {
type Error = V::Error;
fn item(&mut self) -> Result<impl ItemVisitor<'de>, Self::Error> {
map_visitor(self.as_mut(), V::item)
}
fn finish(self) -> Result<impl ParameterVisitor<'de>, Self::Error> {
map_visitor(self, V::finish)
}
}
#[derive(Clone, Copy, Debug)]
pub enum Never {}
impl<'de> ParameterVisitor<'de> for Never {
type Out = ();
type Error = Infallible;
fn parameter(
&mut self,
_key: &'de KeyRef,
_value: BareItemFromInput<'de>,
) -> Result<(), Self::Error> {
match *self {}
}
fn finish(self) -> Result<Self::Out, Self::Error> {
match self {}
}
}
impl<'de> ItemVisitor<'de> for Never {
type Out = ();
type Error = Infallible;
fn bare_item(
self,
_bare_item: BareItemFromInput<'de>,
) -> Result<impl ParameterVisitor<'de, Out = Self::Out>, Self::Error> {
Ok(self)
}
}
impl<'de> EntryVisitor<'de> for Never {
type Error = Infallible;
fn item(self) -> Result<impl ItemVisitor<'de>, Self::Error> {
Ok(self)
}
fn inner_list(self) -> Result<impl InnerListVisitor<'de>, Self::Error> {
Ok(self)
}
}
impl<'de> InnerListVisitor<'de> for Never {
type Error = Infallible;
fn item(&mut self) -> Result<impl ItemVisitor<'de>, Self::Error> {
Ok(*self)
}
fn finish(self) -> Result<impl ParameterVisitor<'de>, Self::Error> {
Ok(self)
}
}
pub fn parameter_visitor_with<'de, V, T>(
visitor: V,
finish: impl FnOnce(V::Out) -> Result<T, V::Error>,
) -> impl ParameterVisitor<'de, Out = T, Error = V::Error>
where
V: ParameterVisitor<'de>,
{
ParameterVisitorWith { visitor, finish }
}
struct ParameterVisitorWith<V, F> {
visitor: V,
finish: F,
}
impl<'de, V, F, T> ParameterVisitor<'de> for ParameterVisitorWith<V, F>
where
V: ParameterVisitor<'de>,
F: FnOnce(V::Out) -> Result<T, V::Error>,
{
type Out = T;
type Error = V::Error;
fn parameter(
&mut self,
key: &'de KeyRef,
value: BareItemFromInput<'de>,
) -> Result<(), Self::Error> {
self.visitor.parameter(key, value)
}
fn finish(self) -> Result<Self::Out, Self::Error> {
(self.finish)(self.visitor.finish()?)
}
}
pub trait MakeItemVisitor<'de> {
fn make_item_visitor() -> impl ItemVisitor<'de, Out = Self>;
}
pub trait MakeListVisitor<'de> {
fn make_list_visitor() -> impl ListVisitor<'de, Out = Self>;
}
pub trait MakeDictionaryVisitor<'de> {
fn make_dictionary_visitor() -> impl DictionaryVisitor<'de, Out = Self>;
}
impl<'de, V> MakeItemVisitor<'de> for V
where
V: ItemVisitor<'de, Out = Self> + Default,
{
fn make_item_visitor() -> impl ItemVisitor<'de, Out = Self> {
V::default()
}
}
impl<'de, V> MakeListVisitor<'de> for V
where
V: ListVisitor<'de, Out = Self> + Default,
{
fn make_list_visitor() -> impl ListVisitor<'de, Out = Self> {
V::default()
}
}
impl<'de, V> MakeDictionaryVisitor<'de> for V
where
V: DictionaryVisitor<'de, Out = Self> + Default,
{
fn make_dictionary_visitor() -> impl DictionaryVisitor<'de, Out = Self> {
V::default()
}
}
#[allow(clippy::unnecessary_wraps)]
fn infallible_bare_item_visitor<'de, T>(
bare_item: BareItemFromInput<'de>,
) -> Result<impl ParameterVisitor<'de, Out = T>, Infallible>
where
T: From<BareItemFromInput<'de>>,
{
Ok(parameter_visitor_with(Ignored, |()| Ok(T::from(bare_item))))
}
impl<'de> MakeItemVisitor<'de> for BareItemFromInput<'de> {
fn make_item_visitor() -> impl ItemVisitor<'de, Out = Self> {
infallible_bare_item_visitor
}
}
impl<'de> MakeItemVisitor<'de> for super::BareItem {
fn make_item_visitor() -> impl ItemVisitor<'de, Out = Self> {
infallible_bare_item_visitor
}
}
#[derive(Debug)]
enum BareItemType {
Decimal,
Integer,
String,
ByteSequence,
Boolean,
Token,
Date,
DisplayString,
}
impl BareItemFromInput<'_> {
fn ty(&self) -> BareItemType {
match *self {
Self::Decimal(_) => BareItemType::Decimal,
Self::Integer(_) => BareItemType::Integer,
Self::String(_) => BareItemType::String,
Self::ByteSequence(_) => BareItemType::ByteSequence,
Self::Boolean(_) => BareItemType::Boolean,
Self::Token(_) => BareItemType::Token,
Self::Date(_) => BareItemType::Date,
Self::DisplayString(_) => BareItemType::DisplayString,
}
}
}
impl std::fmt::Display for BareItemType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.write_str(match *self {
Self::Decimal => "decimal",
Self::Integer => "integer",
Self::String => "string",
Self::ByteSequence => "byte sequence",
Self::Boolean => "boolean",
Self::Token => "token",
Self::Date => "date",
Self::DisplayString => "display string",
})
}
}
#[derive(Debug)]
struct UnexpectedBareItemType {
expected: BareItemType,
got: BareItemType,
}
impl std::fmt::Display for UnexpectedBareItemType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"unexpected bare item type: expected {}, got {}",
self.expected, self.got
)
}
}
impl Error for UnexpectedBareItemType {}
macro_rules! impl_make_item_visitor_ignoring_params {
($($var: ident($t: ty) $doc: literal,)+) => {
$(
/// Makes an item visitor expecting
#[doc = $doc]
/// bare item and ignoring parameters.
impl<'de> MakeItemVisitor<'de> for $t {
fn make_item_visitor() -> impl ItemVisitor<'de, Out = Self> {
|v| {
if let BareItemFromInput::$var(v) = v {
Ok(parameter_visitor_with(Ignored, move |()| Ok(v)))
} else {
Err(UnexpectedBareItemType {
expected: BareItemType::$var,
got: v.ty(),
})
}
}
}
}
)+
};
}
impl_make_item_visitor_ignoring_params! {
Decimal(super::Decimal) "a decimal",
Integer(super::Integer) "an integer",
String(std::borrow::Cow<'de, super::StringRef>) "a string",
ByteSequence(Vec<u8>) "a byte sequence",
Boolean(bool) "a boolean",
Token(&'de super::TokenRef) "a token",
Date(super::Date) "a date",
}