• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

davidcole1340 / ext-php-rs / 14501981872

16 Apr 2025 08:30PM UTC coverage: 14.129% (+0.7%) from 13.479%
14501981872

push

github

web-flow
style(clippy): apply pedantic rules

Refs: #418

41 of 345 new or added lines in 46 files covered. (11.88%)

48 existing lines in 25 files now uncovered.

553 of 3914 relevant lines covered (14.13%)

1.3 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

6.25
/src/convert.rs
1
//! Traits used to convert between Zend/PHP and Rust types.
2

3
use crate::{
4
    boxed::ZBox,
5
    error::Result,
6
    exception::PhpException,
7
    flags::DataType,
8
    types::{ZendObject, Zval},
9
};
10

11
/// Allows zvals to be converted into Rust types in a fallible way. Reciprocal
12
/// of the [`IntoZval`] trait.
13
pub trait FromZval<'a>: Sized {
14
    /// The corresponding type of the implemented value in PHP.
15
    const TYPE: DataType;
16

17
    /// Attempts to retrieve an instance of `Self` from a reference to a
18
    /// [`Zval`].
19
    ///
20
    /// # Parameters
21
    ///
22
    /// * `zval` - Zval to get value from.
23
    fn from_zval(zval: &'a Zval) -> Option<Self>;
24
}
25

26
impl<'a, T> FromZval<'a> for Option<T>
27
where
28
    T: FromZval<'a>,
29
{
30
    const TYPE: DataType = T::TYPE;
31

32
    fn from_zval(zval: &'a Zval) -> Option<Self> {
×
33
        Some(T::from_zval(zval))
×
34
    }
35
}
36

37
/// Allows mutable zvals to be converted into Rust types in a fallible way.
38
///
39
/// If `Self` does not require the zval to be mutable to be extracted, you
40
/// should implement [`FromZval`] instead, as this trait is generically
41
/// implemented for any type that implements [`FromZval`].
42
pub trait FromZvalMut<'a>: Sized {
43
    /// The corresponding type of the implemented value in PHP.
44
    const TYPE: DataType;
45

46
    /// Attempts to retrieve an instance of `Self` from a mutable reference to a
47
    /// [`Zval`].
48
    ///
49
    /// # Parameters
50
    ///
51
    /// * `zval` - Zval to get value from.
52
    fn from_zval_mut(zval: &'a mut Zval) -> Option<Self>;
53
}
54

55
impl<'a, T> FromZvalMut<'a> for T
56
where
57
    T: FromZval<'a>,
58
{
59
    const TYPE: DataType = <T as FromZval>::TYPE;
60

61
    #[inline]
62
    fn from_zval_mut(zval: &'a mut Zval) -> Option<Self> {
2✔
63
        Self::from_zval(zval)
2✔
64
    }
65
}
66

67
/// `FromZendObject` is implemented by types which can be extracted from a Zend
68
/// object.
69
///
70
/// Normal usage is through the helper method `ZendObject::extract`:
71
///
72
/// ```rust,ignore
73
/// let obj: ZendObject = ...;
74
/// let repr: String = obj.extract();
75
/// let props: HashMap = obj.extract();
76
/// ```
77
///
78
/// Should be functionally equivalent to casting an object to another compatible
79
/// type.
80
pub trait FromZendObject<'a>: Sized {
81
    /// Extracts `Self` from the source `ZendObject`.
82
    ///
83
    /// # Errors
84
    ///
85
    /// If the conversion fails, an [`Error`] is returned.
86
    ///
87
    /// [`Error`]: crate::error::Error
88
    // TODO: Expand on error information
89
    fn from_zend_object(obj: &'a ZendObject) -> Result<Self>;
90
}
91

92
/// Implemented on types which can be extracted from a mutable zend object.
93
///
94
/// If `Self` does not require the object to be mutable, it should implement
95
/// [`FromZendObject`] instead, as this trait is generically implemented for
96
/// any types that also implement [`FromZendObject`].
97
pub trait FromZendObjectMut<'a>: Sized {
98
    /// Extracts `Self` from the source `ZendObject`.
99
    ///
100
    /// # Errors
101
    ///
102
    /// If the conversion fails, an [`Error`] is returned.
103
    ///
104
    /// [`Error`]: crate::error::Error
105
    // TODO: Expand on error information
106
    fn from_zend_object_mut(obj: &'a mut ZendObject) -> Result<Self>;
107
}
108

109
impl<'a, T> FromZendObjectMut<'a> for T
110
where
111
    T: FromZendObject<'a>,
112
{
113
    #[inline]
114
    fn from_zend_object_mut(obj: &'a mut ZendObject) -> Result<Self> {
×
115
        Self::from_zend_object(obj)
×
116
    }
117
}
118

119
/// Implemented on types which can be converted into a Zend object. It is up to
120
/// the implementation to determine the type of object which is produced.
121
pub trait IntoZendObject {
122
    /// Attempts to convert `self` into a Zend object.
123
    ///
124
    /// # Errors
125
    ///
126
    /// If the conversion fails, an [`Error`] is returned.
127
    ///
128
    /// [`Error`]: crate::error::Error
129
    // TODO: Expand on error information
130
    fn into_zend_object(self) -> Result<ZBox<ZendObject>>;
131
}
132

