Expand description
Annotations over recursive data structures.
An Annotation
is a type that annotates a child of a recursive data
structure with some extra information. Implementing it for a type allows that
type to also be an annotation over a reference to a child.
The Annotated
type is provided to compute and store the annotation over a
reference to a child. Annotations are computed lazily, triggered by when a
reference to them is asked for.
Example
extern crate alloc;
use alloc::rc::Rc;
use core::mem;
use ranno::{Annotated, Annotation};
#[derive(Debug, Default, Clone, PartialEq, Eq)]
struct Cardinality(usize);
impl<T> Annotation<LinkedList<T, Cardinality>> for Cardinality {
fn from_child(list: &LinkedList<T, Cardinality>) -> Self {
let c = match list {
LinkedList::Empty => 0,
LinkedList::Node { next, .. } => 1 + next.anno().0,
};
// the cardinality of a linked list is just the cardinality of the
// next element added to the current one
Self(c)
}
}
enum LinkedList<T, A> {
Empty,
Node {
elem: T,
// the cardinality of a linked list is just the cardinality of the
// next element added to the current one
next: Annotated<Rc<LinkedList<T, A>>, A>,
},
}
impl<T, A> LinkedList<T, A>
where
A: Annotation<LinkedList<T, A>>,
{
fn new() -> Self {
Self::Empty
}
fn push(&mut self, elem: T) {
let mut next = Self::Empty;
mem::swap(&mut next, self);
let next = Annotated::new(Rc::new(next));
*self = Self::Node { elem, next };
}
fn pop(&mut self) -> Option<T> {
let mut node = Self::Empty;
mem::swap(&mut node, self);
match node {
LinkedList::Empty => None,
LinkedList::Node { elem, next } => {
let (next, _) = next.split();
match Rc::try_unwrap(next) {
Ok(list) => {
*self = list;
Some(elem)
}
Err(next) => {
let next = Annotated::new(next);
*self = Self::Node { elem, next };
None
}
}
}
}
}
}
let mut list = LinkedList::<_, Cardinality>::new();
assert_eq!(Cardinality::from_child(&list), Cardinality(0));
list.push(1);
assert_eq!(Cardinality::from_child(&list), Cardinality(1));
list.push(2);
assert_eq!(Cardinality::from_child(&list), Cardinality(2));
list.pop();
assert_eq!(Cardinality::from_child(&list), Cardinality(1));
Structs
A child annotated with some metadata.
A mutable reference to an annotated child.
Traits
Annotation over a child.