macro_rules! flavor {
(
$(#[doc = $doc:literal])*
$vis:vis struct $ty:ident {
type Index = $index:ty;
$(type Width = $width:ty;)?
$(type Error = $error:ty;)?
$(type Storage<$t:ident> = $storage:ty;)?
$(type Indexes = $indexes:ty;)?
}
) => { ... };
(@error $ty:ty) => { ... };
(@error) => { ... };
(@width $ty:ty) => { ... };
(@width) => { ... };
(@pointer $ty:ty) => { ... };
(@pointer) => { ... };
(@storage $t:ident $ty:ty) => { ... };
(@storage) => { ... };
(@indexes $ty:ty) => { ... };
(@indexes) => { ... };
}Expand description
Declare a new flavor.
The associated types are declared in this order, and all but Index are
optional:
type Index = ..;the Index used for spans.type Width = ..;the Width which bounds pointers, defaults tousize.type Error = ..;the error raised by storage, defaults toInfallible.type Storage<T> = ..;the Storage used for tree data, defaults toVec<T>(orEmptyVec<T>without theallocfeature).type Indexes = ..;the Storage ofTreeIndex<Self>, defaults toVec<TreeIndex<Self>>(orEmptyVecwithout theallocfeature), regardless ofStorage.
The Error of both Storage and Indexes must be the flavor’s Error,
so a flavor with a custom Error needs to declare both of them. Errors
raised by storage are reported as Error::Flavor.
§Examples
use syntree::{Empty, EmptyVec, TreeIndex};
syntree::flavor! {
struct FlavorEmpty {
type Index = Empty;
type Indexes = EmptyVec<TreeIndex<Self>>;
}
}
syntree::flavor! {
struct FlavorU32 {
type Index = u32;
type Width = u32;
}
}A flavor with custom fallible storage:
use core::ops::{Deref, DerefMut};
use syntree::{Builder, Error, Storage, TreeIndex};
#[derive(Debug, PartialEq)]
struct Full;
/// Storage which holds at most one item.
struct One<T>(Option<T>);
impl<T> Deref for One<T> {
type Target = [T];
fn deref(&self) -> &[T] {
self.0.as_slice()
}
}
impl<T> DerefMut for One<T> {
fn deref_mut(&mut self) -> &mut [T] {
self.0.as_mut_slice()
}
}
impl<T> Storage<T> for One<T> {
type Error = Full;
const EMPTY: Self = One(None);
fn with_capacity(capacity: usize) -> Result<Self, Full> {
if capacity > 1 {
return Err(Full);
}
Ok(One(None))
}
fn capacity(&self) -> usize {
1
}
fn push(&mut self, item: T) -> Result<(), Full> {
if self.0.is_some() {
return Err(Full);
}
self.0 = Some(item);
Ok(())
}
}
syntree::flavor! {
struct FlavorOne {
type Index = u32;
type Error = Full;
type Storage<T> = One<T>;
type Indexes = One<TreeIndex<Self>>;
}
}
let mut tree: Builder<_, FlavorOne> = Builder::new_with();
tree.token("a", 1)?;
assert_eq!(tree.token("b", 1), Err(Error::Flavor(Full)));