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

davidcole1340 / ext-php-rs / 16392365915

19 Jul 2025 08:16PM UTC coverage: 24.784%. Remained the same
16392365915

Pull #529

github

ptondereau
refactor(array): split array.rs types into smaller files
Pull Request #529: refactor(array): split array.rs types into smaller files

56 of 170 new or added lines in 3 files covered. (32.94%)

976 of 3938 relevant lines covered (24.78%)

5.6 hits per line

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

32.89
/src/types/array/conversions.rs
1
use std::{collections::HashMap, convert::TryFrom, iter::FromIterator};
2

3
use crate::{
4
    boxed::ZBox,
5
    convert::{FromZval, IntoZval},
6
    error::{Error, Result},
7
    flags::DataType,
8
    types::Zval,
9
};
10

11
use super::{ArrayKey, ZendHashTable};
12

13
///////////////////////////////////////////
14
// HashMap
15
///////////////////////////////////////////
16

17
// TODO: Generalize hasher
18
#[allow(clippy::implicit_hasher)]
19
impl<'a, V> TryFrom<&'a ZendHashTable> for HashMap<String, V>
20
where
21
    V: FromZval<'a>,
22
{
23
    type Error = Error;
24

NEW
25
    fn try_from(value: &'a ZendHashTable) -> Result<Self> {
×
NEW
26
        let mut hm = HashMap::with_capacity(value.len());
×
27

NEW
28
        for (key, val) in value {
×
NEW
29
            hm.insert(
×
NEW
30
                key.to_string(),
×
NEW
31
                V::from_zval(val).ok_or_else(|| Error::ZvalConversion(val.get_type()))?,
×
32
            );
33
        }
34

NEW
35
        Ok(hm)
×
36
    }
37
}
38

39
impl<K, V> TryFrom<HashMap<K, V>> for ZBox<ZendHashTable>
40
where
41
    K: AsRef<str>,
42
    V: IntoZval,
43
{
44
    type Error = Error;
45

NEW
46
    fn try_from(value: HashMap<K, V>) -> Result<Self> {
×
47
        let mut ht = ZendHashTable::with_capacity(
NEW
48
            value.len().try_into().map_err(|_| Error::IntegerOverflow)?,
×
49
        );
50

NEW
51
        for (k, v) in value {
×
NEW
52
            ht.insert(k.as_ref(), v)?;
×
53
        }
54

NEW
55
        Ok(ht)
×
56
    }
57
}
58

59
impl<'a, K, V> TryFrom<&'a ZendHashTable> for Vec<(K, V)>
60
where
61
    K: TryFrom<ArrayKey<'a>, Error = Error>,
62
    V: FromZval<'a>,
63
{
64
    type Error = Error;
65

66
    fn try_from(value: &'a ZendHashTable) -> Result<Self> {
7✔
67
        let mut vec = Vec::with_capacity(value.len());
28✔
68

69
        for (key, val) in value {
46✔
70
            vec.push((
25✔
71
                key.try_into()?,
31✔
72
                V::from_zval(val).ok_or_else(|| Error::ZvalConversion(val.get_type()))?,
11✔
73
            ));
74
        }
75

76
        Ok(vec)
4✔
77
    }
78
}
79

