diff --git a/phper/src/values.rs b/phper/src/values.rs index 810eb95..2861c91 100644 --- a/phper/src/values.rs +++ b/phper/src/values.rs @@ -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::expect(val).ok() - } - /// Converts from `ZVal`, return [`ExpectTypeError`] when type mismatch. fn expect(val: &'a ZVal) -> crate::Result; } /// 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::expect(val).ok() - } - /// Converts from mutable `ZVal`, return [`ExpectTypeError`] when type /// mismatch. fn expect(val: &'a mut ZVal) -> crate::Result; @@ -445,14 +435,6 @@ impl ZVal { t.into() } - /// Converts to target type by [`FromZVal`]. - pub fn as_type<'a, T>(&'a self) -> Option - 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 @@ -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 - 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 @@ -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() @@ -854,6 +846,24 @@ impl<'a> FromZVal<'a> for bool { } } +impl<'a> FromZVal<'a> for &'a ZVal { + fn expect(val: &'a ZVal) -> crate::Result { + Ok(val) + } +} + +impl<'a> FromZValMut<'a> for &'a ZVal { + fn expect(val: &'a mut ZVal) -> crate::Result { + Ok(val) + } +} + +impl<'a> FromZValMut<'a> for &'a mut ZVal { + fn expect(val: &'a mut ZVal) -> crate::Result { + Ok(val) + } +} + impl<'a> FromZVal<'a> for i64 { fn expect(val: &'a ZVal) -> crate::Result { val.expect_long() @@ -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 { + val.expect_bytes() + } +} + +impl<'a> FromZValMut<'a> for &'a [u8] { + fn expect(val: &'a mut ZVal) -> crate::Result { + val.expect_mut_z_str().map(|s| s.to_bytes()) + } +} + +impl<'a> FromZVal<'a> for &'a str { + fn expect(val: &'a ZVal) -> crate::Result { + val.expect_str() + } +} + +impl<'a> FromZValMut<'a> for &'a str { + fn expect(val: &'a mut ZVal) -> crate::Result { + Ok(val.expect_mut_z_str()?.to_str()?) + } +} + +impl<'a> FromZVal<'a> for &'a CStr { + fn expect(val: &'a ZVal) -> crate::Result { + val.expect_c_str() + } +} + +impl<'a> FromZValMut<'a> for &'a CStr { + fn expect(val: &'a mut ZVal) -> crate::Result { + 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 { val.expect_mut_z_str() diff --git a/tests/integration/src/values.rs b/tests/integration/src/values.rs index 164a79e..c4699a6 100644 --- a/tests/integration/src/values.rs +++ b/tests/integration/src/values.rs @@ -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::().is_err()); } { let val = ZVal::from(true); - assert_eq!(val.as_type::(), Some(true)); - assert_eq!(val.as_type::(), None); + assert_eq!(val.expect_type::().ok(), Some(true)); + assert_eq!(val.expect_type::().ok(), None); assert!(val.expect_type::().is_err()); } { let mut val = ZVal::from(100i64); - assert_eq!(val.as_type::(), 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::().ok(), Some(100)); + if let Ok(l) = val.expect_mut_type::<&mut i64>() { *l += 100; } assert_eq!(val.expect_type::().unwrap(), 200); @@ -214,8 +229,8 @@ fn integration_values_as(_: &mut [ZVal]) -> Result<(), Infallible> { { let mut val = ZVal::from(100f64); - assert_eq!(val.as_type::(), Some(100.)); - if let Some(d) = val.as_mut_type::<&mut f64>() { + assert_eq!(val.expect_type::().ok(), Some(100.)); + if let Ok(d) = val.expect_mut_type::<&mut f64>() { *d += 100.; } assert_eq!(val.expect_type::().unwrap(), 200.); @@ -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());