rustex_lib 0.1.12

A crate for converting TeX/pdfTeX to HTML
Documentation
use std::borrow::Cow;
use std::fmt::{Debug, Formatter};
use std::ops::{Add, AddAssign};
use tex_engine::tex::numerics::{Dim32, Skip, StretchShrink};

#[derive(Copy, Clone, Debug)]
pub(crate) enum Flex {
    Fixed(i32),
    Fil(i32),
    Fill(i32),
    Filll(i32),
}
impl Default for Flex {
    fn default() -> Self {
        Flex::Fixed(0)
    }
}
impl Flex {
    fn is_zero(&self) -> bool {
        match self {
            Flex::Fixed(0) => true,
            _ => false,
        }
    }
}
impl Add for Flex {
    type Output = Self;
    fn add(self, other: Self) -> Self {
        match (self, other) {
            (Flex::Fixed(a), Flex::Fixed(b)) => Flex::Fixed(a + b),
            (Flex::Fil(a), Flex::Fil(b)) => Flex::Fil(a + b),
            (Flex::Fill(a), Flex::Fill(b)) => Flex::Fill(a + b),
            (Flex::Filll(a), Flex::Filll(b)) => Flex::Filll(a + b),
            (Flex::Fixed(_), Flex::Fil(b)) => Flex::Fil(b),
            (Flex::Fil(a), Flex::Fixed(_)) => Flex::Fil(a),
            (Flex::Fixed(_) | Flex::Fil(_), Flex::Fill(b)) => Flex::Fill(b),
            (Flex::Fill(a), Flex::Fixed(_) | Flex::Fil(_)) => Flex::Fill(a),
            (_, Flex::Filll(b)) => Flex::Filll(b),
            (Flex::Filll(a), _) => Flex::Filll(a),
        }
    }
}
impl From<StretchShrink<Dim32>> for Flex {
    fn from(ss: StretchShrink<Dim32>) -> Self {
        match ss {
            StretchShrink::Dim(d) => Flex::Fixed(d.0),
            StretchShrink::Fil(d) if d != 0 => Flex::Fil(d),
            StretchShrink::Fill(d) if d != 0 => Flex::Fill(d),
            StretchShrink::Filll(d) if d != 0 => Flex::Filll(d),
            _ => Flex::Fixed(0),
        }
    }
}
#[derive(Copy, Clone)]
pub(crate) struct Margin {
    pub(crate) base: i32,
    pub(crate) stretch: Flex,
    pub(crate) shrink: Flex,
}
impl Debug for Margin {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "<skip {}", self.base)?;
        if !self.stretch.is_zero() {
            write!(f, " plus {:?}", self.stretch)?;
        }
        if !self.shrink.is_zero() {
            write!(f, " minus {:?}", self.shrink)?;
        }
        f.write_str(">")
    }
}
impl Margin {
    pub(crate) fn fil() -> Self {
        Self {
            base: 0,
            stretch: Flex::Fil(1),
            shrink: Flex::Fixed(0),
        }
    }
    pub(crate) fn fill() -> Self {
        Self {
            base: 0,
            stretch: Flex::Fill(1),
            shrink: Flex::Fixed(0),
        }
    }
    pub(crate) fn filll() -> Self {
        Self {
            base: 0,
            stretch: Flex::Filll(1),
            shrink: Flex::Fixed(0),
        }
    }
    pub(crate) fn ss() -> Self {
        Self {
            base: 0,
            stretch: Flex::Fil(1),
            shrink: Flex::Fil(1),
        }
    }
    pub(crate) fn is_zero(&self) -> bool {
        self.base == 0 && self.stretch.is_zero() && self.shrink.is_zero()
    }
}
impl Add for Margin {
    type Output = Self;
    fn add(self, other: Self) -> Self {
        Self {
            base: self.base + other.base,
            stretch: self.stretch + other.stretch,
            shrink: self.shrink + other.shrink,
        }
    }
}
impl From<Skip<Dim32>> for Margin {
    fn from(skip: Skip<Dim32>) -> Self {
        let base = skip.base.0;
        let stretch = skip.stretch.map(|s| s.into()).unwrap_or_default();
        let shrink = skip.shrink.map(|s| s.into()).unwrap_or_default();
        Self {
            base,
            stretch,
            shrink,
        }
    }
}
impl From<Dim32> for Margin {
    fn from(dim: Dim32) -> Self {
        Self {
            base: dim.0,
            stretch: Flex::Fixed(0),
            shrink: Flex::Fixed(0),
        }
    }
}
impl AddAssign for Margin {
    fn add_assign(&mut self, other: Self) {
        self.base += other.base;
        self.stretch = self.stretch + other.stretch;
        self.shrink = self.shrink + other.shrink;
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct VecSet<K: PartialEq> {
    pub inner: Vec<K>,
}
impl<K: PartialEq> Default for VecSet<K> {
    #[inline]
    fn default() -> Self {
        Self { inner: Vec::new() }
    }
}
impl<K: PartialEq> VecSet<K> {
    #[inline]
    pub fn contains(&self, key: &K) -> bool {
        self.inner.contains(key)
    }
    #[inline]
    pub fn insert(&mut self, key: K) {
        if !self.inner.contains(&key) {
            self.inner.push(key);
        }
    }
}
impl<K: PartialEq> IntoIterator for VecSet<K> {
    type Item = K;
    type IntoIter = std::vec::IntoIter<K>;
    fn into_iter(self) -> Self::IntoIter {
        self.inner.into_iter()
    }
}
impl<K: PartialEq> FromIterator<K> for VecSet<K> {
    fn from_iter<T: IntoIterator<Item = K>>(iter: T) -> Self {
        let mut set = VecSet::default();
        for item in iter {
            set.insert(item);
        }
        set
    }
}

#[derive(Clone)]
pub struct VecMap<K, V> {
    pub inner: Vec<(K, V)>,
}
impl<K: Debug, V: Debug> Debug for VecMap<K, V> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_map()
            .entries(self.inner.iter().map(|(k, v)| (k, v)))
            .finish()
    }
}
impl<K, V> Default for VecMap<K, V> {
    fn default() -> Self {
        Self { inner: Vec::new() }
    }
}
impl<K: PartialEq, V> VecMap<K, V> {
    pub fn get<E: ?Sized>(&self, key: &E) -> Option<&V>
    where
        for<'a> &'a E: PartialEq<&'a K>,
    {
        self.inner.iter().find(|(k, _)| key == k).map(|(_, v)| v)
    }
    pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
        self.inner
            .iter_mut()
            .find(|(k, _)| k == key)
            .map(|(_, v)| v)
    }
    pub fn insert(&mut self, key: K, value: V) {
        match self.inner.iter_mut().find(|(k, _)| k == &key) {
            Some((_, v)) => *v = value,
            None => self.inner.push((key, value)),
        };
    }
    pub fn get_or_insert_mut(&mut self, key: K, value: impl FnOnce() -> V) -> &mut V {
        if let Some((i, (_, v))) = self.inner.iter().enumerate().find(|(_, (k, _))| k == &key) {
            return &mut self.inner.get_mut(i).unwrap().1;
        };
        let value = value();
        self.inner.push((key, value));
        &mut self.inner.last_mut().unwrap().1
    }
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }
    pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
        self.inner.iter().map(|(k, v)| (k, v))
    }
    pub fn contains_key<E: ?Sized>(&self, key: &E) -> bool
    where
        for<'a> &'a E: PartialEq<&'a K>,
    {
        self.inner.iter().any(|(k, _)| key == k)
    }
}
impl<K, V> IntoIterator for VecMap<K, V> {
    type Item = (K, V);
    type IntoIter = std::vec::IntoIter<Self::Item>;
    fn into_iter(self) -> Self::IntoIter {
        self.inner.into_iter()
    }
}
impl<'a, 'b> Into<VecMap<Cow<'a, str>, Cow<'b, str>>> for VecMap<String, String> {
    fn into(self) -> VecMap<Cow<'a, str>, Cow<'b, str>> {
        VecMap {
            inner: self
                .inner
                .into_iter()
                .map(|(k, v)| (Cow::Owned(k), Cow::Owned(v)))
                .collect(),
        }
    }
}