105 lines
2.2 KiB
Rust
105 lines
2.2 KiB
Rust
use std::{cell::RefCell, collections::HashMap, fmt::Debug, hash::Hash, rc::Rc};
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
pub enum ValueInner {
|
|
Boolean(bool),
|
|
Number(i64),
|
|
String(String),
|
|
Table(Table),
|
|
Function(Function),
|
|
}
|
|
|
|
macro_rules! impl_from {
|
|
($as: ident, $from: ty) => {
|
|
impl From<$from> for ValueInner {
|
|
fn from(value: $from) -> Self {
|
|
Self::$as(value.into())
|
|
}
|
|
}
|
|
};
|
|
(try $as: ident, $from: ty) => {
|
|
impl TryFrom<$from> for ValueInner {
|
|
type Error = ::std::num::TryFromIntError;
|
|
fn try_from(value: $from) -> Result<Self, Self::Error> {
|
|
Ok(Self::$as(value.try_into()?))
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
impl_from!(Boolean, bool);
|
|
impl_from!(try Number, isize);
|
|
impl_from!(try Number, usize);
|
|
impl_from!(try Number, i64);
|
|
impl_from!(try Number, u64);
|
|
impl_from!(Number, u32);
|
|
impl_from!(Number, i32);
|
|
impl_from!(String, String);
|
|
impl_from!(String, &str);
|
|
impl_from!(Table, Table);
|
|
|
|
pub type Value = Option<ValueInner>;
|
|
|
|
#[derive(Debug, Clone, Default)]
|
|
struct TableInner {
|
|
content: HashMap<ValueInner, ValueInner>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Default)]
|
|
pub struct Table(Rc<RefCell<TableInner>>);
|
|
|
|
impl PartialEq for Table {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
std::ptr::eq(self.0.as_ptr(), other.0.as_ptr())
|
|
}
|
|
}
|
|
|
|
impl Eq for Table {}
|
|
|
|
impl Hash for Table {
|
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
std::ptr::hash(self.0.as_ptr(), state)
|
|
}
|
|
}
|
|
|
|
impl Table {
|
|
pub fn get(&self, key: ValueInner) -> Value {
|
|
self.0.borrow().content.get(&key).cloned()
|
|
}
|
|
|
|
pub fn set(&self, key: ValueInner, value: Value) {
|
|
let mut this = self.0.borrow_mut();
|
|
if let Some(value) = value {
|
|
this.content.insert(key, value);
|
|
} else {
|
|
this.content.remove(&key);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct Function {
|
|
name: &'static str,
|
|
inner: Rc<dyn Fn(&[Value]) -> Value>,
|
|
}
|
|
|
|
impl Debug for Function {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "<function {}>", self.name)
|
|
}
|
|
}
|
|
|
|
impl PartialEq for Function {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
std::ptr::eq(self.inner.as_ref(), other.inner.as_ref())
|
|
}
|
|
}
|
|
|
|
impl Eq for Function {}
|
|
|
|
impl Hash for Function {
|
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
std::ptr::hash(self.inner.as_ref(), state)
|
|
}
|
|
}
|