1use bitflags::bitflags;
4
5#[cfg(not(php82))]
6use crate::ffi::ZEND_ACC_REUSE_GET_ITERATOR;
7use crate::ffi::{
8 CONST_CS, CONST_DEPRECATED, CONST_NO_FILE_CACHE, CONST_PERSISTENT, E_COMPILE_ERROR,
9 E_COMPILE_WARNING, E_CORE_ERROR, E_CORE_WARNING, E_DEPRECATED, E_ERROR, E_NOTICE, E_PARSE,
10 E_RECOVERABLE_ERROR, E_STRICT, E_USER_DEPRECATED, E_USER_ERROR, E_USER_NOTICE, E_USER_WARNING,
11 E_WARNING, IS_ARRAY, IS_CALLABLE, IS_CONSTANT_AST, IS_DOUBLE, IS_FALSE, IS_INDIRECT,
12 IS_ITERABLE, IS_LONG, IS_MIXED, IS_NULL, IS_OBJECT, IS_PTR, IS_REFERENCE, IS_RESOURCE,
13 IS_STRING, IS_TRUE, IS_TYPE_COLLECTABLE, IS_TYPE_REFCOUNTED, IS_UNDEF, IS_VOID, PHP_INI_ALL,
14 PHP_INI_PERDIR, PHP_INI_SYSTEM, PHP_INI_USER, ZEND_ACC_ABSTRACT, ZEND_ACC_ANON_CLASS,
15 ZEND_ACC_CALL_VIA_TRAMPOLINE, ZEND_ACC_CHANGED, ZEND_ACC_CLOSURE, ZEND_ACC_CONSTANTS_UPDATED,
16 ZEND_ACC_CTOR, ZEND_ACC_DEPRECATED, ZEND_ACC_DONE_PASS_TWO, ZEND_ACC_EARLY_BINDING,
17 ZEND_ACC_FAKE_CLOSURE, ZEND_ACC_FINAL, ZEND_ACC_GENERATOR, ZEND_ACC_HAS_FINALLY_BLOCK,
18 ZEND_ACC_HAS_RETURN_TYPE, ZEND_ACC_HAS_TYPE_HINTS, ZEND_ACC_HEAP_RT_CACHE, ZEND_ACC_IMMUTABLE,
19 ZEND_ACC_IMPLICIT_ABSTRACT_CLASS, ZEND_ACC_INTERFACE, ZEND_ACC_LINKED, ZEND_ACC_NEARLY_LINKED,
20 ZEND_ACC_NEVER_CACHE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, ZEND_ACC_PRELOADED, ZEND_ACC_PRIVATE,
21 ZEND_ACC_PROMOTED, ZEND_ACC_PROTECTED, ZEND_ACC_PUBLIC, ZEND_ACC_RESOLVED_INTERFACES,
22 ZEND_ACC_RESOLVED_PARENT, ZEND_ACC_RETURN_REFERENCE, ZEND_ACC_STATIC, ZEND_ACC_STRICT_TYPES,
23 ZEND_ACC_TOP_LEVEL, ZEND_ACC_TRAIT, ZEND_ACC_TRAIT_CLONE, ZEND_ACC_UNRESOLVED_VARIANCE,
24 ZEND_ACC_USES_THIS, ZEND_ACC_USE_GUARDS, ZEND_ACC_VARIADIC, ZEND_EVAL_CODE,
25 ZEND_HAS_STATIC_IN_METHODS, ZEND_INTERNAL_FUNCTION, ZEND_USER_FUNCTION, Z_TYPE_FLAGS_SHIFT,
26 _IS_BOOL,
27};
28
29use std::{convert::TryFrom, fmt::Display};
30
31use crate::error::{Error, Result};
32
33bitflags! {
34 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
36 pub struct ZvalTypeFlags: u32 {
37 const Undef = IS_UNDEF;
39 const Null = IS_NULL;
41 const False = IS_FALSE;
43 const True = IS_TRUE;
45 const Long = IS_LONG;
47 const Double = IS_DOUBLE;
49 const String = IS_STRING;
51 const Array = IS_ARRAY;
53 const Object = IS_OBJECT;
55 const Resource = IS_RESOURCE;
57 const Reference = IS_REFERENCE;
59 const Callable = IS_CALLABLE;
61 const ConstantExpression = IS_CONSTANT_AST;
63 const Void = IS_VOID;
65 const Ptr = IS_PTR;
67 const Iterable = IS_ITERABLE;
69
70 const InternedStringEx = Self::String.bits();
72 const StringEx = Self::String.bits() | Self::RefCounted.bits();
74 const ArrayEx = Self::Array.bits() | Self::RefCounted.bits() | Self::Collectable.bits();
76 const ObjectEx = Self::Object.bits() | Self::RefCounted.bits() | Self::Collectable.bits();
78 const ResourceEx = Self::Resource.bits() | Self::RefCounted.bits();
80 const ReferenceEx = Self::Reference.bits() | Self::RefCounted.bits();
82 const ConstantAstEx = Self::ConstantExpression.bits() | Self::RefCounted.bits();
84
85 const RefCounted = (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT);
87 const Collectable = (IS_TYPE_COLLECTABLE << Z_TYPE_FLAGS_SHIFT);
89 }
90}
91
92bitflags! {
93 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
95 pub struct ClassFlags: u32 {
96 const Final = ZEND_ACC_FINAL;
98 const Abstract = ZEND_ACC_ABSTRACT;
100 const Immutable = ZEND_ACC_IMMUTABLE;
103 const HasTypeHints = ZEND_ACC_HAS_TYPE_HINTS;
105 const TopLevel = ZEND_ACC_TOP_LEVEL;
107 const Preloaded = ZEND_ACC_PRELOADED;
109
110 const Interface = ZEND_ACC_INTERFACE;
112 const Trait = ZEND_ACC_TRAIT;
114 const AnonymousClass = ZEND_ACC_ANON_CLASS;
116 const Linked = ZEND_ACC_LINKED;
118 const ImplicitAbstractClass = ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
120 const UseGuards = ZEND_ACC_USE_GUARDS;
122
123 const ConstantsUpdated = ZEND_ACC_CONSTANTS_UPDATED;
125 const NoDynamicProperties = ZEND_ACC_NO_DYNAMIC_PROPERTIES;
127 const HasStaticInMethods = ZEND_HAS_STATIC_IN_METHODS;
129 #[cfg(not(php82))]
131 const ReuseGetIterator = ZEND_ACC_REUSE_GET_ITERATOR;
132 const ResolvedParent = ZEND_ACC_RESOLVED_PARENT;
134 const ResolvedInterfaces = ZEND_ACC_RESOLVED_INTERFACES;
136 const UnresolvedVariance = ZEND_ACC_UNRESOLVED_VARIANCE;
138 const NearlyLinked = ZEND_ACC_NEARLY_LINKED;
140
141 #[cfg(php81)]
143 const NotSerializable = crate::ffi::ZEND_ACC_NOT_SERIALIZABLE;
144 }
145}
146
147bitflags! {
148 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
150 pub struct MethodFlags: u32 {
151 const Public = ZEND_ACC_PUBLIC;
153 const Protected = ZEND_ACC_PROTECTED;
155 const Private = ZEND_ACC_PRIVATE;
157 const Changed = ZEND_ACC_CHANGED;
159 const Static = ZEND_ACC_STATIC;
161 const Final = ZEND_ACC_FINAL;
163 const Abstract = ZEND_ACC_ABSTRACT;
165 const Immutable = ZEND_ACC_IMMUTABLE;
168 const HasTypeHints = ZEND_ACC_HAS_TYPE_HINTS;
170 const TopLevel = ZEND_ACC_TOP_LEVEL;
172 const Preloaded = ZEND_ACC_PRELOADED;
174
175 const Deprecated = ZEND_ACC_DEPRECATED;
177 const ReturnReference = ZEND_ACC_RETURN_REFERENCE;
179 const HasReturnType = ZEND_ACC_HAS_RETURN_TYPE;
181 const Variadic = ZEND_ACC_VARIADIC;
183 const HasFinallyBlock = ZEND_ACC_HAS_FINALLY_BLOCK;
185 const EarlyBinding = ZEND_ACC_EARLY_BINDING;
187 const UsesThis = ZEND_ACC_USES_THIS;
189 const CallViaTrampoline = ZEND_ACC_CALL_VIA_TRAMPOLINE;
195 const NeverCache = ZEND_ACC_NEVER_CACHE;
197 const TraitClone = ZEND_ACC_TRAIT_CLONE;
199 const IsConstructor = ZEND_ACC_CTOR;
201 const Closure = ZEND_ACC_CLOSURE;
203 const FakeClosure = ZEND_ACC_FAKE_CLOSURE;
205 const Generator = ZEND_ACC_GENERATOR;
207 const DonePassTwo = ZEND_ACC_DONE_PASS_TWO;
209 const HeapRTCache = ZEND_ACC_HEAP_RT_CACHE;
211 const StrictTypes = ZEND_ACC_STRICT_TYPES;
213 }
214}
215
216bitflags! {
217 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
219 pub struct PropertyFlags: u32 {
220 const Public = ZEND_ACC_PUBLIC;
222 const Protected = ZEND_ACC_PROTECTED;
224 const Private = ZEND_ACC_PRIVATE;
226 const Changed = ZEND_ACC_CHANGED;
228 const Static = ZEND_ACC_STATIC;
230 const Promoted = ZEND_ACC_PROMOTED;
232 }
233}
234
235bitflags! {
236 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
238 pub struct ConstantFlags: u32 {
239 const Public = ZEND_ACC_PUBLIC;
241 const Protected = ZEND_ACC_PROTECTED;
243 const Private = ZEND_ACC_PRIVATE;
245 const Promoted = ZEND_ACC_PROMOTED;
247 }
248}
249
250bitflags! {
251 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
253 pub struct GlobalConstantFlags: u32 {
254 #[deprecated(note = "No longer used -- always case-sensitive")]
256 const CaseSensitive = CONST_CS;
257 const Persistent = CONST_PERSISTENT;
259 const NoFileCache = CONST_NO_FILE_CACHE;
261 const Deprecated = CONST_DEPRECATED;
263 }
264}
265
266bitflags! {
267 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
269 pub struct ZendResult: i32 {
270 const Success = 0;
272 const Failure = -1;
274 }
275}
276
277bitflags! {
278 pub struct IniEntryPermission: u32 {
280 const User = PHP_INI_USER;
282 const PerDir = PHP_INI_PERDIR;
284 const System = PHP_INI_SYSTEM;
286 const All = PHP_INI_ALL;
288 }
289}
290
291bitflags! {
292 pub struct ErrorType: u32 {
294 const Error = E_ERROR;
296 const Warning = E_WARNING;
298 const Parse = E_PARSE;
300 const Notice = E_NOTICE;
302 const CoreError = E_CORE_ERROR;
304 const CoreWarning = E_CORE_WARNING;
306 const CompileError = E_COMPILE_ERROR;
308 const CompileWarning = E_COMPILE_WARNING;
310 #[cfg_attr(php84, deprecated = "`E_USER_ERROR` is deprecated since PHP 8.4. Throw an exception instead.")]
312 const UserError = E_USER_ERROR;
313 const UserWarning = E_USER_WARNING;
315 const UserNotice = E_USER_NOTICE;
317 const Strict = E_STRICT;
319 const RecoverableError = E_RECOVERABLE_ERROR;
321 const Deprecated = E_DEPRECATED;
323 const UserDeprecated = E_USER_DEPRECATED;
325 }
326}
327
328#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
330pub enum FunctionType {
331 Internal,
333 User,
335 Eval,
337}
338
339impl From<u8> for FunctionType {
340 #[allow(clippy::bad_bit_mask)]
341 fn from(value: u8) -> Self {
342 match value.into() {
343 ZEND_INTERNAL_FUNCTION => Self::Internal,
344 ZEND_USER_FUNCTION => Self::User,
345 ZEND_EVAL_CODE => Self::Eval,
346 _ => panic!("Unknown function type: {value}"),
347 }
348 }
349}
350
351#[repr(C, u8)]
353#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
354pub enum DataType {
355 Undef,
357 Null,
359 False,
361 True,
363 Long,
365 Double,
367 String,
369 Array,
371 Iterable,
373 Object(Option<&'static str>),
375 Resource,
377 Reference,
379 Callable,
381 ConstantExpression,
383 Void,
385 Mixed,
387 Bool,
389 Ptr,
391 Indirect,
393}
394
395impl Default for DataType {
396 fn default() -> Self {
397 Self::Void
398 }
399}
400
401impl DataType {
402 #[must_use]
404 pub const fn as_u32(&self) -> u32 {
405 match self {
406 DataType::Undef => IS_UNDEF,
407 DataType::Null => IS_NULL,
408 DataType::False => IS_FALSE,
409 DataType::True => IS_TRUE,
410 DataType::Long => IS_LONG,
411 DataType::Double => IS_DOUBLE,
412 DataType::String => IS_STRING,
413 DataType::Array => IS_ARRAY,
414 DataType::Object(_) => IS_OBJECT,
415 DataType::Resource | DataType::Reference => IS_RESOURCE,
416 DataType::Indirect => IS_INDIRECT,
417 DataType::Callable => IS_CALLABLE,
418 DataType::ConstantExpression => IS_CONSTANT_AST,
419 DataType::Void => IS_VOID,
420 DataType::Mixed => IS_MIXED,
421 DataType::Bool => _IS_BOOL,
422 DataType::Ptr => IS_PTR,
423 DataType::Iterable => IS_ITERABLE,
424 }
425 }
426}
427
428impl TryFrom<ZvalTypeFlags> for DataType {
440 type Error = Error;
441
442 fn try_from(value: ZvalTypeFlags) -> Result<Self> {
443 macro_rules! contains {
444 ($t: ident) => {
445 if value.contains(ZvalTypeFlags::$t) {
446 return Ok(DataType::$t);
447 }
448 };
449 }
450
451 contains!(Undef);
452 contains!(Null);
453 contains!(False);
454 contains!(True);
455 contains!(False);
456 contains!(Long);
457 contains!(Double);
458 contains!(String);
459 contains!(Array);
460 contains!(Resource);
461 contains!(Callable);
462 contains!(ConstantExpression);
463 contains!(Void);
464
465 if value.contains(ZvalTypeFlags::Object) {
466 return Ok(DataType::Object(None));
467 }
468
469 Err(Error::UnknownDatatype(0))
470 }
471}
472
473impl From<u32> for DataType {
474 #[allow(clippy::bad_bit_mask)]
475 fn from(value: u32) -> Self {
476 macro_rules! contains {
477 ($c: ident, $t: ident) => {
478 if (value & $c) == $c {
479 return DataType::$t;
480 }
481 };
482 }
483
484 contains!(IS_VOID, Void);
485 contains!(IS_PTR, Ptr);
486 contains!(IS_INDIRECT, Indirect);
487 contains!(IS_CALLABLE, Callable);
488 contains!(IS_CONSTANT_AST, ConstantExpression);
489 contains!(IS_REFERENCE, Reference);
490 contains!(IS_RESOURCE, Resource);
491 contains!(IS_ARRAY, Array);
492 contains!(IS_STRING, String);
493 contains!(IS_DOUBLE, Double);
494 contains!(IS_LONG, Long);
495 contains!(IS_TRUE, True);
496 contains!(IS_FALSE, False);
497 contains!(IS_NULL, Null);
498
499 if (value & IS_OBJECT) == IS_OBJECT {
500 return DataType::Object(None);
501 }
502
503 contains!(IS_UNDEF, Undef);
504
505 DataType::Mixed
506 }
507}
508
509impl Display for DataType {
510 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
511 match self {
512 DataType::Undef => write!(f, "Undefined"),
513 DataType::Null => write!(f, "Null"),
514 DataType::False => write!(f, "False"),
515 DataType::True => write!(f, "True"),
516 DataType::Long => write!(f, "Long"),
517 DataType::Double => write!(f, "Double"),
518 DataType::String => write!(f, "String"),
519 DataType::Array => write!(f, "Array"),
520 DataType::Object(obj) => write!(f, "{}", obj.as_deref().unwrap_or("Object")),
521 DataType::Resource => write!(f, "Resource"),
522 DataType::Reference => write!(f, "Reference"),
523 DataType::Callable => write!(f, "Callable"),
524 DataType::ConstantExpression => write!(f, "Constant Expression"),
525 DataType::Void => write!(f, "Void"),
526 DataType::Bool => write!(f, "Bool"),
527 DataType::Mixed => write!(f, "Mixed"),
528 DataType::Ptr => write!(f, "Pointer"),
529 DataType::Indirect => write!(f, "Indirect"),
530 DataType::Iterable => write!(f, "Iterable"),
531 }
532 }
533}
534
535#[cfg(test)]
536mod tests {
537 #![allow(clippy::unnecessary_fallible_conversions)]
538 use super::DataType;
539 use crate::ffi::{
540 IS_ARRAY, IS_ARRAY_EX, IS_CONSTANT_AST, IS_CONSTANT_AST_EX, IS_DOUBLE, IS_FALSE,
541 IS_INDIRECT, IS_INTERNED_STRING_EX, IS_LONG, IS_NULL, IS_OBJECT, IS_OBJECT_EX, IS_PTR,
542 IS_REFERENCE, IS_REFERENCE_EX, IS_RESOURCE, IS_RESOURCE_EX, IS_STRING, IS_STRING_EX,
543 IS_TRUE, IS_UNDEF, IS_VOID,
544 };
545 use std::convert::TryFrom;
546
547 #[test]
548 fn test_datatype() {
549 macro_rules! test {
550 ($c: ident, $t: ident) => {
551 assert_eq!(DataType::try_from($c), Ok(DataType::$t));
552 };
553 }
554
555 test!(IS_UNDEF, Undef);
556 test!(IS_NULL, Null);
557 test!(IS_FALSE, False);
558 test!(IS_TRUE, True);
559 test!(IS_LONG, Long);
560 test!(IS_DOUBLE, Double);
561 test!(IS_STRING, String);
562 test!(IS_ARRAY, Array);
563 assert_eq!(DataType::try_from(IS_OBJECT), Ok(DataType::Object(None)));
564 test!(IS_RESOURCE, Resource);
565 test!(IS_REFERENCE, Reference);
566 test!(IS_CONSTANT_AST, ConstantExpression);
567 test!(IS_INDIRECT, Indirect);
568 test!(IS_VOID, Void);
569 test!(IS_PTR, Ptr);
570
571 test!(IS_INTERNED_STRING_EX, String);
572 test!(IS_STRING_EX, String);
573 test!(IS_ARRAY_EX, Array);
574 assert_eq!(DataType::try_from(IS_OBJECT_EX), Ok(DataType::Object(None)));
575 test!(IS_RESOURCE_EX, Resource);
576 test!(IS_REFERENCE_EX, Reference);
577 test!(IS_CONSTANT_AST_EX, ConstantExpression);
578 }
579}