use std::any::{Any, TypeId};
use std::fmt;
use std::ops::Range;
use std::sync::Arc;
use crate::error::{Error, ErrorKind};
use crate::value::{intern, Value};
use crate::vm::State;
pub trait Object: fmt::Display + fmt::Debug + Any + Sync + Send {
fn kind(&self) -> ObjectKind<'_> {
ObjectKind::Plain
}
fn call_method(&self, state: &State, name: &str, args: &[Value]) -> Result<Value, Error> {
let _state = state;
let _args = args;
Err(Error::new(
ErrorKind::UnknownMethod,
format!("object has no method named {name}"),
))
}
fn call(&self, state: &State, args: &[Value]) -> Result<Value, Error> {
let _state = state;
let _args = args;
Err(Error::new(
ErrorKind::InvalidOperation,
"tried to call non callable object",
))
}
}
impl dyn Object {
pub fn downcast_ref<T: Object>(&self) -> Option<&T> {
self.is::<T>().then(|| {
unsafe { &*(self as *const dyn Object as *const T) }
})
}
pub fn is<T: Object>(&self) -> bool {
(*self).type_id() == TypeId::of::<T>()
}
}
impl<T: Object> Object for Arc<T> {
#[inline]
fn kind(&self) -> ObjectKind<'_> {
T::kind(self)
}
#[inline]
fn call_method(&self, state: &State, name: &str, args: &[Value]) -> Result<Value, Error> {
T::call_method(self, state, name, args)
}
#[inline]
fn call(&self, state: &State, args: &[Value]) -> Result<Value, Error> {
T::call(self, state, args)
}
}
#[non_exhaustive]
pub enum ObjectKind<'a> {
Plain,
Seq(&'a dyn SeqObject),
Struct(&'a dyn StructObject),
}
pub trait SeqObject: Send + Sync {
fn get_item(&self, idx: usize) -> Option<Value>;
fn item_count(&self) -> usize;
}
impl dyn SeqObject + '_ {
pub fn iter(&self) -> SeqObjectIter<'_> {
SeqObjectIter {
seq: self,
range: 0..self.item_count(),
}
}
}
impl<T: SeqObject> SeqObject for Arc<T> {
#[inline]
fn get_item(&self, idx: usize) -> Option<Value> {
T::get_item(self, idx)
}
#[inline]
fn item_count(&self) -> usize {
T::item_count(self)
}
}
impl<'a, T: SeqObject + ?Sized> SeqObject for &'a T {
#[inline]
fn get_item(&self, idx: usize) -> Option<Value> {
T::get_item(self, idx)
}
#[inline]
fn item_count(&self) -> usize {
T::item_count(self)
}
}
impl<T: Into<Value> + Send + Sync + Clone> SeqObject for [T] {
#[inline(always)]
fn get_item(&self, idx: usize) -> Option<Value> {
self.get(idx).cloned().map(Into::into)
}
#[inline(always)]
fn item_count(&self) -> usize {
self.len()
}
}
impl<T: Into<Value> + Send + Sync + Clone> SeqObject for Vec<T> {
#[inline(always)]
fn get_item(&self, idx: usize) -> Option<Value> {
self.get(idx).cloned().map(Into::into)
}
#[inline(always)]
fn item_count(&self) -> usize {
self.len()
}
}
pub struct SeqObjectIter<'a> {
seq: &'a dyn SeqObject,
range: Range<usize>,
}
impl<'a> Iterator for SeqObjectIter<'a> {
type Item = Value;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
self.range
.next()
.map(|idx| self.seq.get_item(idx).unwrap_or(Value::UNDEFINED))
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
self.range.size_hint()
}
}
impl<'a> DoubleEndedIterator for SeqObjectIter<'a> {
#[inline(always)]
fn next_back(&mut self) -> Option<Self::Item> {
self.range
.next_back()
.map(|idx| self.seq.get_item(idx).unwrap_or(Value::UNDEFINED))
}
}
impl<'a> ExactSizeIterator for SeqObjectIter<'a> {}
pub trait StructObject: Send + Sync {
fn get_field(&self, name: &str) -> Option<Value>;
fn static_fields(&self) -> Option<&'static [&'static str]> {
None
}
fn fields(&self) -> Vec<Arc<String>> {
self.static_fields()
.into_iter()
.flat_map(|fields| fields.iter().copied().map(intern))
.collect()
}
fn field_count(&self) -> usize {
if let Some(fields) = self.static_fields() {
fields.len()
} else {
self.fields().len()
}
}
}
impl<T: StructObject> StructObject for Arc<T> {
#[inline]
fn get_field(&self, name: &str) -> Option<Value> {
T::get_field(self, name)
}
#[inline]
fn static_fields(&self) -> Option<&'static [&'static str]> {
T::static_fields(self)
}
#[inline]
fn fields(&self) -> Vec<Arc<String>> {
T::fields(self)
}
#[inline]
fn field_count(&self) -> usize {
T::field_count(self)
}
}
impl<'a, T: StructObject + ?Sized> StructObject for &'a T {
#[inline]
fn get_field(&self, name: &str) -> Option<Value> {
T::get_field(self, name)
}
#[inline]
fn static_fields(&self) -> Option<&'static [&'static str]> {
T::static_fields(self)
}
#[inline]
fn fields(&self) -> Vec<Arc<String>> {
T::fields(self)
}
#[inline]
fn field_count(&self) -> usize {
T::field_count(self)
}
}
#[repr(transparent)]
pub struct SimpleSeqObject<T>(pub T);
impl<T: SeqObject + 'static> fmt::Display for SimpleSeqObject<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
ok!(write!(f, "["));
for (idx, val) in (&self.0 as &dyn SeqObject).iter().enumerate() {
if idx > 0 {
ok!(write!(f, ", "));
}
ok!(write!(f, "{val:?}"));
}
write!(f, "]")
}
}
impl<T: SeqObject + 'static> fmt::Debug for SimpleSeqObject<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list()
.entries((&self.0 as &dyn SeqObject).iter())
.finish()
}
}
impl<T: SeqObject + 'static> Object for SimpleSeqObject<T> {
fn kind(&self) -> ObjectKind<'_> {
ObjectKind::Seq(&self.0)
}
}
#[repr(transparent)]
pub struct SimpleStructObject<T>(pub T);
impl<T: StructObject + 'static> fmt::Display for SimpleStructObject<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
ok!(write!(f, "{{"));
for (idx, field) in self.0.fields().iter().enumerate() {
if idx > 0 {
ok!(write!(f, ", "));
}
let val = self.0.get_field(field).unwrap_or(Value::UNDEFINED);
ok!(write!(f, "{field:?}: {val:?}"));
}
write!(f, "}}")
}
}
impl<T: StructObject + 'static> fmt::Debug for SimpleStructObject<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut m = f.debug_map();
for field in self.0.fields() {
let value = self.0.get_field(&field).unwrap_or(Value::UNDEFINED);
m.entry(&field, &value);
}
m.finish()
}
}
impl<T: StructObject + 'static> Object for SimpleStructObject<T> {
fn kind(&self) -> ObjectKind<'_> {
ObjectKind::Struct(&self.0)
}
}