Skip to content

Commit f11451f

Browse files
Replace unit errors with error enum (#29)
* WIP: Replacing unit type errors with actual error * Tidied up errors
1 parent 439f2ae commit f11451f

File tree

6 files changed

+128
-46
lines changed

6 files changed

+128
-46
lines changed

src/errors.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use std::{error::Error as ErrorTrait, fmt::Display};
2+
3+
use crate::php::enums::DataType;
4+
5+
/// The main result type which is passed by the library.
6+
pub type Result<T> = std::result::Result<T, Error>;
7+
8+
/// The main error type which is passed by the library inside the custom
9+
/// [`Result`] type.
10+
#[derive(Debug, Clone)]
11+
#[non_exhaustive]
12+
pub enum Error {
13+
/// An incorrect number of arguments was given to a PHP function.
14+
///
15+
/// The type carries two integers - the first representing the minimum
16+
/// number of arguments expected, and the second representing the number of
17+
/// arguments that were received.
18+
IncorrectArguments(u32, u32),
19+
20+
/// There was an error converting a Zval into a primitive type.
21+
///
22+
/// The type carries the data type of the Zval.
23+
ZvalConversion(DataType),
24+
25+
/// The type of the Zval is unknown.
26+
///
27+
/// The type carries the integer representation of the type of Zval.
28+
UnknownDatatype(u8),
29+
}
30+
31+
impl Display for Error {
32+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33+
match self {
34+
Error::IncorrectArguments(n, expected) => write!(
35+
f,
36+
"Expected at least {} arguments, got {} arguments.",
37+
expected, n
38+
),
39+
Error::ZvalConversion(ty) => write!(
40+
f,
41+
"Could not convert Zval from type {} into primitive type.",
42+
ty
43+
),
44+
Error::UnknownDatatype(dt) => write!(f, "Unknown datatype {}.", dt),
45+
}
46+
}
47+
}
48+
49+
impl ErrorTrait for Error {}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#[macro_use]
66
pub mod macros;
77
pub mod bindings;
8+
pub mod errors;
89
pub mod functions;
910
pub mod php;
1011

src/php/args.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@ use std::convert::{TryFrom, TryInto};
44

55
use super::{enums::DataType, execution_data::ExecutionData, types::zval::Zval};
66

