1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use crate::plugin::*;
use crate::{def_package, FnPtr, ImmutableString, NativeCallContext};
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
def_package!(crate:BasicFnPackage:"Basic Fn functions.", lib, {
combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions);
});
#[export_module]
mod fn_ptr_functions {
#[rhai_fn(name = "name", get = "name", pure)]
pub fn name(f: &mut FnPtr) -> ImmutableString {
f.get_fn_name().as_str().into()
}
#[cfg(not(feature = "no_function"))]
pub mod functions {
#[rhai_fn(name = "is_anonymous", get = "is_anonymous", pure)]
pub fn is_anonymous(f: &mut FnPtr) -> bool {
f.is_anonymous()
}
}
#[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "no_index"))]
#[cfg(not(feature = "no_object"))]
pub mod functions_and_maps {
pub fn get_fn_metadata_list(ctx: NativeCallContext) -> crate::Array {
collect_fn_metadata(ctx)
}
}
}
#[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "no_index"))]
#[cfg(not(feature = "no_object"))]
fn collect_fn_metadata(ctx: NativeCallContext) -> crate::Array {
use crate::{ast::ScriptFnDef, Array, Identifier, Map};
use std::collections::BTreeSet;
fn make_metadata(
dict: &BTreeSet<Identifier>,
namespace: Option<Identifier>,
f: &ScriptFnDef,
) -> Map {
const DICT: &str = "never fails because the dictionary is pre-filled with all the keys";
let mut map = Map::new();
if let Some(ns) = namespace {
map.insert(dict.get("namespace").expect(DICT).clone().into(), ns.into());
}
map.insert(
dict.get("name").expect(DICT).clone().into(),
f.name.clone().into(),
);
map.insert(
dict.get("access").expect(DICT).clone().into(),
match f.access {
FnAccess::Public => dict.get("public").expect(DICT).clone(),
FnAccess::Private => dict.get("private").expect(DICT).clone(),
}
.into(),
);
map.insert(
dict.get("is_anonymous").expect(DICT).clone().into(),
f.name.starts_with(crate::engine::FN_ANONYMOUS).into(),
);
map.insert(
dict.get("params").expect(DICT).clone().into(),
f.params
.iter()
.cloned()
.map(Into::<Dynamic>::into)
.collect::<Array>()
.into(),
);
map.into()
}
let dict: BTreeSet<Identifier> = [
"namespace",
"name",
"access",
"public",
"private",
"is_anonymous",
"params",
]
.iter()
.map(|&s| s.into())
.collect();
let mut list: Array = Default::default();
ctx.iter_namespaces()
.flat_map(|m| m.iter_script_fn())
.for_each(|(_, _, _, _, f)| list.push(make_metadata(&dict, None, f).into()));
#[cfg(not(feature = "no_module"))]
{
fn scan_module(
list: &mut Array,
dict: &BTreeSet<Identifier>,
namespace: Identifier,
module: &Module,
) {
module.iter_script_fn().for_each(|(_, _, _, _, f)| {
list.push(make_metadata(dict, Some(namespace.clone()), f).into())
});
module.iter_sub_modules().for_each(|(ns, m)| {
let ns = format!("{}::{}", namespace, ns);
scan_module(list, dict, ns.into(), m.as_ref())
});
}
ctx.iter_imports_raw()
.for_each(|(ns, m)| scan_module(&mut list, &dict, ns.clone(), m.as_ref()));
}
list
}