Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 72 additions & 26 deletions phper/src/values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,22 +238,12 @@ pub struct ZVal {

/// Conversion from immutable [`ZVal`].
pub trait FromZVal<'a>: Sized {
/// Converts from `ZVal`, return `None` when type mismatch.
fn as_(val: &'a ZVal) -> Option<Self> {
Self::expect(val).ok()
}

/// Converts from `ZVal`, return [`ExpectTypeError`] when type mismatch.
fn expect(val: &'a ZVal) -> crate::Result<Self>;
}

/// Conversion from mutable [`ZVal`].
pub trait FromZValMut<'a>: Sized {
/// Converts from mutable `ZVal`, return `None` when type mismatch.
fn as_(val: &'a mut ZVal) -> Option<Self> {
Self::expect(val).ok()
}

/// Converts from mutable `ZVal`, return [`ExpectTypeError`] when type
/// mismatch.
fn expect(val: &'a mut ZVal) -> crate::Result<Self>;
Expand Down Expand Up @@ -445,14 +435,6 @@ impl ZVal {
t.into()
}

/// Converts to target type by [`FromZVal`].
pub fn as_type<'a, T>(&'a self) -> Option<T>
where
T: FromZVal<'a>,
{
T::as_(self)
}

/// Converts to target type by [`FromZVal`], otherwise returns
/// [`ExpectTypeError`].
pub fn expect_type<'a, T>(&'a self) -> crate::Result<T>
Expand All @@ -462,14 +444,6 @@ impl ZVal {
T::expect(self)
}

/// Converts to target mutable type by [`FromZValMut`].
pub fn as_mut_type<'a, T>(&'a mut self) -> Option<T>
where
T: FromZValMut<'a>,
{
T::as_(self)
}

/// Converts to target mutable type by [`FromZValMut`], otherwise returns
/// [`ExpectTypeError`].
pub fn expect_mut_type<'a, T>(&'a mut self) -> crate::Result<T>
Expand Down Expand Up @@ -615,6 +589,24 @@ impl ZVal {
self.inner_expect_z_str().map(|x| &*x)
}

/// Converts to bytes if `ZVal` is string, otherwise returns
/// [`ExpectTypeError`].
pub fn expect_bytes(&self) -> crate::Result<&[u8]> {
self.expect_z_str().map(ZStr::to_bytes)
}

/// Converts to str if `ZVal` is string and valid UTF-8, otherwise returns
/// error.
pub fn expect_str(&self) -> crate::Result<&str> {
Ok(self.expect_z_str()?.to_str()?)
}

/// Converts to CStr if `ZVal` is string and contains a valid trailing nul,
/// otherwise returns error.
pub fn expect_c_str(&self) -> crate::Result<&CStr> {
Ok(self.expect_z_str()?.to_c_str()?)
}

/// Converts to mutable string if `ZVal` is string.
pub fn as_mut_z_str(&mut self) -> Option<&mut ZStr> {
self.expect_mut_z_str().ok()
Expand Down Expand Up @@ -854,6 +846,24 @@ impl<'a> FromZVal<'a> for bool {
}
}

impl<'a> FromZVal<'a> for &'a ZVal {
fn expect(val: &'a ZVal) -> crate::Result<Self> {
Ok(val)
}
}

impl<'a> FromZValMut<'a> for &'a ZVal {
fn expect(val: &'a mut ZVal) -> crate::Result<Self> {
Ok(val)
}
}

impl<'a> FromZValMut<'a> for &'a mut ZVal {
fn expect(val: &'a mut ZVal) -> crate::Result<Self> {
Ok(val)
}
}

impl<'a> FromZVal<'a> for i64 {
fn expect(val: &'a ZVal) -> crate::Result<Self> {
val.expect_long()
Expand Down Expand Up @@ -884,6 +894,42 @@ impl<'a> FromZVal<'a> for &'a ZStr {
}
}

impl<'a> FromZVal<'a> for &'a [u8] {
fn expect(val: &'a ZVal) -> crate::Result<Self> {
val.expect_bytes()
}
}