7-
use crate::bindings::{
8-
_zend_expected_type, _zend_expected_type_Z_EXPECTED_ARRAY, _zend_expected_type_Z_EXPECTED_BOOL,
9-
_zend_expected_type_Z_EXPECTED_DOUBLE, _zend_expected_type_Z_EXPECTED_LONG,
10-
_zend_expected_type_Z_EXPECTED_OBJECT, _zend_expected_type_Z_EXPECTED_RESOURCE,
11-
_zend_expected_type_Z_EXPECTED_STRING, zend_internal_arg_info,
12-
zend_wrong_parameters_count_error,
7+
use crate::{
8+
bindings::{
9+
_zend_expected_type, _zend_expected_type_Z_EXPECTED_ARRAY,
10+
_zend_expected_type_Z_EXPECTED_BOOL, _zend_expected_type_Z_EXPECTED_DOUBLE,
11+
_zend_expected_type_Z_EXPECTED_LONG, _zend_expected_type_Z_EXPECTED_OBJECT,
12+
_zend_expected_type_Z_EXPECTED_RESOURCE, _zend_expected_type_Z_EXPECTED_STRING,
13+
zend_internal_arg_info, zend_wrong_parameters_count_error,
14+
},
15+
errors::{Error, Result},
1316
};
1417

1518
/// Represents an argument to a function.
@@ -180,7 +183,7 @@ impl<'a, 'b> ArgParser<'a, 'b> {
180183
/// * `Err(String)` - There were too many or too little arguments
181184
/// passed to the function. The user has already been notified so you
182185
/// can discard and return from the function if an `Err` is received.
183-
pub fn parse(mut self) -> Result<(), String> {
186+
pub fn parse(mut self) -> Result<()> {
184187
let execute_data = unsafe { self.execute_data.as_ref() }.unwrap();
185188
let num_args = unsafe { execute_data.This.u2.num_args };
186189
let max_num_args = self.args.len() as u32;
@@ -192,10 +195,7 @@ impl<'a, 'b> ArgParser<'a, 'b> {
192195
if num_args < min_num_args || num_args > max_num_args {
193196
unsafe { zend_wrong_parameters_count_error(min_num_args, max_num_args) };
194197

195-
return Err(format!(
196-
"Expected at least {} arguments, got {} arguments.",
197-
min_num_args, num_args,
198-
));
198+
return Err(Error::IncorrectArguments(num_args, min_num_args));
199199
}
200200

201201
for (i, arg) in self.args.iter_mut().enumerate() {

src/php/enums.rs

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
//! Wrapper for enums introduced in C.
22
3-
use crate::bindings::{
4-
IS_ARRAY, IS_CALLABLE, IS_CONSTANT_AST, IS_DOUBLE, IS_FALSE, IS_LONG, IS_NULL, IS_OBJECT,
5-
IS_REFERENCE, IS_RESOURCE, IS_STRING, IS_TRUE, IS_UNDEF, IS_VOID,
6-
};
3+
use std::{convert::TryFrom, fmt::Display};
74

8-
use super::types::long::ZendLong;
5+
use crate::{
6+
bindings::{
7+
IS_ARRAY, IS_CALLABLE, IS_CONSTANT_AST, IS_DOUBLE, IS_FALSE, IS_LONG, IS_NULL, IS_OBJECT,
8+
IS_REFERENCE, IS_RESOURCE, IS_STRING, IS_TRUE, IS_UNDEF, IS_VOID,
9+
},
10+
errors::{Error, Result},
11+
};
912

1013
/// Valid data types for PHP.
1114
#[derive(Clone, Copy, Debug)]
@@ -29,30 +32,48 @@ pub enum DataType {
2932
Void = IS_VOID,
3033
}
3134

32-
impl From<ZendLong> for DataType {
33-
fn from(_: ZendLong) -> Self {
34-
Self::Long
35-
}
36-
}
35+
impl TryFrom<u8> for DataType {
36+
type Error = Error;
3737

38-
impl From<bool> for DataType {
39-
fn from(x: bool) -> Self {
40-
if x {
41-
Self::True
42-
} else {
43-
Self::False
44-
}
45-
}
46-
}
38+
fn try_from(value: u8) -> Result<Self> {
39+
match value as u32 {
40+
IS_UNDEF => Ok(DataType::Undef),
41+
IS_NULL => Ok(DataType::Null),
42+
IS_FALSE => Ok(DataType::False),
43+
IS_TRUE => Ok(DataType::True),
44+
IS_LONG => Ok(DataType::Long),
45+
IS_DOUBLE => Ok(DataType::Double),
46+
IS_STRING => Ok(DataType::String),
47+
IS_ARRAY => Ok(DataType::Array),
48+
IS_OBJECT => Ok(DataType::Object),
49+
IS_RESOURCE => Ok(DataType::Resource),
50+
IS_REFERENCE => Ok(DataType::Reference),
51+
IS_CALLABLE => Ok(DataType::Callable),
52+
IS_CONSTANT_AST => Ok(DataType::ConstantExpression),
53+
IS_VOID => Ok(DataType::Void),
4754

48-
impl From<f64> for DataType {
49-
fn from(_: f64) -> Self {
50-
Self::Double
55+
_ => Err(Error::UnknownDatatype(value)),
56+
}
5157
}
5258
}
5359

54-
impl From<String> for DataType {
55-
fn from(_: String) -> Self {
56-
Self::String
60+
impl Display for DataType {
61+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62+
match self {
63+
DataType::Undef => write!(f, "Undefined"),
64+
DataType::Null => write!(f, "Null"),
65+
DataType::False => write!(f, "False"),
66+
DataType::True => write!(f, "True"),
67+
DataType::Long => write!(f, "Long"),
68+
DataType::Double => write!(f, "Double"),
69+
DataType::String => write!(f, "String"),
70+
DataType::Array => write!(f, "Array"),
71+
DataType::Object => write!(f, "Object"),
72+
DataType::Resource => write!(f, "Resource"),
73+
DataType::Reference => write!(f, "Reference"),
74+
DataType::Callable => write!(f, "Callable"),
75+
DataType::ConstantExpression => write!(f, "Constant Expression"),
76+
DataType::Void => write!(f, "Void"),
77+
}
5778
}
5879
}

src/php/types/array.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ impl ZendHashTable {
135135
/// # Returns
136136
///
137137
/// * `Ok(())` - Key was successfully removed.
138-
/// * `Err(())` - No key was removed, did not exist.
138+
/// * `None` - No key was removed, did not exist.
139139
pub fn remove_index(&self, key: u64) -> Option<()> {
140140
let result = unsafe { zend_hash_index_del(self.ptr, key) };
141141

@@ -191,7 +191,7 @@ impl ZendHashTable {
191191
///
192192
/// # Returns
193193
///
194-
/// * `Some(Zval)` - The existing value in the hash table that was overriden.
194+
/// * `Some(&Zval)` - The existing value in the hash table that was overriden.
195195
/// * `None` - The element was inserted.
196196
pub fn insert_at_index<V>(&mut self, key: u64, val: V) -> Option<&Zval>
197197
where

src/php/types/zval.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
use core::slice;
55
use std::{convert::TryFrom, ptr};
66

7-
use crate::bindings::{
8-
_call_user_function_impl, _zval_struct__bindgen_ty_1, _zval_struct__bindgen_ty_2,
9-
ext_php_rs_zend_string_release, zend_is_callable, zend_object, zend_resource, zend_value, zval,
10-
IS_INTERNED_STRING_EX, IS_STRING_EX,
7+
use crate::{
8+
bindings::{
9+
_call_user_function_impl, _zval_struct__bindgen_ty_1, _zval_struct__bindgen_ty_2,
10+
ext_php_rs_zend_string_release, zend_is_callable, zend_object, zend_resource, zend_value,
11+
zval, IS_INTERNED_STRING_EX, IS_STRING_EX,
12+
},
13+
errors::{Error, Result},
1114
};
1215

1316
use crate::php::{
@@ -178,6 +181,11 @@ impl<'a> Zval {
178181
}
179182
}
180183

184+
/// Returns the type of the Zval.
185+
pub fn get_type(&self) -> Result<DataType> {
186+
DataType::try_from(unsafe { self.u1.v.type_ })
187+
}
188+
181189
/// Returns true if the zval is a long, false otherwise.
182190
pub fn is_long(&self) -> bool {
183191
unsafe { self.u1.v.type_ == DataType::Long as u8 }
@@ -361,11 +369,14 @@ impl<'a> Zval {
361369
macro_rules! try_from_zval {
362370
($type: ty, $fn: ident) => {
363371
impl TryFrom<&Zval> for $type {
364-
type Error = ();
365-
fn try_from(value: &Zval) -> Result<Self, Self::Error> {
372+
type Error = Error;
373+
fn try_from(value: &Zval) -> Result<Self> {
366374
match value.$fn() {
367-
Some(v) => <$type>::try_from(v).map_err(|_| ()),
368-
_ => Err(()),
375+
Some(v) => match <$type>::try_from(v) {
376+
Ok(v) => Ok(v),
377+
Err(_) => Err(Error::ZvalConversion(value.get_type()?)),
378+
},
379+
_ => Err(Error::ZvalConversion(value.get_type()?)),
369380
}
370381
}
371382
}

0 commit comments

Comments
 (0)