80
impl<'a, V> TryFrom<&'a ZendHashTable> for Vec<(ArrayKey<'a>, V)>
81
where
82
    V: FromZval<'a>,
83
{
84
    type Error = Error;
85

86
    fn try_from(value: &'a ZendHashTable) -> Result<Self> {
2✔
87
        let mut vec = Vec::with_capacity(value.len());
8✔
88

89
        for (key, val) in value {
20✔
90
            vec.push((
12✔
91
                key,
6✔
92
                V::from_zval(val).ok_or_else(|| Error::ZvalConversion(val.get_type()))?,
18✔
93
            ));
94
        }
95

96
        Ok(vec)
2✔
97
    }
98
}
99

100
impl<'a, K, V> TryFrom<Vec<(K, V)>> for ZBox<ZendHashTable>
101
where
102
    K: Into<ArrayKey<'a>>,
103
    V: IntoZval,
104
{
105
    type Error = Error;
106

107
    fn try_from(value: Vec<(K, V)>) -> Result<Self> {
4✔
108
        let mut ht = ZendHashTable::with_capacity(
109
            value.len().try_into().map_err(|_| Error::IntegerOverflow)?,
16✔
110
        );
111

112
        for (k, v) in value {
40✔
113
            ht.insert(k, v)?;
36✔
114
        }
115

116
        Ok(ht)
4✔
117
    }
118
}
119

120
// TODO: Generalize hasher
121
#[allow(clippy::implicit_hasher)]
122
impl<K, V> IntoZval for HashMap<K, V>
123
where
124
    K: AsRef<str>,
125
    V: IntoZval,
126
{
127
    const TYPE: DataType = DataType::Array;
128
    const NULLABLE: bool = false;
129

NEW
130
    fn set_zval(self, zv: &mut Zval, _: bool) -> Result<()> {
×
NEW
131
        let arr = self.try_into()?;
×
NEW
132
        zv.set_hashtable(arr);
×
NEW
133
        Ok(())
×
134
    }
135
}
136

137
// TODO: Generalize hasher
138
#[allow(clippy::implicit_hasher)]
139
impl<'a, T> FromZval<'a> for HashMap<String, T>
140
where
141
    T: FromZval<'a>,
142
{
143
    const TYPE: DataType = DataType::Array;
144

NEW
145
    fn from_zval(zval: &'a Zval) -> Option<Self> {
×
NEW
146
        zval.array().and_then(|arr| arr.try_into().ok())
×
147
    }
148
}
149

150
impl<'a, K, V> IntoZval for Vec<(K, V)>
151
where
152
    K: Into<ArrayKey<'a>>,
153
    V: IntoZval,
154
{
155
    const TYPE: DataType = DataType::Array;
156
    const NULLABLE: bool = false;
157

158
    fn set_zval(self, zv: &mut Zval, _: bool) -> Result<()> {
2✔
159
        let arr = self.try_into()?;
6✔
NEW
160
        zv.set_hashtable(arr);
×
NEW
161
        Ok(())
×
162
    }
163
}
164

165
impl<'a, K, V> FromZval<'a> for Vec<(K, V)>
166
where
167
    K: TryFrom<ArrayKey<'a>, Error = Error>,
168
    V: FromZval<'a>,
169
{
170
    const TYPE: DataType = DataType::Array;
171

172
    fn from_zval(zval: &'a Zval) -> Option<Self> {
3✔
173
        zval.array().and_then(|arr| arr.try_into().ok())
18✔
174
    }
175
}
176

177
impl<'a, V> FromZval<'a> for Vec<(ArrayKey<'a>, V)>
178
where
179
    V: FromZval<'a>,
180
{
181
    const TYPE: DataType = DataType::Array;
182

183
    fn from_zval(zval: &'a Zval) -> Option<Self> {
1✔
184
        zval.array().and_then(|arr| arr.try_into().ok())
6✔
185
    }
186
}
187

188
///////////////////////////////////////////
189
// Vec
190
///////////////////////////////////////////
191

192
impl<'a, T> TryFrom<&'a ZendHashTable> for Vec<T>
193
where
194
    T: FromZval<'a>,
195
{
196
    type Error = Error;
197

NEW
198
    fn try_from(value: &'a ZendHashTable) -> Result<Self> {
×
NEW
199
        let mut vec = Vec::with_capacity(value.len());
×
200

NEW
201
        for (_, val) in value {
×
NEW
202
            vec.push(T::from_zval(val).ok_or_else(|| Error::ZvalConversion(val.get_type()))?);
×
203
        }
204

NEW
205
        Ok(vec)
×
206
    }
207
}
208

209
impl<T> TryFrom<Vec<T>> for ZBox<ZendHashTable>
210
where
211
    T: IntoZval,
212
{
213
    type Error = Error;
214

NEW
215
    fn try_from(value: Vec<T>) -> Result<Self> {
×
216
        let mut ht = ZendHashTable::with_capacity(
NEW
217
            value.len().try_into().map_err(|_| Error::IntegerOverflow)?,
×
218
        );
219

NEW
220
        for val in value {
×
NEW
221
            ht.push(val)?;
×
222
        }
223

NEW
224
        Ok(ht)
×
225
    }
226
}
227

228
impl<T> IntoZval for Vec<T>
229
where
230
    T: IntoZval,
231
{
232
    const TYPE: DataType = DataType::Array;
233
    const NULLABLE: bool = false;
234

NEW
235
    fn set_zval(self, zv: &mut Zval, _: bool) -> Result<()> {
×
NEW
236
        let arr = self.try_into()?;
×
NEW
237
        zv.set_hashtable(arr);
×
NEW
238
        Ok(())
×
239
    }
240
}
241

242
impl<'a, T> FromZval<'a> for Vec<T>
243
where
244
    T: FromZval<'a>,
245
{
246
    const TYPE: DataType = DataType::Array;
247

NEW
248
    fn from_zval(zval: &'a Zval) -> Option<Self> {
×
NEW
249
        zval.array().and_then(|arr| arr.try_into().ok())
×
250
    }
251
}
252

253
impl FromIterator<Zval> for ZBox<ZendHashTable> {
NEW
254
    fn from_iter<T: IntoIterator<Item = Zval>>(iter: T) -> Self {
×
NEW
255
        let mut ht = ZendHashTable::new();
×
NEW
256
        for item in iter {
×
257
            // Inserting a zval cannot fail, as `push` only returns `Err` if converting
258
            // `val` to a zval fails.
NEW
259
            let _ = ht.push(item);
×
260
        }
NEW
261
        ht
×
262
    }
263
}
264

265
impl FromIterator<(i64, Zval)> for ZBox<ZendHashTable> {
NEW
266
    fn from_iter<T: IntoIterator<Item = (i64, Zval)>>(iter: T) -> Self {
×
NEW
267
        let mut ht = ZendHashTable::new();
×
NEW
268
        for (key, val) in iter {
×
269
            // Inserting a zval cannot fail, as `push` only returns `Err` if converting
270
            // `val` to a zval fails.
NEW
271
            let _ = ht.insert_at_index(key, val);
×
272
        }
NEW
273
        ht
×
274
    }
275
}
276

277
impl<'a> FromIterator<(&'a str, Zval)> for ZBox<ZendHashTable> {
NEW
278
    fn from_iter<T: IntoIterator<Item = (&'a str, Zval)>>(iter: T) -> Self {
×
NEW
279
        let mut ht = ZendHashTable::new();
×
NEW
280
        for (key, val) in iter {
×
281
            // Inserting a zval cannot fail, as `push` only returns `Err` if converting
282
            // `val` to a zval fails.
NEW
283
            let _ = ht.insert(key, val);
×
284
        }
NEW
285
        ht
×
286
    }
287
}
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