Skip to content

Commit 455b192

Browse files
committed
feat(types): Argument coercion into HashSet/BTreeSet #493
1 parent 34035ed commit 455b192

File tree

4 files changed

+152
-0
lines changed

4 files changed

+152
-0
lines changed

src/types/array/array_key.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,38 @@ impl<'a> From<&'a str> for ArrayKey<'a> {
9292
}
9393
}
9494

95+
impl<'a> From<i32> for ArrayKey<'a> {
96+
fn from(index: i32) -> ArrayKey<'a> {
97+
ArrayKey::Long(i64::from(index))
98+
}
99+
}
100+
95101
impl<'a> From<i64> for ArrayKey<'a> {
96102
fn from(index: i64) -> ArrayKey<'a> {
97103
ArrayKey::Long(index)
98104
}
99105
}
100106

107+
impl<'a> From<u64> for ArrayKey<'a> {
108+
fn from(index: u64) -> ArrayKey<'a> {
109+
if let Ok(index) = i64::try_from(index) {
110+
ArrayKey::Long(index)
111+
} else {
112+
ArrayKey::String(index.to_string())
113+
}
114+
}
115+
}
116+
117+
impl<'a> From<usize> for ArrayKey<'a> {
118+
fn from(index: usize) -> ArrayKey<'a> {
119+
if let Ok(index) = i64::try_from(index) {
120+
ArrayKey::Long(index)
121+
} else {
122+
ArrayKey::String(index.to_string())
123+
}
124+
}
125+
}
126+
101127
impl<'a> FromZval<'a> for ArrayKey<'_> {
102128
const TYPE: DataType = DataType::String;
103129

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use super::super::ZendHashTable;
2+
use crate::{
3+
boxed::ZBox,
4+
convert::{FromZval, IntoZval},
5+
error::{Error, Result},
6+
flags::DataType,
7+
types::Zval,
8+
};
9+
use std::collections::BTreeSet;
10+
use std::convert::TryFrom;
11+
12+
impl<'a, V> TryFrom<&'a ZendHashTable> for BTreeSet<V>
13+
where
14+
V: FromZval<'a> + Ord,
15+
{
16+
type Error = Error;
17+
18+
fn try_from(value: &'a ZendHashTable) -> Result<Self> {
19+
let mut set = Self::new();
20+
21+
for (_key, val) in value {
22+
set.insert(V::from_zval(val).ok_or_else(|| Error::ZvalConversion(val.get_type()))?);
23+
}
24+
25+
Ok(set)
26+
}
27+
}
28+
29+
impl<V> TryFrom<BTreeSet<V>> for ZBox<ZendHashTable>
30+
where
31+
V: IntoZval,
32+
{
33+
type Error = Error;
34+
35+
fn try_from(value: BTreeSet<V>) -> Result<Self> {
36+
let mut set = ZendHashTable::with_capacity(
37+
value.len().try_into().map_err(|_| Error::IntegerOverflow)?,
38+
);
39+
40+
for (k, v) in value.into_iter().enumerate() {
41+
set.insert(k, v)?;
42+
}
43+
44+
Ok(set)
45+
}
46+
}
47+
48+
impl<V> IntoZval for BTreeSet<V>
49+
where
50+
V: IntoZval,
51+
{
52+
const TYPE: DataType = DataType::Array;
53+
const NULLABLE: bool = false;
54+
55+
fn set_zval(self, zv: &mut Zval, _: bool) -> Result<()> {
56+
let arr = self.try_into()?;
57+
zv.set_hashtable(arr);
58+
Ok(())
59+
}
60+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use super::super::ZendHashTable;
2+
use crate::{
3+
boxed::ZBox,
4+
convert::{FromZval, IntoZval},
5+
error::{Error, Result},
6+
flags::DataType,
7+
types::Zval,
8+
};
9+
use std::collections::HashSet;
10+
use std::convert::TryFrom;
11+
use std::hash::{BuildHasher, Hash};
12+
13+
impl<'a, V, H> TryFrom<&'a ZendHashTable> for HashSet<V, H>
14+
where
15+
V: FromZval<'a> + Eq + Hash,
16+
H: BuildHasher + Default,
17+
{
18+
type Error = Error;
19+
20+
fn try_from(value: &'a ZendHashTable) -> Result<Self> {
21+
let mut set = Self::with_capacity_and_hasher(value.len(), H::default());
22+
23+
for (_key, val) in value {
24+
set.insert(V::from_zval(val).ok_or_else(|| Error::ZvalConversion(val.get_type()))?);
25+
}
26+
27+
Ok(set)
28+
}
29+
}
30+
31+
impl<V, H> TryFrom<HashSet<V, H>> for ZBox<ZendHashTable>
32+
where
33+
V: IntoZval,
34+
H: BuildHasher,
35+
{
36+
type Error = Error;
37+
38+
fn try_from(value: HashSet<V, H>) -> Result<Self> {
39+
let mut ht = ZendHashTable::with_capacity(
40+
value.len().try_into().map_err(|_| Error::IntegerOverflow)?,
41+
);
42+
43+
for (k, v) in value.into_iter().enumerate() {
44+
ht.insert(k, v)?;
45+
}
46+
47+
Ok(ht)
48+
}
49+
}
50+
51+
impl<V, H> IntoZval for HashSet<V, H>
52+
where
53+
V: IntoZval,
54+
H: BuildHasher,
55+
{
56+
const TYPE: DataType = DataType::Array;
57+
const NULLABLE: bool = false;
58+
59+
fn set_zval(self, zv: &mut Zval, _: bool) -> Result<()> {
60+
let arr = self.try_into()?;
61+
zv.set_hashtable(arr);
62+
Ok(())
63+
}
64+
}

src/types/array/conversions/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@
1111
//! - `Vec<T>` and `Vec<(K, V)>` ↔ `ZendHashTable` (via `vec` module)
1212
1313
mod btree_map;
14+
mod btree_set;
1415
mod hash_map;
16+
mod hash_set;
1517
mod vec;

0 commit comments

Comments
 (0)