use super::*;
#[derive(Educe)]
#[educe(Clone, Copy, Default)]
pub struct MultiplicitySelector<Field>(PhantomData<fn() -> Field>);
pub trait ItemSetMethods: Copy + Sized {
type Each: Sized;
type Field: Sized;
fn can_accumulate(self, acc: &Option<Self::Field>) -> Result<(), EP>;
fn accumulate(self, acc: &mut Option<Self::Field>, one: Self::Each) -> Result<(), EP>;
fn finish(
self,
acc: Option<Self::Field>,
item_keyword: &'static str,
) -> Result<Self::Field, EP>;
fn is_intro_item_keyword(self, kw: KeywordRef<'_>) -> bool
where
Self::Each: NetdocParseable,
{
Self::Each::is_intro_item_keyword(kw)
}
fn is_structural_keyword(self, kw: KeywordRef<'_>) -> Option<IsStructural>
where
Self::Each: NetdocParseable,
{
Self::Each::is_structural_keyword(kw)
}
fn finish_subdoc(self, acc: Option<Self::Field>) -> Result<Self::Field, EP>
where
Self::Each: NetdocParseable,
{
self.finish(acc, Self::Each::doctype_for_error())
}
fn check_item_value_parseable(self)
where
Self::Each: ItemValueParseable,
{
}
fn check_signature_item_parseable<H>(self, _: &mut H)
where
Self::Each: SignatureItemParseable,
H: AsMut<<Self::Each as SignatureItemParseable>::HashAccu>,
{
}
fn check_subdoc_parseable(self)
where
Self::Each: NetdocParseable,
{
}
fn check_item_argument_parseable(self)
where
Self::Each: ItemArgumentParseable,
{
}
}
impl<T> ItemSetMethods for MultiplicitySelector<Vec<T>> {
type Each = T;
type Field = Vec<T>;
fn can_accumulate(self, _acc: &Option<Vec<T>>) -> Result<(), EP> {
Ok(())
}
fn accumulate(self, acc: &mut Option<Vec<T>>, item: T) -> Result<(), EP> {
acc.get_or_insert_default().push(item);
Ok(())
}
fn finish(self, acc: Option<Vec<T>>, _keyword: &'static str) -> Result<Vec<T>, EP> {
Ok(acc.unwrap_or_default())
}
}
impl<T: Ord> ItemSetMethods for MultiplicitySelector<BTreeSet<T>> {
type Each = T;
type Field = BTreeSet<T>;
fn can_accumulate(self, _acc: &Option<BTreeSet<T>>) -> Result<(), EP> {
Ok(())
}
fn accumulate(self, acc: &mut Option<BTreeSet<T>>, item: T) -> Result<(), EP> {
if !acc.get_or_insert_default().insert(item) {
return Err(EP::ItemRepeated);
}
Ok(())
}
fn finish(self, acc: Option<BTreeSet<T>>, _keyword: &'static str) -> Result<BTreeSet<T>, EP> {
Ok(acc.unwrap_or_default())
}
}
impl<T> ItemSetMethods for MultiplicitySelector<Option<T>> {
type Each = T;
type Field = Option<T>;
fn can_accumulate(self, acc: &Option<Option<T>>) -> Result<(), EP> {
if acc.is_some() {
Err(EP::ItemRepeated)?;
}
Ok(())
}
fn accumulate(self, acc: &mut Option<Option<T>>, item: T) -> Result<(), EP> {
self.can_accumulate(acc)?;
*acc = Some(Some(item));
Ok(())
}
fn finish(self, acc: Option<Option<T>>, _keyword: &'static str) -> Result<Option<T>, EP> {
Ok(acc.flatten())
}
}
impl<T> ItemSetMethods for &'_ MultiplicitySelector<T> {
type Each = T;
type Field = T;
fn can_accumulate(self, acc: &Option<T>) -> Result<(), EP> {
if acc.is_some() {
Err(EP::ItemRepeated)?;
}
Ok(())
}
fn accumulate(self, acc: &mut Option<T>, item: T) -> Result<(), EP> {
self.can_accumulate(acc)?;
*acc = Some(item);
Ok(())
}
fn finish(self, acc: Option<T>, keyword: &'static str) -> Result<T, EP> {
acc.ok_or(EP::MissingItem { keyword })
}
}
pub trait ArgumentSetMethods: Copy + Sized {
type Each: Sized;
type Field: Sized;
fn parse_with<P>(self, args: &mut ArgumentStream<'_>, parser: P) -> Result<Self::Field, AE>
where
P: for<'s> Fn(&mut ArgumentStream<'s>) -> Result<Self::Each, AE>;
fn check_argument_value_parseable(self)
where
Self::Each: ItemArgumentParseable,
{
}
}
impl<T> ArgumentSetMethods for MultiplicitySelector<Vec<T>> {
type Each = T;
type Field = Vec<T>;
fn parse_with<P>(self, args: &mut ArgumentStream<'_>, parser: P) -> Result<Self::Field, AE>
where
P: for<'s> Fn(&mut ArgumentStream<'s>) -> Result<Self::Each, AE>,
{
let mut acc = vec![];
while args.something_to_yield() {
acc.push(parser(args)?);
}
Ok(acc)
}
}
impl<T: Ord> ArgumentSetMethods for MultiplicitySelector<BTreeSet<T>> {
type Each = T;
type Field = BTreeSet<T>;
fn parse_with<P>(self, args: &mut ArgumentStream<'_>, parser: P) -> Result<Self::Field, AE>
where
P: for<'s> Fn(&mut ArgumentStream<'s>) -> Result<Self::Each, AE>,
{
let mut acc = BTreeSet::new();
while args.something_to_yield() {
if !acc.insert(parser(args)?) {
return Err(AE::Invalid);
}
}
Ok(acc)
}
}
impl<T> ArgumentSetMethods for MultiplicitySelector<Option<T>> {
type Each = T;
type Field = Option<T>;
fn parse_with<P>(self, args: &mut ArgumentStream<'_>, parser: P) -> Result<Self::Field, AE>
where
P: for<'s> Fn(&mut ArgumentStream<'s>) -> Result<Self::Each, AE>,
{
if !args.something_to_yield() {
return Ok(None);
}
Ok(Some(parser(args)?))
}
}
impl<T> ArgumentSetMethods for &MultiplicitySelector<T> {
type Each = T;
type Field = T;
fn parse_with<P>(self, args: &mut ArgumentStream<'_>, parser: P) -> Result<Self::Field, AE>
where
P: for<'s> Fn(&mut ArgumentStream<'s>) -> Result<Self::Each, AE>,
{
parser(args)
}
}
pub trait ObjectSetMethods: Copy + Sized {
type Each: Sized;
type Field: Sized;
fn resolve_option(self, found: Option<Self::Each>) -> Result<Self::Field, EP>;
fn check_label(self, label: &str) -> Result<(), EP>
where
Self::Each: ItemObjectParseable,
{
Self::Each::check_label(label)
}
fn check_object_parseable(self)
where
Self::Each: ItemObjectParseable,
{
}
}
impl<T> ObjectSetMethods for MultiplicitySelector<Option<T>> {
type Field = Option<T>;
type Each = T;
fn resolve_option(self, found: Option<Self::Each>) -> Result<Self::Field, EP> {
Ok(found)
}
}
impl<T> ObjectSetMethods for &MultiplicitySelector<T> {
type Field = T;
type Each = T;
fn resolve_option(self, found: Option<Self::Each>) -> Result<Self::Field, EP> {
found.ok_or(EP::MissingObject)
}
}