tin 0.3.0

tin: a statically structurally typed embeddable programming language
Documentation
use std::fmt;

use specs::Component;
use specs::VecStorage;

#[derive(Clone, Component, Debug, VisitEntities, VisitEntitiesMut)]
#[storage(VecStorage)]
pub struct Layout {
    pub size: usize,
    pub alignment: usize,
    pub named_fields: Option<Vec<NamedField>>,
    pub unnamed_fields: Option<Vec<OffsetLayout>>,
}

#[derive(Clone, Debug, VisitEntities, VisitEntitiesMut)]
pub struct NamedField {
    pub field: String,
    pub offset_layout: OffsetLayout,
}

#[derive(Clone, Debug, VisitEntities, VisitEntitiesMut)]
pub struct OffsetLayout {
    pub offset: usize,
    pub layout: Layout,
}

impl Layout {
    pub const fn zero() -> Layout {
        Layout {
            size: 0,
            alignment: 1,
            named_fields: None,
            unnamed_fields: None,
        }
    }

    pub const fn scalar(size: usize) -> Layout {
        Layout {
            size,
            alignment: size,
            named_fields: None,
            unnamed_fields: None,
        }
    }

    pub fn named_fields(size: usize, alignment: usize, named_fields: Vec<NamedField>) -> Layout {
        let named_fields = Some(named_fields);
        let unnamed_fields = None;

        Layout {
            size,
            alignment,
            named_fields,
            unnamed_fields,
        }
    }

    pub fn unnamed_fields(
        size: usize,
        alignment: usize,
        unnamed_fields: Vec<OffsetLayout>,
    ) -> Layout {
        let named_fields = None;
        let unnamed_fields = Some(unnamed_fields);

        Layout {
            size,
            alignment,
            named_fields,
            unnamed_fields,
        }
    }
}

impl OffsetLayout {
    pub const fn zero() -> OffsetLayout {
        OffsetLayout {
            offset: 0,
            layout: Layout::zero(),
        }
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}/{}", self.size, self.alignment)?;

        if self
            .named_fields
            .as_ref()
            .map(|v| !v.is_empty())
            .unwrap_or(false)
        {
            write!(f, "[")?;

            let mut needs_sep = false;
            for named_field in self.named_fields.as_ref().unwrap() {
                if needs_sep {
                    write!(f, ",")?;
                }
                write!(f, "{:?}:{}", named_field.field, named_field.offset_layout)?;
                needs_sep = true;
            }

            write!(f, "]")?;
        }

        if self
            .unnamed_fields
            .as_ref()
            .map(|v| !v.is_empty())
            .unwrap_or(false)
        {
            write!(f, "[")?;

            let mut needs_sep = false;
            for (idx, offset) in self.unnamed_fields.as_ref().unwrap().iter().enumerate() {
                if needs_sep {
                    write!(f, ",")?;
                }
                write!(f, "{}:{}", idx, offset)?;
                needs_sep = true;
            }

            write!(f, "]")?;
        }

        Ok(())
    }
}

impl fmt::Display for OffsetLayout {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}({})", self.offset, self.layout)
    }
}