use std::convert::Infallible;
use indexmap::IndexMap;
use crate::{
private::Sealed,
visitor::{
DictionaryVisitor, EntryVisitor, InnerListVisitor, ItemVisitor, ListVisitor,
ParameterVisitor,
},
BareItem, BareItemFromInput, Error, Key, KeyRef, Parser,
};
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Item {
pub bare_item: BareItem,
pub params: Parameters,
}
impl Item {
#[must_use]
pub fn new(bare_item: impl Into<BareItem>) -> Self {
Self {
bare_item: bare_item.into(),
params: Parameters::new(),
}
}
#[must_use]
pub fn with_params(bare_item: impl Into<BareItem>, params: Parameters) -> Self {
Self {
bare_item: bare_item.into(),
params,
}
}
}
pub type Dictionary = IndexMap<Key, ListEntry>;
pub type List = Vec<ListEntry>;
pub type Parameters = IndexMap<Key, BareItem>;
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum ListEntry {
Item(Item),
InnerList(InnerList),
}
impl From<Item> for ListEntry {
fn from(item: Item) -> Self {
ListEntry::Item(item)
}
}
impl From<InnerList> for ListEntry {
fn from(inner_list: InnerList) -> Self {
ListEntry::InnerList(inner_list)
}
}
#[derive(Debug, Default, PartialEq, Clone)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct InnerList {
pub items: Vec<Item>,
pub params: Parameters,
}
impl InnerList {
#[must_use]
pub fn new(items: Vec<Item>) -> Self {
Self {
items,
params: Parameters::new(),
}
}
#[must_use]
pub fn with_params(items: Vec<Item>, params: Parameters) -> Self {
Self { items, params }
}
}
impl<'de> ParameterVisitor<'de> for &mut Parameters {
type Error = Infallible;
fn parameter(
&mut self,
key: &'de KeyRef,
value: BareItemFromInput<'de>,
) -> Result<(), Self::Error> {
self.insert(key.to_owned(), value.into());
Ok(())
}
}
impl<'de> ItemVisitor<'de> for &mut Item {
type Error = Infallible;
fn bare_item(
self,
bare_item: BareItemFromInput<'de>,
) -> Result<impl ParameterVisitor<'de>, Self::Error> {
self.bare_item = bare_item.into();
Ok(&mut self.params)
}
}
impl<'de> ItemVisitor<'de> for &mut InnerList {
type Error = Infallible;
fn bare_item(
self,
bare_item: BareItemFromInput<'de>,
) -> Result<impl ParameterVisitor<'de>, Self::Error> {
self.items.push(Item::new(bare_item));
match self.items.last_mut() {
Some(item) => Ok(&mut item.params),
None => unreachable!(),
}
}
}
impl<'de> InnerListVisitor<'de> for &mut InnerList {
type Error = Infallible;
fn item(&mut self) -> Result<impl ItemVisitor<'de>, Self::Error> {
Ok(&mut **self)
}
fn finish(self) -> Result<impl ParameterVisitor<'de>, Self::Error> {
Ok(&mut self.params)
}
}
impl<'de> DictionaryVisitor<'de> for Dictionary {
type Error = Infallible;
fn entry(&mut self, key: &'de KeyRef) -> Result<impl EntryVisitor<'de>, Self::Error> {
Ok(self.entry(key.to_owned()))
}
}
type Entry<'a> = indexmap::map::Entry<'a, Key, ListEntry>;
impl<'de> ItemVisitor<'de> for Entry<'_> {
type Error = Infallible;
fn bare_item(
self,
bare_item: BareItemFromInput<'de>,
) -> Result<impl ParameterVisitor<'de>, Self::Error> {
match self.insert_entry(Item::new(bare_item).into()).into_mut() {
ListEntry::Item(item) => Ok(&mut item.params),
ListEntry::InnerList(_) => unreachable!(),
}
}
}
impl<'de> EntryVisitor<'de> for Entry<'_> {
fn inner_list(self) -> Result<impl InnerListVisitor<'de>, Self::Error> {
match self.insert_entry(InnerList::default().into()).into_mut() {
ListEntry::InnerList(inner_list) => Ok(inner_list),
ListEntry::Item(_) => unreachable!(),
}
}
}
impl<'de> ItemVisitor<'de> for &mut List {
type Error = Infallible;
fn bare_item(
self,
bare_item: BareItemFromInput<'de>,
) -> Result<impl ParameterVisitor<'de>, Self::Error> {
self.push(Item::new(bare_item).into());
match self.last_mut() {
Some(ListEntry::Item(item)) => Ok(&mut item.params),
_ => unreachable!(),
}
}
}
impl<'de> EntryVisitor<'de> for &mut List {
fn inner_list(self) -> Result<impl InnerListVisitor<'de>, Self::Error> {
self.push(InnerList::default().into());
match self.last_mut() {
Some(ListEntry::InnerList(inner_list)) => Ok(inner_list),
_ => unreachable!(),
}
}
}
impl<'de> ListVisitor<'de> for List {
type Error = Infallible;
fn entry(&mut self) -> Result<impl EntryVisitor<'de>, Self::Error> {
Ok(self)
}
}
pub trait FieldType: Sealed {
type SerializeResult: Into<Option<String>>;
#[must_use]
fn serialize(&self) -> Self::SerializeResult;
fn parse(parser: Parser<'_>) -> Result<Self, Error>
where
Self: Sized;
}
impl Sealed for Item {}
impl FieldType for Item {
type SerializeResult = String;
fn serialize(&self) -> String {
crate::ItemSerializer::new()
.bare_item(&self.bare_item)
.parameters(&self.params)
.finish()
}
fn parse(parser: Parser<'_>) -> Result<Self, Error> {
let mut item = Self::new(false);
parser.parse_item_with_visitor(&mut item)?;
Ok(item)
}
}
impl Sealed for List {}
impl FieldType for List {
type SerializeResult = Option<String>;
fn serialize(&self) -> Option<String> {
let mut ser = crate::ListSerializer::new();
ser.members(self);
ser.finish()
}
fn parse(parser: Parser<'_>) -> Result<Self, Error> {
let mut list = Self::new();
parser.parse_list_with_visitor(&mut list)?;
Ok(list)
}
}
impl Sealed for Dictionary {}
impl FieldType for Dictionary {
type SerializeResult = Option<String>;
fn serialize(&self) -> Option<String> {
let mut ser = crate::DictSerializer::new();
ser.members(self);
ser.finish()
}
fn parse(parser: Parser<'_>) -> Result<Self, Error> {
let mut dict = Self::new();
parser.parse_dictionary_with_visitor(&mut dict)?;
Ok(dict)
}
}