minilua/src/types.rs
2025-04-19 10:42:30 +03:00

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)
}
}