tex 0.1.1

The νTeX typesetting engine
Documentation
#![allow(dead_code, unused_variables)]

pub use tex_derive::Modifier;
use std::any::{Any, TypeId};
use std::collections::LinkedList;
use std::fmt::Debug;
use std::ops::Deref;
use std::rc::Rc;

pub trait Modifier: Any + Debug {
    fn id(&self) -> TypeId;
    fn apply(&self);
    fn relax(&self);
}

#[derive(Debug, Clone)]
pub struct ModifierType(Rc<dyn Modifier>);

impl ModifierType {
    pub fn new<T>(modifier: T) -> Self
    where
        T: Modifier,
    {
        Self(Rc::new(modifier))
    }

    pub fn id(&self) -> TypeId {
        (**self).id()
    }
}

impl PartialEq for ModifierType {
    fn eq(&self, other: &ModifierType) -> bool {
        self.id() == other.id()
    }
}

impl<T: Modifier> PartialEq<T> for ModifierType {
    fn eq(&self, other: &T) -> bool {
        self.id() == other.id()
    }
}

impl Deref for ModifierType {
    type Target = dyn Modifier;

    fn deref(&self) -> &dyn Modifier {
        &(*self.0)
    }
}

pub enum Relax {
    Pop,
    Cut(usize),
    Target(Vec<ModifierType>),
}

#[derive(Debug)]
pub struct Format {
    modifiers: Vec<ModifierType>,
    stack: LinkedList<Vec<ModifierType>>,
}

impl Format {
    pub fn new() -> Self {
        Self {
            modifiers: Vec::new(),
            stack: LinkedList::new(),
        }
    }

    pub fn apply(&mut self, modifier: ModifierType) {
        modifier.apply();
        self.modifiers.push(modifier);
    }

    pub fn relax(&mut self, op: Relax) {
        match op {
            Relax::Pop => {
                if let Some(modifier) = self.modifiers.pop() {
                    modifier.relax();
                }
            }
            Relax::Cut(count) => {
                let n = match self.modifiers.len().checked_sub(count) {
                    Some(value) => value,
                    None => self.modifiers.len(),
                };
                self.modifiers.drain(n..).rev().for_each(|m| m.relax());
            }
            Relax::Target(targets) => {
                for target in targets.iter() {
                    if let Some(idx) = self.modifiers.iter().rposition(|m| *m == *target) {
                        let modifier = self.modifiers.remove(idx);
                        modifier.relax();
                    }
                }
            }
        }
    }

    pub fn modifiers(&self) -> &Vec<ModifierType> {
        &self.modifiers
    }

    pub fn modifiers_mut(&mut self) -> &mut Vec<ModifierType> {
        &mut self.modifiers
    }

    pub fn save(&mut self) {
        self.stack.push_front(self.modifiers.clone());
    }

    pub fn load(&mut self) {
        let future = self.stack.pop_front().unwrap();
        let present = &self.modifiers;
        present.into_iter().rev().for_each(|m| m.relax());
        future.iter().for_each(|m| m.apply());
        self.modifiers = future;
    }
}

#[derive(Modifier, Debug, Copy, Clone)]
pub struct Null;

impl Null {
    pub fn new() -> ModifierType {
        ModifierType::new(Self)
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[derive(Modifier, Debug, Copy, Clone)]
    struct TestModifier;

    impl TestModifier {
        fn new() -> ModifierType {
            ModifierType::new(Self)
        }
    }

    #[test]
    fn modifier() {
        assert_eq!(Null::new(), Null::new());
        assert_eq!(Null::new(), Null);
        assert_ne!(Null::new(), TestModifier::new());
        assert_ne!(Null::new(), TestModifier);
    }

    #[test]
    fn format() {
        let mut format = Format::new();
        format.apply(Null::new());
        format.save();
        assert_eq!(format.modifiers(), &[Null; 1]);

        format.apply(Null::new());
        format.apply(Null::new());
        assert_eq!(format.modifiers(), &[Null; 3]);

        format.relax(Relax::Pop);
        assert_eq!(format.modifiers(), &[Null; 2]);

        format.load();
        assert_eq!(format.modifiers(), &[Null; 1]);

        format.relax(Relax::Pop);
        assert_eq!(format.modifiers(), &[Null; 0]);
    }
}