use std::borrow::Cow;
pub trait Syntax: Sized {
type Root: Root<Ast = Self>;
type Block: Block<Ast = Self>;
type Admin: Admin<Ast = Self>;
type Mod: Mod<Ast = Self>;
type Inline: Inline<Ast = Self>;
type Emphasis: Emphasis<Ast = Self>;
type Icon: Icon<Ast = Self>;
type Link: Link<Ast = Self>;
type Newline: Newline;
type Strikethrough: Strikethrough<Ast = Self>;
type Strong: Strong<Ast = Self>;
type Text: Text<Ast = Self>;
}
#[derive(Debug)]
pub enum MaybeOwned<'a, T>
where
T: 'a,
{
Borrowed(&'a T),
Owned(T),
}
impl<T> std::ops::Deref for MaybeOwned<'_, T> {
type Target = T;
fn deref(&self) -> &T {
match self {
MaybeOwned::Borrowed(borrowed) => borrowed,
MaybeOwned::Owned(ref owned) => owned,
}
}
}
pub trait BlockContainer {
type Ast: Syntax;
fn children<'a>(&'a self) -> Box<dyn Iterator<Item = MaybeOwned<'a, <Self::Ast as Syntax>::Block>> + 'a>;
}
pub trait InlineContainer {
type Ast: Syntax;
fn children<'a>(&'a self) -> Box<dyn Iterator<Item = MaybeOwned<'a, <Self::Ast as Syntax>::Inline>> + 'a>;
}
pub trait Root: BlockContainer {
type Ast: Syntax;
}
pub trait Block {
type Ast: Syntax;
fn cast(&self) -> BlockCast<Self::Ast>;
}
pub enum BlockCast<'a, S: Syntax> {
Admin(MaybeOwned<'a, S::Admin>),
Mod(MaybeOwned<'a, S::Mod>),
Emphasis(MaybeOwned<'a, S::Emphasis>),
Icon(MaybeOwned<'a, S::Icon>),
Link(MaybeOwned<'a, S::Link>),
Newline(MaybeOwned<'a, S::Newline>),
Strikethrough(MaybeOwned<'a, S::Strikethrough>),
Strong(MaybeOwned<'a, S::Strong>),
Text(MaybeOwned<'a, S::Text>),
}
pub trait Admin: BlockContainer {
type Ast: Syntax;
}
pub trait Mod: BlockContainer {
type Ast: Syntax;
}
pub trait Inline {
type Ast: Syntax;
fn cast(&self) -> InlineCast<Self::Ast>;
}
pub enum InlineCast<'a, S: Syntax> {
Emphasis(MaybeOwned<'a, S::Emphasis>),
Icon(MaybeOwned<'a, S::Icon>),
Link(MaybeOwned<'a, S::Link>),
Newline(MaybeOwned<'a, S::Newline>),
Strikethrough(MaybeOwned<'a, S::Strikethrough>),
Strong(MaybeOwned<'a, S::Strong>),
Text(MaybeOwned<'a, S::Text>),
}
pub trait Emphasis: InlineContainer {
type Ast: Syntax;
}
pub trait Icon {
type Ast: Syntax;
fn key(&self) -> Cow<str>;
}
pub trait Link: InlineContainer {
type Ast: Syntax;
fn uri(&self) -> Cow<str>;
}
pub trait Newline {}
pub trait Strikethrough: InlineContainer {
type Ast: Syntax;
}
pub trait Strong: InlineContainer {
type Ast: Syntax;
}
pub trait Text {
type Ast: Syntax;
fn text(&self) -> Cow<str>;
}