1use super::native::{FnAny, FnIterator, FnPlugin, SendSync};
4use crate::ast::{EncapsulatedEnviron, FnAccess};
5use crate::plugin::PluginFunc;
6use crate::Shared;
7use std::fmt;
8#[cfg(feature = "no_std")]
9use std::prelude::v1::*;
10
11#[derive(Clone)]
14#[non_exhaustive]
15pub enum RhaiFunc {
16 Pure {
18 func: Shared<FnAny>,
20 has_context: bool,
22 is_pure: bool,
24 is_volatile: bool,
28 },
29 Method {
32 func: Shared<FnAny>,
34 has_context: bool,
36 is_pure: bool,
38 is_volatile: bool,
42 },
43 Iterator {
45 func: Shared<FnIterator>,
47 },
48 Plugin {
50 func: Shared<FnPlugin>,
52 },
53 #[cfg(not(feature = "no_function"))]
55 Script {
56 fn_def: Shared<crate::ast::ScriptFuncDef>,
58 env: Option<Shared<EncapsulatedEnviron>>,
60 },
61}
62
63impl fmt::Debug for RhaiFunc {
64 #[cold]
65 #[inline(never)]
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 match self {
68 Self::Pure { .. } => f.write_str("NativePureFunction"),
69 Self::Method { .. } => f.write_str("NativeMethod"),
70 Self::Iterator { .. } => f.write_str("NativeIterator"),
71 Self::Plugin { .. } => f.write_str("PluginFunction"),
72
73 #[cfg(not(feature = "no_function"))]
74 Self::Script { fn_def, .. } => fmt::Debug::fmt(fn_def, f),
75 }
76 }
77}
78
79impl fmt::Display for RhaiFunc {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 match self {
82 Self::Pure { .. } => f.write_str("NativePureFunction"),
83 Self::Method { .. } => f.write_str("NativeMethod"),
84 Self::Iterator { .. } => f.write_str("NativeIterator"),
85 Self::Plugin { .. } => f.write_str("PluginFunction"),
86
87 #[cfg(not(feature = "no_function"))]
88 Self::Script { fn_def, .. } => fmt::Display::fmt(fn_def, f),
89 }
90 }
91}
92
93impl RhaiFunc {
94 #[inline]
96 #[must_use]
97 pub fn is_pure(&self) -> bool {
98 match self {
99 Self::Pure { .. } => true,
100 Self::Method { is_pure, .. } => *is_pure,
101 Self::Iterator { .. } => true,
102
103 Self::Plugin { func, .. } => func.is_pure(),
104
105 #[cfg(not(feature = "no_function"))]
106 Self::Script { .. } => false,
107 }
108 }
109 #[inline]
111 #[must_use]
112 pub fn is_method(&self) -> bool {
113 match self {
114 Self::Method { .. } => true,
115 Self::Pure { .. } | Self::Iterator { .. } => false,
116
117 Self::Plugin { func, .. } => func.is_method_call(),
118
119 #[cfg(not(feature = "no_function"))]
120 Self::Script { .. } => false,
121 }
122 }
123 #[inline]
125 #[must_use]
126 pub const fn is_iter(&self) -> bool {
127 match self {
128 Self::Iterator { .. } => true,
129 Self::Pure { .. } | Self::Method { .. } | Self::Plugin { .. } => false,
130
131 #[cfg(not(feature = "no_function"))]
132 Self::Script { .. } => false,
133 }
134 }
135 #[inline]
137 #[must_use]
138 pub const fn is_script(&self) -> bool {
139 #[cfg(feature = "no_function")]
140 return false;
141
142 #[cfg(not(feature = "no_function"))]
143 match self {
144 Self::Script { .. } => true,
145 Self::Pure { .. }
146 | Self::Method { .. }
147 | Self::Iterator { .. }
148 | Self::Plugin { .. } => false,
149 }
150 }
151 #[inline]
153 #[must_use]
154 pub const fn is_plugin_fn(&self) -> bool {
155 match self {
156 Self::Plugin { .. } => true,
157 Self::Pure { .. } | Self::Method { .. } | Self::Iterator { .. } => false,
158
159 #[cfg(not(feature = "no_function"))]
160 Self::Script { .. } => false,
161 }
162 }
163 #[inline]
165 #[must_use]
166 pub const fn is_native(&self) -> bool {
167 #[cfg(feature = "no_function")]
168 return true;
169
170 #[cfg(not(feature = "no_function"))]
171 match self {
172 Self::Pure { .. }
173 | Self::Method { .. }
174 | Self::Plugin { .. }
175 | Self::Iterator { .. } => true,
176 Self::Script { .. } => false,
177 }
178 }
179 #[inline]
181 #[must_use]
182 pub fn has_context(&self) -> bool {
183 match self {
184 Self::Pure { has_context, .. } | Self::Method { has_context, .. } => *has_context,
185 Self::Plugin { func, .. } => func.has_context(),
186 Self::Iterator { .. } => false,
187 #[cfg(not(feature = "no_function"))]
188 Self::Script { .. } => false,
189 }
190 }
191 #[inline]
195 #[must_use]
196 pub fn is_volatile(&self) -> bool {
197 match self {
198 Self::Pure { is_volatile, .. } => *is_volatile,
199 Self::Method { is_volatile, .. } => *is_volatile,
200 Self::Iterator { .. } => true,
201
202 Self::Plugin { func, .. } => func.is_volatile(),
203
204 #[cfg(not(feature = "no_function"))]
206 Self::Script { .. } => true,
207 }
208 }
209 #[inline]
211 #[must_use]
212 pub fn access(&self) -> FnAccess {
213 #[cfg(feature = "no_function")]
214 return FnAccess::Public;
215
216 #[cfg(not(feature = "no_function"))]
217 match self {
218 Self::Plugin { .. }
219 | Self::Pure { .. }
220 | Self::Method { .. }
221 | Self::Iterator { .. } => FnAccess::Public,
222 Self::Script { fn_def, .. } => fn_def.access,
223 }
224 }
225 #[inline]
227 #[must_use]
228 pub fn get_native_fn(&self) -> Option<&Shared<FnAny>> {
229 match self {
230 Self::Pure { func, .. } | Self::Method { func, .. } => Some(func),
231 Self::Iterator { .. } | Self::Plugin { .. } => None,
232
233 #[cfg(not(feature = "no_function"))]
234 Self::Script { .. } => None,
235 }
236 }
237 #[cfg(not(feature = "no_function"))]
241 #[inline]
242 #[must_use]
243 pub const fn get_script_fn_def(&self) -> Option<&Shared<crate::ast::ScriptFuncDef>> {
244 match self {
245 Self::Pure { .. }
246 | Self::Method { .. }
247 | Self::Iterator { .. }
248 | Self::Plugin { .. } => None,
249 Self::Script { fn_def, .. } => Some(fn_def),
250 }
251 }
252 #[inline(always)]
254 #[must_use]
255 pub fn get_encapsulated_environ(&self) -> Option<&EncapsulatedEnviron> {
256 self.get_shared_encapsulated_environ().map(AsRef::as_ref)
257 }
258 #[inline]
260 #[must_use]
261 pub(crate) fn get_shared_encapsulated_environ(&self) -> Option<&Shared<EncapsulatedEnviron>> {
262 match self {
263 Self::Pure { .. }
264 | Self::Method { .. }
265 | Self::Iterator { .. }
266 | Self::Plugin { .. } => None,
267
268 #[cfg(not(feature = "no_function"))]
269 Self::Script { env, .. } => env.as_ref(),
270 }
271 }
272 #[inline]
274 #[must_use]
275 pub fn get_iter_fn(&self) -> Option<&FnIterator> {
276 match self {
277 Self::Iterator { func, .. } => Some(&**func),
278 Self::Pure { .. } | Self::Method { .. } | Self::Plugin { .. } => None,
279
280 #[cfg(not(feature = "no_function"))]
281 Self::Script { .. } => None,
282 }
283 }
284 #[inline]
286 #[must_use]
287 pub fn get_plugin_fn(&self) -> Option<&Shared<FnPlugin>> {
288 match self {
289 Self::Plugin { func, .. } => Some(func),
290 Self::Pure { .. } | Self::Method { .. } | Self::Iterator { .. } => None,
291
292 #[cfg(not(feature = "no_function"))]
293 Self::Script { .. } => None,
294 }
295 }
296}
297
298#[cfg(not(feature = "no_function"))]
299impl From<crate::ast::ScriptFuncDef> for RhaiFunc {
300 #[inline(always)]
301 fn from(fn_def: crate::ast::ScriptFuncDef) -> Self {
302 Self::Script {
303 fn_def: fn_def.into(),
304 env: None,
305 }
306 }
307}
308
309#[cfg(not(feature = "no_function"))]
310impl From<Shared<crate::ast::ScriptFuncDef>> for RhaiFunc {
311 #[inline(always)]
312 fn from(fn_def: Shared<crate::ast::ScriptFuncDef>) -> Self {
313 Self::Script { fn_def, env: None }
314 }
315}
316
317impl<T: PluginFunc + 'static + SendSync> From<T> for RhaiFunc {
318 #[inline(always)]
319 fn from(func: T) -> Self {
320 Self::Plugin {
321 func: Shared::new(func),
322 }
323 }
324}
325
326impl From<Shared<FnPlugin>> for RhaiFunc {
327 #[inline(always)]
328 fn from(func: Shared<FnPlugin>) -> Self {
329 Self::Plugin { func }
330 }
331}