Skip to main content

fre_rs/
function.rs

1use super::*;
2
3
4pub type Initializer = fn () -> Option<Box<dyn Any>>;
5pub type Finalizer = fn (ext_data: Option<Box<dyn Any>>);
6pub type ContextInitializer = fn (frt: &FlashRuntime) -> FunctionSet;
7pub type ContextFinalizer = fn (frt: &FlashRuntime);
8pub type Function <'a> = fn (frt: &FlashRuntime<'a>, func_data: Option<&mut dyn Any>, args: &[Object<'a>]) -> Object<'a>;
9
10
11/// **In typical usage of this crate, instances of this type should not be constructed directly.**
12/// 
13/// The [`crate::function!`] macro should be used to construct this type, as it provides a safer abstraction.
14#[derive(Debug)]
15pub struct FunctionDefinition {
16    raw_name: UCStr,
17    raw_func: FREFunction,
18}
19impl FunctionDefinition {
20    pub fn raw_name(&self) -> &UCStr {&self.raw_name}
21    pub fn raw_func(&self) -> FREFunction {self.raw_func}
22    pub const fn new (raw_name: UCStr, raw_func: FREFunction) -> Self {
23        Self { raw_name, raw_func }
24    }
25}
26
27
28/// A collection of functions associated with a specific context type.
29///
30/// This type is used to construct and register a set of functions for a [`Context`].
31/// Once registered, these functions are referred to as *methods* within this crate,
32/// and can be invoked from ActionScript via `ExtensionContext.call`.
33#[derive(Debug)]
34pub struct FunctionSet {
35    list: Vec<FRENamedFunction>,
36    map: HashMap<UCStr, usize>,
37}
38impl FunctionSet {
39    pub fn new () -> Self {
40        Self {
41            list: Vec::new(),
42            map: HashMap::new(),
43        }
44    }
45    pub fn with_capacity (capacity: usize) -> Self{
46        Self {
47            list: Vec::with_capacity(capacity),
48            map: HashMap::with_capacity(capacity),
49        }
50    }
51
52    /// Adds a named function entry to the internal registry.
53    ///
54    /// # Panics
55    ///
56    /// Panics if a function with the same `name` has already been added.
57    ///
58    /// Callers must ensure that each `name` is unique within this registry.
59    pub fn add (
60        &mut self,
61        name: Option<UCStr>,
62        func_data: Option<impl Data>,
63        func: &FunctionDefinition,
64    ) {
65        let name = name.unwrap_or(func.raw_name.clone());
66        let index = self.list.len();
67        self.list.push(FRENamedFunction {
68            name: name.as_ptr(),
69            functionData: if let Some(func_data) = func_data {func_data.into_raw().as_ptr()} else {FREData::default()},
70            function: func.raw_func,
71        });
72        let r = self.map.insert(name, index);
73        assert!(r.is_none());
74    }
75}
76impl Drop for FunctionSet {
77    fn drop(&mut self) {
78        self.list.iter()
79            .map(|i| i.functionData)
80            .for_each(|d| {
81                if let Some(d) = NonNullFREData::new(d) {
82                    unsafe {crate::data::drop_from(d)};
83                }
84            });
85    }
86}
87
88
89#[derive(Debug)]
90pub(super) struct MethodSet {
91    registry: Box<[FRENamedFunction]>,
92    dictionary: HashMap<UCStr, usize>,
93}
94impl MethodSet {
95    /// ## Borrow
96    pub(super) fn get(&self, name: &str) -> Option<(FREFunction, FREData)> {
97        self.dictionary.get(name)
98            .map(|index| {
99                let i = &(self.registry[*index]);
100                (i.function, i.functionData)
101            })
102    }
103}
104impl Drop for MethodSet {
105    fn drop(&mut self) {
106        self.registry.iter()
107            .map(|i| i.functionData)
108            .for_each(|d| {
109                if let Some(d) = NonNullFREData::new(d) {
110                    unsafe {crate::data::drop_from(d)};
111                }
112            });
113    }
114}
115impl From<FunctionSet> for MethodSet {
116    fn from(mut value: FunctionSet) -> Self {
117        let registry = std::mem::take(&mut value.list).into_boxed_slice();
118        let dictionary = std::mem::take(&mut value.map);
119        Self { registry, dictionary }
120    }
121}
122impl AsRef<[FRENamedFunction]> for MethodSet {
123    fn as_ref(&self) -> &[FRENamedFunction] {self.registry.as_ref()}
124}