xee-interpreter 0.2.0

Interpreter for XPath and XSLT
Documentation
use std::rc::Rc;

use crate::{context, stack};

use super::array::Array;
use super::map::Map;

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct InlineFunctionId(pub(crate) usize);

impl InlineFunctionId {
    pub fn new(id: usize) -> Self {
        InlineFunctionId(id)
    }

    pub fn get(&self) -> usize {
        self.0
    }

    pub fn as_u16(&self) -> u16 {
        self.0 as u16
    }
}

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct StaticFunctionId(pub(crate) usize);

impl StaticFunctionId {
    pub fn as_u16(&self) -> u16 {
        self.0 as u16
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum Function {
    Static(Rc<StaticFunctionData>),
    Inline(Rc<InlineFunctionData>),
    Map(Map),
    Array(Array),
}

#[cfg(target_arch = "x86_64")]
static_assertions::assert_eq_size!(Function, [u8; 16]);

#[derive(Debug, PartialEq)]
pub struct StaticFunctionData {
    pub(crate) id: StaticFunctionId,
    pub(crate) closure_vars: Box<[stack::Value]>,
}

impl From<StaticFunctionData> for Function {
    fn from(data: StaticFunctionData) -> Self {
        Self::Static(Rc::new(data))
    }
}

impl StaticFunctionData {
    pub(crate) fn new(id: StaticFunctionId, closure_vars: Vec<stack::Value>) -> Self {
        StaticFunctionData {
            id,
            closure_vars: closure_vars.into(),
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct InlineFunctionData {
    pub(crate) id: InlineFunctionId,
    pub(crate) closure_vars: Box<[stack::Value]>,
}

impl From<InlineFunctionData> for Function {
    fn from(data: InlineFunctionData) -> Self {
        Self::Inline(Rc::new(data))
    }
}

impl InlineFunctionData {
    pub(crate) fn new(id: InlineFunctionId, closure_vars: Vec<stack::Value>) -> Self {
        InlineFunctionData {
            id,
            closure_vars: closure_vars.into(),
        }
    }
}

impl Function {
    pub(crate) fn closure_vars(&self) -> &[stack::Value] {
        match self {
            Self::Static(data) => &data.closure_vars,
            Self::Inline(data) => &data.closure_vars,
            _ => unreachable!(),
        }
    }

    pub fn display_representation(
        &self,
        xot: &xot::Xot,
        context: &context::DynamicContext,
    ) -> String {
        match self {
            Self::Static(data) => {
                let function = context.static_function_by_id(data.id);
                function.display_representation()
            }
            Self::Inline(data) => {
                let function = context.inline_function_by_id(data.id);
                function.display_representation()
            }
            Self::Map(map) => map.display_representation(xot, context),
            Self::Array(array) => array.display_representation(xot, context),
        }
    }
}