use crate::{
builtins::function::NativeFunction,
object::{ConstructorBuilder, GcObject, NativeObject, ObjectData},
property::{Attribute, PropertyKey},
Context, Result, Value,
};
pub trait Class: NativeObject + Sized {
const NAME: &'static str;
const LENGTH: usize = 0;
const ATTRIBUTE: Attribute = Attribute::all();
fn constructor(this: &Value, args: &[Value], context: &mut Context) -> Result<Self>;
fn init(class: &mut ClassBuilder<'_>) -> Result<()>;
}
pub trait ClassConstructor: Class {
fn raw_constructor(this: &Value, args: &[Value], context: &mut Context) -> Result<Value>
where
Self: Sized;
}
impl<T: Class> ClassConstructor for T {
fn raw_constructor(this: &Value, args: &[Value], context: &mut Context) -> Result<Value>
where
Self: Sized,
{
let object_instance = Self::constructor(this, args, context)?;
this.set_data(ObjectData::NativeObject(Box::new(object_instance)));
Ok(this.clone())
}
}
#[derive(Debug)]
pub struct ClassBuilder<'context> {
builder: ConstructorBuilder<'context>,
}
impl<'context> ClassBuilder<'context> {
#[inline]
pub(crate) fn new<T>(context: &'context mut Context) -> Self
where
T: ClassConstructor,
{
let mut builder = ConstructorBuilder::new(context, T::raw_constructor);
builder.name(T::NAME);
builder.length(T::LENGTH);
Self { builder }
}
#[inline]
pub(crate) fn build(mut self) -> GcObject {
self.builder.build()
}
#[inline]
pub fn method<N>(&mut self, name: N, length: usize, function: NativeFunction) -> &mut Self
where
N: AsRef<str>,
{
self.builder.method(function, name.as_ref(), length);
self
}
#[inline]
pub fn static_method<N>(
&mut self,
name: N,
length: usize,
function: NativeFunction,
) -> &mut Self
where
N: AsRef<str>,
{
self.builder.static_method(function, name.as_ref(), length);
self
}
#[inline]
pub fn property<K, V>(&mut self, key: K, value: V, attribute: Attribute) -> &mut Self
where
K: Into<PropertyKey>,
V: Into<Value>,
{
self.builder.property(key, value, attribute);
self
}
#[inline]
pub fn static_property<K, V>(&mut self, key: K, value: V, attribute: Attribute) -> &mut Self
where
K: Into<PropertyKey>,
V: Into<Value>,
{
self.builder.static_property(key, value, attribute);
self
}
#[inline]
pub fn context(&mut self) -> &'_ mut Context {
self.builder.context()
}
}