diff --git a/src/binary_slice.rs b/src/binary_slice.rs index 058d3a7a89..223f480025 100644 --- a/src/binary_slice.rs +++ b/src/binary_slice.rs @@ -6,16 +6,11 @@ use crate::ffi::zend_string; -use std::{convert::TryFrom, ops::Deref, slice::from_raw_parts}; +use std::{ops::Deref, slice::from_raw_parts}; -use crate::{ - convert::FromZval, - error::{Error, Result}, - flags::DataType, - types::Zval, -}; +use crate::{convert::FromZval, flags::DataType, types::Zval}; -/// Acts as a wrapper around [`&[T]`] where `T` implements [`PackSlice`]. +/// Acts as a wrapper around `&[T]` where `T` implements [`PackSlice`]. /// Primarily used for passing read-only binary data into Rust functions. #[derive(Debug)] pub struct BinarySlice<'a, T>(&'a [T]) @@ -47,28 +42,17 @@ where } } -impl FromZval<'_> for BinarySlice<'_, T> +impl<'a, T> FromZval<'a> for BinarySlice<'a, T> where T: PackSlice, { const TYPE: DataType = DataType::String; - fn from_zval(zval: &Zval) -> Option { + fn from_zval(zval: &'a Zval) -> Option { zval.binary_slice().map(BinarySlice) } } -impl TryFrom for BinarySlice<'_, T> -where - T: PackSlice, -{ - type Error = Error; - - fn try_from(value: Zval) -> Result { - Self::from_zval(&value).ok_or_else(|| Error::ZvalConversion(value.get_type())) - } -} - impl<'a, T> From> for &'a [T] where T: PackSlice, @@ -117,7 +101,7 @@ pub unsafe trait PackSlice: Clone { /// * `s` - The Zend string containing the binary data. /// /// [`pack`]: https://www.php.net/manual/en/function.pack.php - fn unpack_into<'a>(s: &zend_string) -> &'a [Self]; + fn unpack_into(s: &zend_string) -> &[Self]; } /// Implements the [`PackSlice`] trait for a given type. @@ -128,7 +112,7 @@ macro_rules! pack_slice_impl { ($t: ty, $d: expr) => { unsafe impl PackSlice for $t { - fn unpack_into<'a>(s: &zend_string) -> &'a [Self] { + fn unpack_into(s: &zend_string) -> &[Self] { let bytes = ($d / 8) as usize; let len = (s.len as usize) / bytes; let ptr = s.val.as_ptr() as *const $t; diff --git a/src/types/zval.rs b/src/types/zval.rs index f6c13c544a..aa190d2f9e 100644 --- a/src/types/zval.rs +++ b/src/types/zval.rs @@ -130,21 +130,26 @@ impl Zval { /// /// [`pack`]: https://www.php.net/manual/en/function.pack.php pub fn binary(&self) -> Option> { - if self.is_string() { - // SAFETY: Type is string therefore we are able to take a reference. - Some(T::unpack_into(unsafe { self.value.str_.as_ref() }?)) - } else { - None - } + self.zend_str().map(T::unpack_into) } - pub fn binary_slice<'a, T: PackSlice>(&self) -> Option<&'a [T]> { - if self.is_string() { - // SAFETY: Type is string therefore we are able to take a reference. - Some(T::unpack_into(unsafe { self.value.str_.as_ref() }?)) - } else { - None - } + /// Returns the value of the zval if it is a string and can be unpacked into + /// a slice of a given type. Similar to the [`unpack`](https://www.php.net/manual/en/function.unpack.php) + /// in PHP, except you can only unpack one type. + /// + /// This function is similar to [`Zval::binary`] except that a slice is + /// returned instead of a vector, meaning the contents of the string is + /// not copied. + /// + /// # Safety + /// + /// There is no way to tell if the data stored in the string is actually of + /// the given type. The results of this function can also differ from + /// platform-to-platform due to the different representation of some + /// types on different platforms. Consult the [`pack`] function + /// documentation for more details. + pub fn binary_slice(&self) -> Option<&[T]> { + self.zend_str().map(T::unpack_into) } /// Returns the value of the zval if it is a resource.