133
/// Provides implementations for converting Rust primitive types into PHP zvals.
134
/// Alternative to the built-in Rust [`From`] and [`TryFrom`] implementations,
135
/// allowing the caller to specify whether the Zval contents will persist
136
/// between requests.
137
///
138
/// [`TryFrom`]: std::convert::TryFrom
139
pub trait IntoZval: Sized {
140
    /// The corresponding type of the implemented value in PHP.
141
    const TYPE: DataType;
142

143
    /// Whether converting into a [`Zval`] may result in null.
144
    const NULLABLE: bool;
145

146
    /// Converts a Rust primitive type into a Zval. Returns a result containing
147
    /// the Zval if successful.
148
    ///
149
    /// # Parameters
150
    ///
151
    /// * `persistent` - Whether the contents of the Zval will persist between
152
    ///   requests.
153
    ///
154
    /// # Errors
155
    ///
156
    /// If the conversion fails, an [`Error`] is returned.
157
    ///
158
    /// [`Error`]: crate::error::Error
159
    // TODO: Expand on error information
160
    fn into_zval(self, persistent: bool) -> Result<Zval> {
×
161
        let mut zval = Zval::new();
×
162
        self.set_zval(&mut zval, persistent)?;
×
163
        Ok(zval)
×
164
    }
165

166
    /// Sets the content of a pre-existing zval. Returns a result containing
167
    /// nothing if setting the content was successful.
168
    ///
169
    /// # Parameters
170
    ///
171
    /// * `zv` - The Zval to set the content of.
172
    /// * `persistent` - Whether the contents of the Zval will persist between
173
    ///   requests.
174
    ///
175
    /// # Errors
176
    ///
177
    /// If setting the content fails, an [`Error`] is returned.
178
    ///
179
    /// [`Error`]: crate::error::Error
180
    // TODO: Expand on error information
181
    fn set_zval(self, zv: &mut Zval, persistent: bool) -> Result<()>;
182
}
183

184
impl IntoZval for () {
185
    const TYPE: DataType = DataType::Void;
186
    const NULLABLE: bool = true;
187

188
    #[inline]
189
    fn set_zval(self, zv: &mut Zval, _: bool) -> Result<()> {
×
190
        zv.set_null();
×
191
        Ok(())
×
192
    }
193
}
194

195
impl<T> IntoZval for Option<T>
196
where
197
    T: IntoZval,
198
{
199
    const TYPE: DataType = T::TYPE;
200
    const NULLABLE: bool = true;
201

202
    #[inline]
203
    fn set_zval(self, zv: &mut Zval, persistent: bool) -> Result<()> {
×
NEW
204
        if let Some(val) = self {
×
NEW
205
            val.set_zval(zv, persistent)
×
206
        } else {
NEW
207
            zv.set_null();
×
NEW
208
            Ok(())
×
209
        }
210
    }
211
}
212

213
impl<T, E> IntoZval for std::result::Result<T, E>
214
where
215
    T: IntoZval,
216
    E: Into<PhpException>,
217
{
218
    const TYPE: DataType = T::TYPE;
219
    const NULLABLE: bool = T::NULLABLE;
220

221
    fn set_zval(self, zv: &mut Zval, persistent: bool) -> Result<()> {
×
222
        match self {
×
223
            Ok(val) => val.set_zval(zv, persistent),
×
224
            Err(e) => {
×
225
                let ex: PhpException = e.into();
×
226
                ex.throw()
×
227
            }
228
        }
229
    }
230
}
231

232
/// An object-safe version of the [`IntoZval`] trait.
233
///
234
/// This trait is automatically implemented on any type that implements both
235
/// [`IntoZval`] and [`Clone`]. You avoid implementing this trait directly,
236
/// rather implement these two other traits.
237
pub trait IntoZvalDyn {
238
    /// Converts a Rust primitive type into a Zval. Returns a result containing
239
    /// the Zval if successful. `self` is cloned before being converted into
240
    /// a zval.
241
    ///
242
    /// # Parameters
243
    ///
244
    /// * `persistent` - Whether the contents of the Zval will persist between
245
    ///   requests.
246
    ///
247
    /// # Errors
248
    ///
249
    /// If the conversion fails, an [`Error`] is returned.
250
    ///
251
    /// [`Error`]: crate::error::Error
252
    fn as_zval(&self, persistent: bool) -> Result<Zval>;
253

254
    /// Returns the PHP type of the type.
255
    fn get_type(&self) -> DataType;
256
}
257

258
impl<T: IntoZval + Clone> IntoZvalDyn for T {
259
    fn as_zval(&self, persistent: bool) -> Result<Zval> {
×
260
        self.clone().into_zval(persistent)
×
261
    }
262

263
    fn get_type(&self) -> DataType {
×
264
        Self::TYPE
×
265
    }
266
}
267

268
impl IntoZvalDyn for Zval {
269
    fn as_zval(&self, _persistent: bool) -> Result<Zval> {
×
270
        Ok(self.shallow_clone())
×
271
    }
272

273
    fn get_type(&self) -> DataType {
×
274
        self.get_type()
×
275
    }
276
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc