1use std::{
4 error::Error as ErrorTrait,
5 ffi::{CString, NulError},
6 fmt::Display,
7};
8
9use crate::{
10 boxed::ZBox,
11 exception::PhpException,
12 ffi::php_error_docref,
13 flags::{ClassFlags, DataType, ErrorType, ZvalTypeFlags},
14 types::ZendObject,
15};
16
17pub type Result<T, E = Error> = std::result::Result<T, E>;
19
20#[derive(Debug)]
23#[non_exhaustive]
24pub enum Error {
25 IncorrectArguments(usize, usize),
31 ZvalConversion(DataType),
35 UnknownDatatype(u32),
39 InvalidTypeToDatatype(ZvalTypeFlags),
45 InvalidScope,
48 InvalidPointer,
51 InvalidProperty,
53 InvalidCString,
56 InvalidUtf8,
58 Callable,
60 Object,
62 InvalidException(ClassFlags),
64 IntegerOverflow,
66 Exception(ZBox<ZendObject>),
68 StreamWrapperRegistrationFailure,
70 StreamWrapperUnregistrationFailure,
72}
73
74impl Display for Error {
75 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 match self {
77 Error::IncorrectArguments(n, expected) => write!(
78 f,
79 "Expected at least {expected} arguments, got {n} arguments."
80 ),
81 Error::ZvalConversion(ty) => write!(
82 f,
83 "Could not convert Zval from type {ty} into primitive type."
84 ),
85 Error::UnknownDatatype(dt) => write!(f, "Unknown datatype {dt}."),
86 Error::InvalidTypeToDatatype(dt) => {
87 write!(f, "Type flags did not contain a datatype: {dt:?}")
88 }
89 Error::InvalidScope => write!(f, "Invalid scope."),
90 Error::InvalidPointer => write!(f, "Invalid pointer."),
91 Error::InvalidProperty => write!(f, "Property does not exist on object."),
92 Error::InvalidCString => write!(
93 f,
94 "String given contains NUL-bytes which cannot be present in a C string."
95 ),
96 Error::InvalidUtf8 => write!(f, "Invalid Utf8 byte sequence."),
97 Error::Callable => write!(f, "Could not call given function."),
98 Error::Object => write!(f, "An object was expected."),
99 Error::InvalidException(flags) => {
100 write!(f, "Invalid exception type was thrown: {flags:?}")
101 }
102 Error::IntegerOverflow => {
103 write!(f, "Converting integer arguments resulted in an overflow.")
104 }
105 Error::Exception(e) => write!(f, "Exception was thrown: {e:?}"),
106 Error::StreamWrapperRegistrationFailure => {
107 write!(f, "A failure occurred while registering the stream wrapper")
108 }
109 Error::StreamWrapperUnregistrationFailure => {
110 write!(
111 f,
112 "A failure occurred while unregistering the stream wrapper"
113 )
114 }
115 }
116 }
117}
118
119impl ErrorTrait for Error {}
120
121impl From<NulError> for Error {
122 fn from(_: NulError) -> Self {
123 Self::InvalidCString
124 }
125}
126
127impl From<Error> for PhpException {
128 fn from(err: Error) -> Self {
129 Self::default(err.to_string())
130 }
131}
132
133pub fn php_error(type_: ErrorType, message: &str) {
137 let c_string = match CString::new(message) {
138 Ok(string) => string,
139 Err(_) => {
140 return;
141 }
142 };
143
144 unsafe { php_error_docref(std::ptr::null(), type_.bits() as _, c_string.as_ptr()) }
145}