use std::collections::{HashMap, HashSet};
use super::{builtin::Builtin, value::Value};
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[cfg(feature = "serde")]
fn serialize_builtin<S>(builtin: &dyn Builtin, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(builtin.name())
}
#[cfg(feature = "serde")]
fn deserialize_builtin<'de, 'a, D>(deserializer: D) -> Result<&'a dyn Builtin, D::Error>
where
D: Deserializer<'de>,
{
let name = String::deserialize(deserializer)?;
let functions = crate::funcs::all();
functions.get(name.as_str())
.map(|f| &**f)
.ok_or_else(|| serde::de::Error::custom("unknown function"))
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Function {
User(User),
#[cfg_attr(feature = "serde", serde(
serialize_with = "serialize_builtin",
deserialize_with = "deserialize_builtin"
))]
Builtin(&'static dyn Builtin),
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct User {
pub index: usize,
pub captures: HashSet<usize>,
pub environment: HashMap<usize, Value>,
}
impl User {
pub fn new(index: usize, captures: HashSet<usize>) -> Self {
Self { index, captures, environment: HashMap::new() }
}
}
impl PartialEq for Function {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::User(a), Self::User(b)) => a == b,
(Self::Builtin(a), Self::Builtin(b)) => std::ptr::eq(*a, *b),
_ => false,
}
}
}