1use 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 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
38 pub struct ZvalTypeFlags: u32 {
39 const Undef = IS_UNDEF;
41 const Null = IS_NULL;
43 const False = IS_FALSE;
45 const True = IS_TRUE;
47 const Long = IS_LONG;
49 const Double = IS_DOUBLE;
51 const String = IS_STRING;
53 const Array = IS_ARRAY;
55 const Object = IS_OBJECT;
57 const Resource = IS_RESOURCE;
59 const Reference = IS_REFERENCE;
61 const Callable = IS_CALLABLE;
63 const ConstantExpression = IS_CONSTANT_AST;
65 const Void = IS_VOID;
67 const Ptr = IS_PTR;
69 const Iterable = IS_ITERABLE;
71
72 const InternedStringEx = Self::String.bits();
74 const StringEx = Self::String.bits() | Self::RefCounted.bits();
76 const ArrayEx = Self::Array.bits() | Self::RefCounted.bits() | Self::Collectable.bits();
78 const ObjectEx = Self::Object.bits() | Self::RefCounted.bits() | Self::Collectable.bits();
80 const ResourceEx = Self::Resource.bits() | Self::RefCounted.bits();
82 const ReferenceEx = Self::Reference.bits() | Self::RefCounted.bits();
84 const ConstantAstEx = Self::ConstantExpression.bits() | Self::RefCounted.bits();
86
87 const RefCounted = (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT);
89 const Collectable = (IS_TYPE_COLLECTABLE << Z_TYPE_FLAGS_SHIFT);
91
92 const Immutable = GC_IMMUTABLE;
94 }
95}
96
97bitflags! {
98 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
100 pub struct ClassFlags: u32 {
101 const Final = ZEND_ACC_FINAL;
103 const Abstract = ZEND_ACC_ABSTRACT;
105 const Immutable = ZEND_ACC_IMMUTABLE;
108 const HasTypeHints = ZEND_ACC_HAS_TYPE_HINTS;
110 const TopLevel = ZEND_ACC_TOP_LEVEL;
112 const Preloaded = ZEND_ACC_PRELOADED;
114
115 const Interface = ZEND_ACC_INTERFACE;
117 const Trait = ZEND_ACC_TRAIT;
119 const AnonymousClass = ZEND_ACC_ANON_CLASS;
121 #[cfg(php81)]
123 const Enum = ZEND_ACC_ENUM;
124 const Linked = ZEND_ACC_LINKED;
126 const ImplicitAbstractClass = ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
128 const UseGuards = ZEND_ACC_USE_GUARDS;
130
131 const ConstantsUpdated = ZEND_ACC_CONSTANTS_UPDATED;
133 const NoDynamicProperties = ZEND_ACC_NO_DYNAMIC_PROPERTIES;
135 const HasStaticInMethods = ZEND_HAS_STATIC_IN_METHODS;
137 #[cfg(not(php82))]
139 const ReuseGetIterator = ZEND_ACC_REUSE_GET_ITERATOR;
140 const ResolvedParent = ZEND_ACC_RESOLVED_PARENT;
142 const ResolvedInterfaces = ZEND_ACC_RESOLVED_INTERFACES;
144 const UnresolvedVariance = ZEND_ACC_UNRESOLVED_VARIANCE;
146 const NearlyLinked = ZEND_ACC_NEARLY_LINKED;
148
149 #[cfg(php81)]
151 const NotSerializable = crate::ffi::ZEND_ACC_NOT_SERIALIZABLE;
152
153 #[cfg(php82)]
156 const ReadonlyClass = crate::ffi::ZEND_ACC_READONLY_CLASS;
157 }
158}
159
160bitflags! {
161 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
163 pub struct MethodFlags: u32 {
164 const Public = ZEND_ACC_PUBLIC;
166 const Protected = ZEND_ACC_PROTECTED;
168 const Private = ZEND_ACC_PRIVATE;
170 const Changed = ZEND_ACC_CHANGED;
172 const Static = ZEND_ACC_STATIC;
174 const Final = ZEND_ACC_FINAL;
176 const Abstract = ZEND_ACC_ABSTRACT;
178 const Immutable = ZEND_ACC_IMMUTABLE;
181 const HasTypeHints = ZEND_ACC_HAS_TYPE_HINTS;
183 const TopLevel = ZEND_ACC_TOP_LEVEL;
185 const Preloaded = ZEND_ACC_PRELOADED;
187
188 const Deprecated = ZEND_ACC_DEPRECATED;
190 const ReturnReference = ZEND_ACC_RETURN_REFERENCE;
192 const HasReturnType = ZEND_ACC_HAS_RETURN_TYPE;
194 const Variadic = ZEND_ACC_VARIADIC;
196 const HasFinallyBlock = ZEND_ACC_HAS_FINALLY_BLOCK;
198 const EarlyBinding = ZEND_ACC_EARLY_BINDING;
200 const UsesThis = ZEND_ACC_USES_THIS;
202 const CallViaTrampoline = ZEND_ACC_CALL_VIA_TRAMPOLINE;
208 const NeverCache = ZEND_ACC_NEVER_CACHE;
210 const TraitClone = ZEND_ACC_TRAIT_CLONE;
212 const IsConstructor = ZEND_ACC_CTOR;
214 const Closure = ZEND_ACC_CLOSURE;
216 const FakeClosure = ZEND_ACC_FAKE_CLOSURE;
218 const Generator = ZEND_ACC_GENERATOR;
220 const DonePassTwo = ZEND_ACC_DONE_PASS_TWO;
222 const HeapRTCache = ZEND_ACC_HEAP_RT_CACHE;
224 const StrictTypes = ZEND_ACC_STRICT_TYPES;
226 }
227}
228
229bitflags! {
230 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
232 pub struct PropertyFlags: u32 {
233 const Public = ZEND_ACC_PUBLIC;
235 const Protected = ZEND_ACC_PROTECTED;
237 const Private = ZEND_ACC_PRIVATE;
239 const Changed = ZEND_ACC_CHANGED;
241 const Static = ZEND_ACC_STATIC;
243 const Promoted = ZEND_ACC_PROMOTED;
245 }
246}
247
248bitflags! {
249 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
251 pub struct ConstantFlags: u32 {
252 const Public = ZEND_ACC_PUBLIC;
254 const Protected = ZEND_ACC_PROTECTED;
256 const Private = ZEND_ACC_PRIVATE;
258 }
259}
260
261bitflags! {
262 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
264 pub struct GlobalConstantFlags: u32 {
265 const Persistent = CONST_PERSISTENT;
267 const NoFileCache = CONST_NO_FILE_CACHE;
269 const Deprecated = CONST_DEPRECATED;
271 }
272}
273
274bitflags! {
275 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
277 pub struct ZendResult: i32 {
278 const Success = 0;
280 const Failure = -1;
282 }
283}
284
285bitflags! {
286 pub struct IniEntryPermission: u32 {
288 const User = PHP_INI_USER;
290 const PerDir = PHP_INI_PERDIR;
292 const System = PHP_INI_SYSTEM;
294 const All = PHP_INI_ALL;
296 }
297}
298
299bitflags! {
300 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
305 pub struct ErrorType: u32 {
306 const Error = E_ERROR;
308 const Warning = E_WARNING;
310 const Parse = E_PARSE;
312 const Notice = E_NOTICE;
314 const CoreError = E_CORE_ERROR;
316 const CoreWarning = E_CORE_WARNING;
318 const CompileError = E_COMPILE_ERROR;
320 const CompileWarning = E_COMPILE_WARNING;
322 #[cfg_attr(php84, deprecated = "`E_USER_ERROR` is deprecated since PHP 8.4. Throw an exception instead.")]
324 const UserError = E_USER_ERROR;
325 const UserWarning = E_USER_WARNING;
327 const UserNotice = E_USER_NOTICE;
329 #[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 const RecoverableError = E_RECOVERABLE_ERROR;
334 const Deprecated = E_DEPRECATED;
336 const UserDeprecated = E_USER_DEPRECATED;
338 const All = E_ALL;
340 const Core = E_CORE;
342 const Fatal = E_FATAL_ERRORS;
344 }
345}
346
347#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
349pub enum FunctionType {
350 Internal,
352 User,
354 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
374pub trait DataTypeExt {
379 fn as_u32(&self) -> u32;
381
382 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
445impl 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}