impl<'a> FromZValMut<'a> for &'a [u8] {
fn expect(val: &'a mut ZVal) -> crate::Result<Self> {
val.expect_mut_z_str().map(|s| s.to_bytes())
}
}

impl<'a> FromZVal<'a> for &'a str {
fn expect(val: &'a ZVal) -> crate::Result<Self> {
val.expect_str()
}
}

impl<'a> FromZValMut<'a> for &'a str {
fn expect(val: &'a mut ZVal) -> crate::Result<Self> {
Ok(val.expect_mut_z_str()?.to_str()?)
}
}

impl<'a> FromZVal<'a> for &'a CStr {
fn expect(val: &'a ZVal) -> crate::Result<Self> {
val.expect_c_str()
}
}

impl<'a> FromZValMut<'a> for &'a CStr {
fn expect(val: &'a mut ZVal) -> crate::Result<Self> {
Ok(val.expect_mut_z_str()?.to_c_str()?)
}
}

impl<'a> FromZValMut<'a> for &'a mut ZStr {
fn expect(val: &'a mut ZVal) -> crate::Result<Self> {
val.expect_mut_z_str()
Expand Down
33 changes: 25 additions & 8 deletions tests/integration/src/values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,22 +190,37 @@ fn integration_values_as(_: &mut [ZVal]) -> Result<(), Infallible> {

{
let val = ZVal::default();
assert_eq!(val.as_type::<()>(), Some(()));
assert_eq!(val.expect_type::<()>().ok(), Some(()));
assert!(val.expect_type::<()>().is_ok());
assert!(val.expect_type::<bool>().is_err());
}

{
let val = ZVal::from(true);
assert_eq!(val.as_type::<bool>(), Some(true));
assert_eq!(val.as_type::<i64>(), None);
assert_eq!(val.expect_type::<bool>().ok(), Some(true));
assert_eq!(val.expect_type::<i64>().ok(), None);
assert!(val.expect_type::<i64>().is_err());
}

{
let mut val = ZVal::from(100i64);
assert_eq!(val.as_type::<i64>(), Some(100));
if let Some(l) = val.as_mut_type::<&mut i64>() {
let borrowed = val.expect_type::<&ZVal>().unwrap();
assert_eq!(borrowed.expect_long().unwrap(), 100);
let borrowed_from_mut = val.expect_mut_type::<&ZVal>().unwrap();
assert_eq!(borrowed_from_mut.expect_long().unwrap(), 100);

{
let borrowed_mut = val.expect_mut_type::<&mut ZVal>().unwrap();
*borrowed_mut.expect_mut_long().unwrap() += 1;
}

assert_eq!(val.expect_long().unwrap(), 101);
}

{
let mut val = ZVal::from(100i64);
assert_eq!(val.expect_type::<i64>().ok(), Some(100));
if let Ok(l) = val.expect_mut_type::<&mut i64>() {
*l += 100;
}
assert_eq!(val.expect_type::<i64>().unwrap(), 200);
Expand All @@ -214,8 +229,8 @@ fn integration_values_as(_: &mut [ZVal]) -> Result<(), Infallible> {

{
let mut val = ZVal::from(100f64);
assert_eq!(val.as_type::<f64>(), Some(100.));
if let Some(d) = val.as_mut_type::<&mut f64>() {
assert_eq!(val.expect_type::<f64>().ok(), Some(100.));
if let Ok(d) = val.expect_mut_type::<&mut f64>() {
*d += 100.;
}
assert_eq!(val.expect_type::<f64>().unwrap(), 200.);
Expand All @@ -225,7 +240,9 @@ fn integration_values_as(_: &mut [ZVal]) -> Result<(), Infallible> {
{
let val = ZVal::from("foo");
assert_eq!(
val.as_type::<&phper::strings::ZStr>().unwrap().to_bytes(),
val.expect_type::<&phper::strings::ZStr>()
.unwrap()
.to_bytes(),
b"foo"
);
assert!(val.expect_type::<&phper::arrays::ZArr>().is_err());
Expand Down
Loading