zen-types 0.55.1

Zen Core Types
Documentation
mod conv;
mod util;

use crate::variable::RcCell;
use ahash::HashMap;
pub use ahash::HashMapExt as VariableMapExt;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Write};
use std::hash::{Hash, Hasher};
use std::rc::Rc;

#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub enum VariableType {
    Any,
    Null,
    Bool,
    String,
    Number,
    Date,
    Interval,
    Array(Rc<VariableType>),
    Object(RcCell<HashMap<Rc<str>, VariableType>>),

    Const(Rc<str>),
    Enum(Option<Rc<str>>, Vec<Rc<str>>),
}

impl VariableType {
    pub fn array(self) -> Self {
        Self::Array(Rc::new(self))
    }
}

impl Default for VariableType {
    fn default() -> Self {
        VariableType::Null
    }
}

impl Display for VariableType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            VariableType::Any => write!(f, "any"),
            VariableType::Null => write!(f, "null"),
            VariableType::Bool => write!(f, "bool"),
            VariableType::String => write!(f, "string"),
            VariableType::Number => write!(f, "number"),
            VariableType::Date => write!(f, "date"),
            VariableType::Interval => write!(f, "interval"),
            VariableType::Const(c) => write!(f, "\"{c}\""),
            VariableType::Enum(name, e) => {
                if let Some(name) = name {
                    return name.fmt(f);
                }

                let mut first = true;
                for s in e.iter() {
                    if !first {
                        f.write_str(" | ")?;
                    }

                    f.write_char('"')?;
                    f.write_str(s)?;
                    f.write_char('"')?;
                    first = false;
                }

                Ok(())
            }
            VariableType::Array(v) => write!(f, "{v}[]"),
            VariableType::Object(_) => write!(f, "object"),
        }
    }
}

impl Hash for VariableType {
    fn hash<H: Hasher>(&self, state: &mut H) {
        match &self {
            VariableType::Any => 0.hash(state),
            VariableType::Null => 1.hash(state),
            VariableType::Bool => 2.hash(state),
            VariableType::String => 3.hash(state),
            VariableType::Number => 4.hash(state),
            VariableType::Date => 5.hash(state),
            VariableType::Interval => 6.hash(state),
            VariableType::Const(c) => {
                7.hash(state);
                c.hash(state)
            }
            VariableType::Enum(name, e) => {
                8.hash(state);
                name.hash(state);
                e.hash(state)
            }
            VariableType::Array(arr) => {
                9.hash(state);
                arr.hash(state)
            }
            VariableType::Object(obj) => {
                10.hash(state);

                let obj = obj.borrow();
                let mut pairs: Vec<_> = obj.iter().collect();
                pairs.sort_by_key(|i| i.0);

                Hash::hash(&pairs, state);
            }
        }
    }
}