Skip to main content

ext_php_rs/
flags.rs

1//! Flags and enums used in PHP and the Zend engine.
2
3use bitflags::bitflags;
4
5#[cfg(php81)]
6use crate::ffi::ZEND_ACC_ENUM;
7#[cfg(not(php82))]
8use crate::ffi::ZEND_ACC_REUSE_GET_ITERATOR;
9use crate::ffi::{
10    _IS_BOOL, CONST_DEPRECATED, CONST_NO_FILE_CACHE, CONST_PERSISTENT, E_ALL, E_COMPILE_ERROR,
11    E_COMPILE_WARNING, E_CORE, E_CORE_ERROR, E_CORE_WARNING, E_DEPRECATED, E_ERROR, E_FATAL_ERRORS,
12    E_NOTICE, E_PARSE, E_RECOVERABLE_ERROR, E_STRICT, E_USER_DEPRECATED, E_USER_ERROR,
13    E_USER_NOTICE, E_USER_WARNING, E_WARNING, GC_IMMUTABLE, IS_ARRAY, IS_CALLABLE, IS_CONSTANT_AST,
14    IS_DOUBLE, IS_FALSE, IS_INDIRECT, IS_ITERABLE, IS_LONG, IS_MIXED, IS_NULL, IS_OBJECT, IS_PTR,
15    IS_REFERENCE, IS_RESOURCE, IS_STRING, IS_TRUE, IS_TYPE_COLLECTABLE, IS_TYPE_REFCOUNTED,
16    IS_UNDEF, IS_VOID, PHP_INI_ALL, PHP_INI_PERDIR, PHP_INI_SYSTEM, PHP_INI_USER,
17    Z_TYPE_FLAGS_SHIFT, ZEND_ACC_ABSTRACT, ZEND_ACC_ANON_CLASS, ZEND_ACC_CALL_VIA_TRAMPOLINE,
18    ZEND_ACC_CHANGED, ZEND_ACC_CLOSURE, ZEND_ACC_CONSTANTS_UPDATED, ZEND_ACC_CTOR,
19    ZEND_ACC_DEPRECATED, ZEND_ACC_DONE_PASS_TWO, ZEND_ACC_EARLY_BINDING, ZEND_ACC_FAKE_CLOSURE,
20    ZEND_ACC_FINAL, ZEND_ACC_GENERATOR, ZEND_ACC_HAS_FINALLY_BLOCK, ZEND_ACC_HAS_RETURN_TYPE,
21    ZEND_ACC_HAS_TYPE_HINTS, ZEND_ACC_HEAP_RT_CACHE, ZEND_ACC_IMMUTABLE,
22    ZEND_ACC_IMPLICIT_ABSTRACT_CLASS, ZEND_ACC_INTERFACE, ZEND_ACC_LINKED, ZEND_ACC_NEARLY_LINKED,
23    ZEND_ACC_NEVER_CACHE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, ZEND_ACC_PRELOADED, ZEND_ACC_PRIVATE,
24    ZEND_ACC_PROMOTED, ZEND_ACC_PROTECTED, ZEND_ACC_PUBLIC, ZEND_ACC_RESOLVED_INTERFACES,
25    ZEND_ACC_RESOLVED_PARENT, ZEND_ACC_RETURN_REFERENCE, ZEND_ACC_STATIC, ZEND_ACC_STRICT_TYPES,
26    ZEND_ACC_TOP_LEVEL, ZEND_ACC_TRAIT, ZEND_ACC_TRAIT_CLONE, ZEND_ACC_UNRESOLVED_VARIANCE,
27    ZEND_ACC_USE_GUARDS, ZEND_ACC_USES_THIS, ZEND_ACC_VARIADIC, ZEND_EVAL_CODE,
28    ZEND_HAS_STATIC_IN_METHODS, ZEND_INTERNAL_FUNCTION, ZEND_USER_FUNCTION,
29};
30
31use std::convert::TryFrom;
32
33use crate::error::{Error, Result};
34
35bitflags! {
36    /// Flags used for setting the type of Zval.
37    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
38    pub struct ZvalTypeFlags: u32 {
39        /// Undefined
40        const Undef = IS_UNDEF;
41        /// Null
42        const Null = IS_NULL;
43        /// `false`
44        const False = IS_FALSE;
45        /// `true`
46        const True = IS_TRUE;
47        /// Integer
48        const Long = IS_LONG;
49        /// Floating point number
50        const Double = IS_DOUBLE;
51        /// String
52        const String = IS_STRING;
53        /// Array
54        const Array = IS_ARRAY;
55        /// Object
56        const Object = IS_OBJECT;
57        /// Resource
58        const Resource = IS_RESOURCE;
59        /// Reference
60        const Reference = IS_REFERENCE;
61        /// Callable
62        const Callable = IS_CALLABLE;
63        /// Constant expression
64        const ConstantExpression = IS_CONSTANT_AST;
65        /// Void
66        const Void = IS_VOID;
67        /// Pointer
68        const Ptr = IS_PTR;
69        /// Iterable
70        const Iterable = IS_ITERABLE;
71
72        /// Interned string extended
73        const InternedStringEx = Self::String.bits();
74        /// String extended
75        const StringEx = Self::String.bits() | Self::RefCounted.bits();
76        /// Array extended
77        const ArrayEx = Self::Array.bits() | Self::RefCounted.bits() | Self::Collectable.bits();
78        /// Object extended
79        const ObjectEx = Self::Object.bits() | Self::RefCounted.bits() | Self::Collectable.bits();
80        /// Resource extended
81        const ResourceEx = Self::Resource.bits() | Self::RefCounted.bits();
82        /// Reference extended
83        const ReferenceEx = Self::Reference.bits() | Self::RefCounted.bits();
84        /// Constant ast extended
85        const ConstantAstEx = Self::ConstantExpression.bits() | Self::RefCounted.bits();
86
87        /// Reference counted
88        const RefCounted = (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT);
89        /// Collectable
90        const Collectable = (IS_TYPE_COLLECTABLE << Z_TYPE_FLAGS_SHIFT);
91
92        /// Immutable (used for the shared empty array)
93        const Immutable = GC_IMMUTABLE;
94    }
95}
96
97bitflags! {
98    /// Flags for building classes.
99    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
100    pub struct ClassFlags: u32 {
101        /// Final class or method
102        const Final = ZEND_ACC_FINAL;
103        /// Abstract method
104        const Abstract = ZEND_ACC_ABSTRACT;
105        /// Immutable `op_array` and class_entries
106        /// (implemented only for lazy loading of `op_array`s)
107        const Immutable = ZEND_ACC_IMMUTABLE;
108        /// Function has typed arguments / class has typed props
109        const HasTypeHints = ZEND_ACC_HAS_TYPE_HINTS;
110        /// Top-level class or function declaration
111        const TopLevel = ZEND_ACC_TOP_LEVEL;
112        /// op_array or class is preloaded
113        const Preloaded = ZEND_ACC_PRELOADED;
114
115        /// Class entry is an interface
116        const Interface = ZEND_ACC_INTERFACE;
117        /// Class entry is a trait
118        const Trait = ZEND_ACC_TRAIT;
119        /// Anonymous class
120        const AnonymousClass = ZEND_ACC_ANON_CLASS;
121        /// Class is an Enum
122        #[cfg(php81)]
123        const Enum = ZEND_ACC_ENUM;
124        /// Class linked with parent, interfaces and traits
125        const Linked = ZEND_ACC_LINKED;
126        /// Class is abstract, since it is set by any abstract method
127        const ImplicitAbstractClass = ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
128        /// Class has magic methods `__get`/`__set`/`__unset`/`__isset` that use guards
129        const UseGuards = ZEND_ACC_USE_GUARDS;
130
131        /// Class constants updated
132        const ConstantsUpdated = ZEND_ACC_CONSTANTS_UPDATED;
133        /// Objects of this class may not have dynamic properties
134        const NoDynamicProperties = ZEND_ACC_NO_DYNAMIC_PROPERTIES;
135        /// User class has methods with static variables
136        const HasStaticInMethods = ZEND_HAS_STATIC_IN_METHODS;
137        /// Children must reuse parent `get_iterator()`
138        #[cfg(not(php82))]
139        const ReuseGetIterator = ZEND_ACC_REUSE_GET_ITERATOR;
140        /// Parent class is resolved (CE)
141        const ResolvedParent = ZEND_ACC_RESOLVED_PARENT;
142        /// Interfaces are resolved (CE)
143        const ResolvedInterfaces = ZEND_ACC_RESOLVED_INTERFACES;
144        /// Class has unresolved variance obligations
145        const UnresolvedVariance = ZEND_ACC_UNRESOLVED_VARIANCE;
146        /// Class is linked apart from variance obligations
147        const NearlyLinked = ZEND_ACC_NEARLY_LINKED;
148
149        /// Class cannot be serialized or unserialized
150        #[cfg(php81)]
151        const NotSerializable = crate::ffi::ZEND_ACC_NOT_SERIALIZABLE;
152
153        /// Readonly class (PHP 8.2+)
154        /// All properties are implicitly readonly
155        #[cfg(php82)]
156        const ReadonlyClass = crate::ffi::ZEND_ACC_READONLY_CLASS;
157    }
158}
159
160bitflags! {
161    /// Flags for building methods.
162    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
163    pub struct MethodFlags: u32 {
164        /// Visibility public
165        const Public = ZEND_ACC_PUBLIC;
166        /// Visibility protected
167        const Protected = ZEND_ACC_PROTECTED;
168        /// Visibility private
169        const Private = ZEND_ACC_PRIVATE;
170        /// Method or property overrides private one
171        const Changed = ZEND_ACC_CHANGED;
172        /// Static method
173        const Static = ZEND_ACC_STATIC;
174        /// Final method
175        const Final = ZEND_ACC_FINAL;
176        /// Abstract method
177        const Abstract = ZEND_ACC_ABSTRACT;
178        /// Immutable `op_array` and class_entries
179        /// (implemented only for lazy loading of op_arrays)
180        const Immutable = ZEND_ACC_IMMUTABLE;
181        /// Function has typed arguments / class has typed props
182        const HasTypeHints = ZEND_ACC_HAS_TYPE_HINTS;
183        /// Top-level class or function declaration
184        const TopLevel = ZEND_ACC_TOP_LEVEL;
185        /// `op_array` or class is preloaded
186        const Preloaded = ZEND_ACC_PRELOADED;
187
188        /// Deprecation flag
189        const Deprecated = ZEND_ACC_DEPRECATED;
190        /// Function returning by reference
191        const ReturnReference = ZEND_ACC_RETURN_REFERENCE;
192        /// Function has a return type
193        const HasReturnType = ZEND_ACC_HAS_RETURN_TYPE;
194        /// Function with variable number of arguments
195        const Variadic = ZEND_ACC_VARIADIC;
196        /// `op_array` has finally blocks (user only)
197        const HasFinallyBlock = ZEND_ACC_HAS_FINALLY_BLOCK;
198        /// "main" `op_array` with `ZEND_DECLARE_CLASS_DELAYED` opcodes
199        const EarlyBinding = ZEND_ACC_EARLY_BINDING;
200        /// Closure uses `$this`
201        const UsesThis = ZEND_ACC_USES_THIS;
202        /// Call through user function trampoline
203        ///
204        /// # Example
205        /// - `__call`
206        /// - `__callStatic`
207        const CallViaTrampoline = ZEND_ACC_CALL_VIA_TRAMPOLINE;
208        /// Disable inline caching
209        const NeverCache = ZEND_ACC_NEVER_CACHE;
210        /// `op_array` is a clone of trait method
211        const TraitClone = ZEND_ACC_TRAIT_CLONE;
212        /// Function is a constructor
213        const IsConstructor = ZEND_ACC_CTOR;
214        /// Function is a closure
215        const Closure = ZEND_ACC_CLOSURE;
216        /// Function is a fake closure
217        const FakeClosure = ZEND_ACC_FAKE_CLOSURE;
218        /// Function is a generator
219        const Generator = ZEND_ACC_GENERATOR;
220        /// Function was processed by pass two (user only)
221        const DonePassTwo = ZEND_ACC_DONE_PASS_TWO;
222        /// `run_time_cache` allocated on heap (user only)
223        const HeapRTCache = ZEND_ACC_HEAP_RT_CACHE;
224        /// `op_array` uses strict mode types
225        const StrictTypes = ZEND_ACC_STRICT_TYPES;
226    }
227}
228
229bitflags! {
230    /// Flags for building properties.
231    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
232    pub struct PropertyFlags: u32 {
233        /// Visibility public
234        const Public = ZEND_ACC_PUBLIC;
235        /// Visibility protected
236        const Protected = ZEND_ACC_PROTECTED;
237        /// Visibility private
238        const Private = ZEND_ACC_PRIVATE;
239        /// Property or method overrides private one
240        const Changed = ZEND_ACC_CHANGED;
241        /// Static property
242        const Static = ZEND_ACC_STATIC;
243        /// Promoted property
244        const Promoted = ZEND_ACC_PROMOTED;
245    }
246}
247
248bitflags! {
249    /// Flags for building constants.
250    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
251    pub struct ConstantFlags: u32 {
252        /// Visibility public
253        const Public = ZEND_ACC_PUBLIC;
254        /// Visibility protected
255        const Protected = ZEND_ACC_PROTECTED;
256        /// Visibility private
257        const Private = ZEND_ACC_PRIVATE;
258    }
259}
260
261bitflags! {
262    /// Flags for building module global constants.
263    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
264    pub struct GlobalConstantFlags: u32 {
265        /// Persistent
266        const Persistent = CONST_PERSISTENT;
267        /// Can't be saved in file cache
268        const NoFileCache = CONST_NO_FILE_CACHE;
269        /// Deprecated (this flag is not deprecated, it literally means the constant is deprecated)
270        const Deprecated = CONST_DEPRECATED;
271    }
272}
273
274bitflags! {
275    /// Represents the result of a function.
276    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
277    pub struct ZendResult: i32 {
278        /// Function call was successful.
279        const Success = 0;
280        /// Function call failed.
281        const Failure = -1;
282    }
283}
284
285bitflags! {
286    /// Represents permissions for where a configuration setting may be set.
287    pub struct IniEntryPermission: u32 {
288        /// User
289        const User = PHP_INI_USER;
290        /// Per directory
291        const PerDir = PHP_INI_PERDIR;
292        /// System
293        const System = PHP_INI_SYSTEM;
294        /// All
295        const All = PHP_INI_ALL;
296    }
297}
298
299bitflags! {
300    /// PHP error types (`E_*`), used to raise errors with [`php_error`] and to
301    /// filter them in an error observer.
302    ///
303    /// [`php_error`]: crate::error::php_error
304    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
305    pub struct ErrorType: u32 {
306        /// Error
307        const Error = E_ERROR;
308        /// Warning
309        const Warning = E_WARNING;
310        /// Parse
311        const Parse = E_PARSE;
312        /// Notice
313        const Notice = E_NOTICE;
314        /// Core error
315        const CoreError = E_CORE_ERROR;
316        /// Core warning
317        const CoreWarning = E_CORE_WARNING;
318        /// Compile error
319        const CompileError = E_COMPILE_ERROR;
320        /// Compile warning
321        const CompileWarning = E_COMPILE_WARNING;
322        /// User error
323        #[cfg_attr(php84, deprecated = "`E_USER_ERROR` is deprecated since PHP 8.4. Throw an exception instead.")]
324        const UserError = E_USER_ERROR;
325        /// User warning
326        const UserWarning = E_USER_WARNING;
327        /// User notice
328        const UserNotice = E_USER_NOTICE;
329        /// Strict
330        #[cfg_attr(php84, deprecated = "`E_STRICT` is removed from `E_ALL` since PHP 8.4 and is never raised.")]
331        const Strict = E_STRICT;
332        /// Recoverable error
333        const RecoverableError = E_RECOVERABLE_ERROR;
334        /// Deprecated
335        const Deprecated = E_DEPRECATED;
336        /// User deprecated
337        const UserDeprecated = E_USER_DEPRECATED;
338        /// All error types (`E_ALL`). Contains `Strict` before PHP 8.4.
339        const All = E_ALL;
340        /// Core errors and warnings (`E_CORE`)
341        const Core = E_CORE;
342        /// Fatal error types (`E_FATAL_ERRORS`)
343        const Fatal = E_FATAL_ERRORS;
344    }
345}
346
347/// Represents the type of a function.
348#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
349pub enum FunctionType {
350    /// Internal function
351    Internal,
352    /// User function
353    User,
354    /// Eval code
355    Eval,
356}
357
358impl TryFrom<u8> for FunctionType {
359    type Error = Error;
360
361    #[allow(clippy::bad_bit_mask)]
362    fn try_from(value: u8) -> Result<Self> {
363        match value.into() {
364            ZEND_INTERNAL_FUNCTION => Ok(Self::Internal),
365            ZEND_USER_FUNCTION => Ok(Self::User),
366            ZEND_EVAL_CODE => Ok(Self::Eval),
367            _ => Err(Error::UnknownFunctionType(value)),
368        }
369    }
370}
371
372pub use ext_php_rs_introspection::DataType;
373
374/// Conversions between [`DataType`] and the Zend `IS_*` type constants.
375///
376/// The constants depend on the PHP version and come from bindgen, so they
377/// cannot live next to `DataType` in `ext-php-rs-introspection`.
378pub trait DataTypeExt {
379    /// Returns the integer representation of the data type.
380    fn as_u32(&self) -> u32;
381
382    /// Builds the data type from a Zend type info word.
383    fn from_u32(value: u32) -> Self;
384}
385
386impl DataTypeExt for DataType {
387    fn as_u32(&self) -> u32 {
388        match self {
389            DataType::Undef => IS_UNDEF,
390            DataType::Null => IS_NULL,
391            DataType::False => IS_FALSE,
392            DataType::True => IS_TRUE,
393            DataType::Long => IS_LONG,
394            DataType::Double => IS_DOUBLE,
395            DataType::String => IS_STRING,
396            DataType::Array => IS_ARRAY,
397            DataType::Object(_) => IS_OBJECT,
398            DataType::Resource | DataType::Reference => IS_RESOURCE,
399            DataType::Indirect => IS_INDIRECT,
400            DataType::Callable => IS_CALLABLE,
401            DataType::ConstantExpression => IS_CONSTANT_AST,
402            DataType::Void => IS_VOID,
403            DataType::Mixed => IS_MIXED,
404            DataType::Bool => _IS_BOOL,
405            DataType::Ptr => IS_PTR,
406            DataType::Iterable => IS_ITERABLE,
407        }
408    }
409
410    #[allow(clippy::bad_bit_mask)]
411    fn from_u32(value: u32) -> Self {
412        macro_rules! contains {
413            ($c: ident, $t: ident) => {
414                if (value & $c) == $c {
415                    return DataType::$t;
416                }
417            };
418        }
419
420        contains!(IS_VOID, Void);
421        contains!(IS_PTR, Ptr);
422        contains!(IS_INDIRECT, Indirect);
423        contains!(IS_CALLABLE, Callable);
424        contains!(IS_CONSTANT_AST, ConstantExpression);
425        contains!(IS_REFERENCE, Reference);
426        contains!(IS_RESOURCE, Resource);
427        contains!(IS_ARRAY, Array);
428        contains!(IS_STRING, String);
429        contains!(IS_DOUBLE, Double);
430        contains!(IS_LONG, Long);
431        contains!(IS_TRUE, True);
432        contains!(IS_FALSE, False);
433        contains!(IS_NULL, Null);
434
435        if (value & IS_OBJECT) == IS_OBJECT {
436            return DataType::ANY_OBJECT;
437        }
438
439        contains!(IS_UNDEF, Undef);
440
441        DataType::Mixed
442    }
443}
444
445// TODO: Ideally want something like this
446// pub struct Type {
447//     data_type: DataType,
448//     is_refcounted: bool,
449//     is_collectable: bool,
450//     is_immutable: bool,
451//     is_persistent: bool,
452// }
453//
454// impl From<u32> for Type { ... }
455
456impl TryFrom<ZvalTypeFlags> for DataType {
457    type Error = Error;
458
459    fn try_from(value: ZvalTypeFlags) -> Result<Self> {
460        macro_rules! contains {
461            ($t: ident) => {
462                if value.contains(ZvalTypeFlags::$t) {
463                    return Ok(DataType::$t);
464                }
465            };
466        }
467
468        contains!(Undef);
469        contains!(Null);
470        contains!(False);
471        contains!(True);
472        contains!(False);
473        contains!(Long);
474        contains!(Double);
475        contains!(String);
476        contains!(Array);
477        contains!(Resource);
478        contains!(Callable);
479        contains!(ConstantExpression);
480        contains!(Void);
481
482        if value.contains(ZvalTypeFlags::Object) {
483            return Ok(DataType::ANY_OBJECT);
484        }
485
486        Err(Error::InvalidTypeToDatatype(value))
487    }
488}
489
490#[cfg(test)]
491mod tests {
492    use super::{DataType, DataTypeExt, FunctionType};
493    use crate::error::Error;
494    use crate::ffi::{
495        IS_ARRAY, IS_ARRAY_EX, IS_CONSTANT_AST, IS_CONSTANT_AST_EX, IS_DOUBLE, IS_FALSE,
496        IS_INDIRECT, IS_INTERNED_STRING_EX, IS_LONG, IS_NULL, IS_OBJECT, IS_OBJECT_EX, IS_PTR,
497        IS_REFERENCE, IS_REFERENCE_EX, IS_RESOURCE, IS_RESOURCE_EX, IS_STRING, IS_STRING_EX,
498        IS_TRUE, IS_UNDEF, IS_VOID,
499    };
500    use crate::ffi::{ZEND_EVAL_CODE, ZEND_INTERNAL_FUNCTION, ZEND_USER_FUNCTION};
501    #[test]
502    fn test_datatype() {
503        macro_rules! test {
504            ($c: ident, $t: ident) => {
505                assert_eq!(DataType::from_u32($c), DataType::$t);
506            };
507        }
508
509        test!(IS_UNDEF, Undef);
510        test!(IS_NULL, Null);
511        test!(IS_FALSE, False);
512        test!(IS_TRUE, True);
513        test!(IS_LONG, Long);
514        test!(IS_DOUBLE, Double);
515        test!(IS_STRING, String);
516        test!(IS_ARRAY, Array);
517        assert_eq!(DataType::from_u32(IS_OBJECT), DataType::ANY_OBJECT);
518        test!(IS_RESOURCE, Resource);
519        test!(IS_REFERENCE, Reference);
520        test!(IS_CONSTANT_AST, ConstantExpression);
521        test!(IS_INDIRECT, Indirect);
522        test!(IS_VOID, Void);
523        test!(IS_PTR, Ptr);
524
525        test!(IS_INTERNED_STRING_EX, String);
526        test!(IS_STRING_EX, String);
527        test!(IS_ARRAY_EX, Array);
528        assert_eq!(DataType::from_u32(IS_OBJECT_EX), DataType::ANY_OBJECT);
529        test!(IS_RESOURCE_EX, Resource);
530        test!(IS_REFERENCE_EX, Reference);
531        test!(IS_CONSTANT_AST_EX, ConstantExpression);
532    }
533
534    #[test]
535    fn function_type_maps_the_engine_constants() {
536        let cases = [
537            (ZEND_INTERNAL_FUNCTION, FunctionType::Internal),
538            (ZEND_USER_FUNCTION, FunctionType::User),
539            (ZEND_EVAL_CODE, FunctionType::Eval),
540        ];
541
542        for (raw, expected) in cases {
543            let ty = FunctionType::try_from(u8::try_from(raw).expect("fits in u8"));
544
545            assert_eq!(ty.ok(), Some(expected));
546        }
547    }
548
549    #[test]
550    fn function_type_rejects_an_unknown_value() {
551        let err = FunctionType::try_from(u8::MAX);
552
553        assert!(matches!(err, Err(Error::UnknownFunctionType(u8::MAX))));
554    }
555}