components-arena 0.0.5

Simple library for creating complex domain-specific self-referential data structures.
Documentation
#![deny(warnings)]

#[macro_use]
extern crate derivative;
#[macro_use]
extern crate macro_attr;
#[macro_use]
extern crate components_arena;

mod widgets {
    use components_arena::{Arena, Id, ComponentClassMutex};

    macro_attr! {
        #[derive(Component!(class=WidgetDataComponent))]
        struct WidgetData<T> {
            parent: Option<Id<WidgetData<T>>>,
            next: Id<WidgetData<T>>,
            last_child: Option<Id<WidgetData<T>>>,
            context: T
        }
    }

    static WIDGET: ComponentClassMutex<WidgetDataComponent> = ComponentClassMutex::new();

    pub struct Widgets<T> {
        arena: Arena<WidgetData<T>>,
        root: Id<WidgetData<T>>,
    }

    impl<T> Widgets<T> {
        pub fn new(context: T) -> Self {
            let mut arena = Arena::new();
            let root = arena.push(&mut WIDGET.lock().unwrap(), |this| WidgetData {
                parent: None, next: this, last_child: None, context
            });
            Widgets { arena, root }
        }

        pub fn root(&self) -> Widget<T> { Widget(self.root) }
    }

    #[derive(Derivative)]
    #[derivative(Debug(bound=""), Copy(bound=""), Clone(bound=""), Eq(bound=""), PartialEq(bound=""))]
    #[derivative(Hash(bound=""), Ord(bound=""), PartialOrd(bound=""))]
    pub struct Widget<T>(Id<WidgetData<T>>);

    impl<T> Widget<T> {
        pub fn new(widgets: &mut Widgets<T>, parent: Widget<T>, context: T) -> Widget<T> {
            let widget = widgets.arena.push(&mut WIDGET.lock().unwrap(), |this| WidgetData {
                parent: Some(parent.0), next: this, last_child: None, context
            });
            if let Some(prev) = widgets.arena[parent.0].last_child.replace(widget) {
                widgets.arena[widget].next = prev;
            }
            Widget(widget)
        }

        pub fn parent(self, widgets: &Widgets<T>) -> Option<Widget<T>> {
            widgets.arena[self.0].parent.map(Widget)
        }

        pub fn context(self, widgets: &Widgets<T>) -> &T {
            &widgets.arena[self.0].context
        }
    }
}

use widgets::*;

fn main() {
    let widgets = &mut Widgets::new(1u32);
    let widget = Widget::new(widgets, widgets.root(), 7u32);
    assert_eq!(widget.context(widgets), &7u32);
    assert_eq!(widget.parent(widgets), Some(widgets.root()));
}