use crate::func::SendSync;
use crate::packages::string_basic::{FUNC_TO_DEBUG, FUNC_TO_STRING};
use crate::{types::dynamic::Variant, Engine, Identifier, RegisterNativeFunction};
use std::marker::PhantomData;
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
use crate::func::register::Mut;
pub trait CustomType: Variant + Clone {
fn build(builder: TypeBuilder<Self>);
}
impl Engine {
#[inline]
pub fn build_type<T: CustomType>(&mut self) -> &mut Self {
T::build(TypeBuilder::new(self));
self
}
}
pub struct TypeBuilder<'a, T: Variant + Clone> {
engine: &'a mut Engine,
name: Option<&'static str>,
_marker: PhantomData<T>,
}
impl<'a, T: Variant + Clone> TypeBuilder<'a, T> {
#[inline(always)]
fn new(engine: &'a mut Engine) -> Self {
Self {
engine,
name: None,
_marker: PhantomData,
}
}
}
impl<'a, T: Variant + Clone> TypeBuilder<'a, T> {
#[inline(always)]
pub fn with_name(&mut self, name: &'static str) -> &mut Self {
self.name = Some(name);
self
}
#[inline(always)]
pub fn on_print(
&mut self,
on_print: impl Fn(&mut T) -> String + SendSync + 'static,
) -> &mut Self {
self.engine.register_fn(FUNC_TO_STRING, on_print);
self
}
#[inline(always)]
pub fn on_debug(
&mut self,
on_print: impl Fn(&mut T) -> String + SendSync + 'static,
) -> &mut Self {
self.engine.register_fn(FUNC_TO_DEBUG, on_print);
self
}
#[inline(always)]
pub fn with_fn<A: 'static, const N: usize, const C: bool, R: Variant + Clone, const L: bool>(
&mut self,
name: impl AsRef<str> + Into<Identifier>,
method: impl RegisterNativeFunction<A, N, C, R, L> + SendSync + 'static,
) -> &mut Self {
self.engine.register_fn(name, method);
self
}
}
impl<'a, T> TypeBuilder<'a, T>
where
T: Variant + Clone + IntoIterator,
<T as IntoIterator>::Item: Variant + Clone,
{
#[inline(always)]
pub fn is_iterable(&mut self) -> &mut Self {
self.engine.register_iterator::<T>();
self
}
}
#[cfg(not(feature = "no_object"))]
impl<'a, T: Variant + Clone> TypeBuilder<'a, T> {
#[inline(always)]
pub fn with_get<const C: bool, V: Variant + Clone, const L: bool>(
&mut self,
name: impl AsRef<str>,
get_fn: impl RegisterNativeFunction<(Mut<T>,), 1, C, V, L> + SendSync + 'static,
) -> &mut Self {
self.engine.register_get(name, get_fn);
self
}
#[inline(always)]
pub fn with_set<const C: bool, V: Variant + Clone, const L: bool>(
&mut self,
name: impl AsRef<str>,
set_fn: impl RegisterNativeFunction<(Mut<T>, V), 2, C, (), L> + SendSync + 'static,
) -> &mut Self {
self.engine.register_set(name, set_fn);
self
}
#[inline(always)]
pub fn with_get_set<
const C1: bool,
const C2: bool,
V: Variant + Clone,
const L1: bool,
const L2: bool,
>(
&mut self,
name: impl AsRef<str>,
get_fn: impl RegisterNativeFunction<(Mut<T>,), 1, C1, V, L1> + SendSync + 'static,
set_fn: impl RegisterNativeFunction<(Mut<T>, V), 2, C2, (), L2> + SendSync + 'static,
) -> &mut Self {
self.engine.register_get_set(name, get_fn, set_fn);
self
}
}
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
impl<'a, T: Variant + Clone> TypeBuilder<'a, T> {
#[inline(always)]
pub fn with_indexer_get<
X: Variant + Clone,
const C: bool,
V: Variant + Clone,
const L: bool,
>(
&mut self,
get_fn: impl RegisterNativeFunction<(Mut<T>, X), 2, C, V, L> + SendSync + 'static,
) -> &mut Self {
self.engine.register_indexer_get(get_fn);
self
}
#[inline(always)]
pub fn with_indexer_set<
X: Variant + Clone,
const C: bool,
V: Variant + Clone,
const L: bool,
>(
&mut self,
set_fn: impl RegisterNativeFunction<(Mut<T>, X, V), 3, C, (), L> + SendSync + 'static,
) -> &mut Self {
self.engine.register_indexer_set(set_fn);
self
}
#[inline(always)]
pub fn with_indexer_get_set<
X: Variant + Clone,
const C1: bool,
const C2: bool,
V: Variant + Clone,
const L1: bool,
const L2: bool,
>(
&mut self,
get_fn: impl RegisterNativeFunction<(Mut<T>, X), 2, C1, V, L1> + SendSync + 'static,
set_fn: impl RegisterNativeFunction<(Mut<T>, X, V), 3, C2, (), L2> + SendSync + 'static,
) -> &mut Self {
self.engine.register_indexer_get_set(get_fn, set_fn);
self
}
}
impl<'a, T: Variant + Clone> Drop for TypeBuilder<'a, T> {
#[inline]
fn drop(&mut self) {
match self.name {
Some(name) => self.engine.register_type_with_name::<T>(name),
None => self.engine.register_type::<T>(),
};
}
}