11//! Represents an array in PHP. As all arrays in PHP are associative arrays,
22//! they are represented by hash tables.
33
4- use std::{
5- collections::HashMap,
6- convert::{TryFrom, TryInto},
7- ffi::CString,
8- fmt::{Debug, Display},
9- iter::FromIterator,
10- ptr,
11- str::FromStr,
12- };
13-
144use crate::{
155 boxed::{ZBox, ZBoxable},
166 convert::{FromZval, IntoZval},
@@ -27,6 +17,15 @@ use crate::{
2717 flags::DataType,
2818 types::Zval,
2919};
20+ use std::{
21+ collections::{BTreeMap, HashMap},
22+ convert::{TryFrom, TryInto},
23+ ffi::CString,
24+ fmt::{Debug, Display},
25+ iter::FromIterator,
26+ ptr,
27+ str::FromStr,
28+ };
3029
3130/// A PHP hashtable.
3231///
@@ -1288,6 +1287,76 @@ where
12881287 }
12891288}
12901289
1290+ ///////////////////////////////////////////
1291+ // BTreeMap
1292+ ///////////////////////////////////////////
1293+
1294+ impl<'a, V> TryFrom<&'a ZendHashTable> for BTreeMap<String, V>
1295+ where
1296+ V: FromZval<'a>,
1297+ {
1298+ type Error = Error;
1299+
1300+ fn try_from(value: &'a ZendHashTable) -> Result<Self> {
1301+ let mut hm = BTreeMap::new();
1302+
1303+ for (key, val) in value {
1304+ hm.insert(
1305+ key.to_string(),
1306+ V::from_zval(val).ok_or_else(|| Error::ZvalConversion(val.get_type()))?,
1307+ );
1308+ }
1309+
1310+ Ok(hm)
1311+ }
1312+ }
1313+
1314+ impl<K, V> TryFrom<BTreeMap<K, V>> for ZBox<ZendHashTable>
1315+ where
1316+ K: AsRef<str>,
1317+ V: IntoZval,
1318+ {
1319+ type Error = Error;
1320+
1321+ fn try_from(value: BTreeMap<K, V>) -> Result<Self> {
1322+ let mut ht = ZendHashTable::with_capacity(
1323+ value.len().try_into().map_err(|_| Error::IntegerOverflow)?,
1324+ );
1325+
1326+ for (k, v) in value {
1327+ ht.insert(k.as_ref(), v)?;
1328+ }
1329+
1330+ Ok(ht)
1331+ }
1332+ }
1333+
1334+ impl<K, V> IntoZval for BTreeMap<K, V>
1335+ where
1336+ K: AsRef<str>,
1337+ V: IntoZval,
1338+ {
1339+ const TYPE: DataType = DataType::Array;
1340+ const NULLABLE: bool = false;
1341+
1342+ fn set_zval(self, zv: &mut Zval, _: bool) -> Result<()> {
1343+ let arr = self.try_into()?;
1344+ zv.set_hashtable(arr);
1345+ Ok(())
1346+ }
1347+ }
1348+
1349+ impl<'a, T> FromZval<'a> for BTreeMap<String, T>
1350+ where
1351+ T: FromZval<'a>,
1352+ {
1353+ const TYPE: DataType = DataType::Array;
1354+
1355+ fn from_zval(zval: &'a Zval) -> Option<Self> {
1356+ zval.array().and_then(|arr| arr.try_into().ok())
1357+ }
1358+ }
1359+
12911360///////////////////////////////////////////
12921361// Vec
12931362///////////////////////////////////////////
0 commit comments