Skip to content

Commit 8d2ad7d

Browse files
fix binary slice lifetimes (#181)
1 parent 4ea01f8 commit 8d2ad7d

File tree

2 files changed

+25
-36
lines changed

2 files changed

+25
-36
lines changed

src/binary_slice.rs

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,11 @@
66
77
use crate::ffi::zend_string;
88

9-
use std::{convert::TryFrom, ops::Deref, slice::from_raw_parts};
9+
use std::{ops::Deref, slice::from_raw_parts};
1010

11-
use crate::{
12-
convert::FromZval,
13-
error::{Error, Result},
14-
flags::DataType,
15-
types::Zval,
16-
};
11+
use crate::{convert::FromZval, flags::DataType, types::Zval};
1712

18-
/// Acts as a wrapper around [`&[T]`] where `T` implements [`PackSlice`].
13+
/// Acts as a wrapper around `&[T]` where `T` implements [`PackSlice`].
1914
/// Primarily used for passing read-only binary data into Rust functions.
2015
#[derive(Debug)]
2116
pub struct BinarySlice<'a, T>(&'a [T])
@@ -47,28 +42,17 @@ where
4742
}
4843
}
4944

50-
impl<T> FromZval<'_> for BinarySlice<'_, T>
45+
impl<'a, T> FromZval<'a> for BinarySlice<'a, T>
5146
where
5247
T: PackSlice,
5348
{
5449
const TYPE: DataType = DataType::String;
5550

56-
fn from_zval(zval: &Zval) -> Option<Self> {
51+
fn from_zval(zval: &'a Zval) -> Option<Self> {
5752
zval.binary_slice().map(BinarySlice)
5853
}
5954
}
6055

61-
impl<T> TryFrom<Zval> for BinarySlice<'_, T>
62-
where
63-
T: PackSlice,
64-
{
65-
type Error = Error;
66-
67-
fn try_from(value: Zval) -> Result<Self> {
68-
Self::from_zval(&value).ok_or_else(|| Error::ZvalConversion(value.get_type()))
69-
}
70-
}
71-
7256
impl<'a, T> From<BinarySlice<'a, T>> for &'a [T]
7357
where
7458
T: PackSlice,
@@ -117,7 +101,7 @@ pub unsafe trait PackSlice: Clone {
117101
/// * `s` - The Zend string containing the binary data.
118102
///
119103
/// [`pack`]: https://www.php.net/manual/en/function.pack.php
120-
fn unpack_into<'a>(s: &zend_string) -> &'a [Self];
104+
fn unpack_into(s: &zend_string) -> &[Self];
121105
}
122106

123107
/// Implements the [`PackSlice`] trait for a given type.
@@ -128,7 +112,7 @@ macro_rules! pack_slice_impl {
128112

129113
($t: ty, $d: expr) => {
130114
unsafe impl PackSlice for $t {
131-
fn unpack_into<'a>(s: &zend_string) -> &'a [Self] {
115+
fn unpack_into(s: &zend_string) -> &[Self] {
132116
let bytes = ($d / 8) as usize;
133117
let len = (s.len as usize) / bytes;
134118
let ptr = s.val.as_ptr() as *const $t;

src/types/zval.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -130,21 +130,26 @@ impl Zval {
130130
///
131131
/// [`pack`]: https://www.php.net/manual/en/function.pack.php
132132
pub fn binary<T: Pack>(&self) -> Option<Vec<T>> {
133-
if self.is_string() {
134-
// SAFETY: Type is string therefore we are able to take a reference.
135-
Some(T::unpack_into(unsafe { self.value.str_.as_ref() }?))
136-
} else {
137-
None
138-
}
133+
self.zend_str().map(T::unpack_into)
139134
}
140135

141-
pub fn binary_slice<'a, T: PackSlice>(&self) -> Option<&'a [T]> {
142-
if self.is_string() {
143-
// SAFETY: Type is string therefore we are able to take a reference.
144-
Some(T::unpack_into(unsafe { self.value.str_.as_ref() }?))
145-
} else {
146-
None
147-
}
136+
/// Returns the value of the zval if it is a string and can be unpacked into
137+
/// a slice of a given type. Similar to the [`unpack`](https://www.php.net/manual/en/function.unpack.php)
138+
/// in PHP, except you can only unpack one type.
139+
///
140+
/// This function is similar to [`Zval::binary`] except that a slice is
141+
/// returned instead of a vector, meaning the contents of the string is
142+
/// not copied.
143+
///
144+
/// # Safety
145+
///
146+
/// There is no way to tell if the data stored in the string is actually of
147+
/// the given type. The results of this function can also differ from
148+
/// platform-to-platform due to the different representation of some
149+
/// types on different platforms. Consult the [`pack`] function
150+
/// documentation for more details.
151+
pub fn binary_slice<T: PackSlice>(&self) -> Option<&[T]> {
152+
self.zend_str().map(T::unpack_into)
148153
}
149154

150155
/// Returns the value of the zval if it is a resource.

0 commit comments

Comments
 (0)