use super::*;
pub type Initializer = fn () -> Option<Box<dyn Any>>;
pub type Finalizer = fn (ext_data: Option<Box<dyn Any>>);
pub type ContextInitializer = fn (ctx: &mut CurrentContext) -> (Option<Box<dyn Any>>, FunctionSet);
pub type ContextFinalizer = fn (ctx: &mut CurrentContext);
pub type Function <'a> = fn (ctx: &mut CurrentContext<'a>, func_data: Option<&mut dyn Any>, args: &[Object<'a>]) -> Object<'a>;
#[derive(Debug)]
pub struct FunctionImplementation {
name: UCStr,
func: FREFunction,
}
impl FunctionImplementation {
pub fn name(&self) -> &UCStr {&self.name}
pub fn func(&self) -> FREFunction {self.func}
pub(crate) const fn new (name: UCStr, func: FREFunction) -> Self {Self { name, func }}
}
#[derive(Debug)]
pub struct FunctionSet {
list: Vec<FRENamedFunction>,
map: HashMap<UCStr, usize>,
}
impl FunctionSet {
pub fn new () -> Self {
Self {
list: Vec::new(),
map: HashMap::new(),
}
}
pub fn with_capacity (capacity: usize) -> Self{
Self {
list: Vec::with_capacity(capacity),
map: HashMap::with_capacity(capacity),
}
}
pub fn add (
&mut self,
name: Option<UCStr>,
func_data: Option<Box<dyn Any>>,
func_impl: &'static FunctionImplementation,
) {
let name = name.unwrap_or(func_impl.name.clone());
let index = self.list.len();
self.list.push(FRENamedFunction {
name: name.as_ptr(),
functionData: if let Some(func_data) = func_data {crate::data::into_raw(func_data).as_ptr()} else {FREData::default()},
function: func_impl.func,
});
let r = self.map.insert(name, index);
assert!(r.is_none(), "Method name conflict.");
}
}
impl Drop for FunctionSet {
fn drop(&mut self) {
self.list.iter()
.map(|i| i.functionData)
.for_each(|d| {
if let Some(d) = NonNullFREData::new(d) {
unsafe {crate::data::drop_from(d)};
}
});
}
}
#[derive(Debug)]
pub(super) struct MethodSet {
registry: Box<[FRENamedFunction]>,
dictionary: HashMap<UCStr, usize>,
}
impl MethodSet {
pub(super) fn get(&self, name: &str) -> Option<(FREFunction, FREData)> {
self.dictionary.get(name)
.map(|index| {
let i = &(self.registry[*index]);
(i.function, i.functionData)
})
}
}
impl Drop for MethodSet {
fn drop(&mut self) {
self.registry.iter()
.map(|i| i.functionData)
.for_each(|d| {
if let Some(d) = NonNullFREData::new(d) {
unsafe {crate::data::drop_from(d)};
}
});
}
}
impl From<FunctionSet> for MethodSet {
fn from(mut value: FunctionSet) -> Self {
let registry = std::mem::take(&mut value.list).into_boxed_slice();
let dictionary = std::mem::take(&mut value.map);
Self { registry, dictionary }
}
}
impl AsRef<[FRENamedFunction]> for MethodSet {
fn as_ref(&self) -> &[FRENamedFunction] {self.registry.as_ref()}
}
pub fn trace <T: ToUcstrLossy + Sized> (message: T) {crate::context::stack::current_context().trace(message);}