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

extphprs / ext-php-rs / 20234271478

15 Dec 2025 01:39PM UTC coverage: 36.015% (+0.8%) from 35.229%
20234271478

push

github

web-flow
feat(types): Argument coercion into HashSet/BTreeSet #493 (#598)

* feat(types): Argument coercion into HashSet/BTreeSet #493

* feat(types): array: impl FromZval for HashSet/BTreeSet

* feat(types): array: impl FromZval for HashSet/BTreeSet: tests

43 of 56 new or added lines in 4 files covered. (76.79%)

2 existing lines in 1 file now uncovered.

1652 of 4587 relevant lines covered (36.01%)

10.97 hits per line

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

75.0
/src/types/array/conversions/hash_set.rs
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> {
1✔
21
        let mut set = Self::with_capacity_and_hasher(value.len(), H::default());
5✔
22

23
        for (_key, val) in value {
10✔
24
            set.insert(V::from_zval(val).ok_or_else(|| Error::ZvalConversion(val.get_type()))?);
15✔
25
        }
26

27
        Ok(set)
1✔
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> {
1✔
39
        let mut ht = ZendHashTable::with_capacity(
40
            value.len().try_into().map_err(|_| Error::IntegerOverflow)?,
4✔
41
        );
42

43
        for (k, v) in value.into_iter().enumerate() {
5✔
44
            ht.insert(k, v)?;
3✔
45
        }
46

47
        Ok(ht)
1✔
48
    }
49
}
50

51
impl<'a, V, H> FromZval<'a> for HashSet<V, H>
52
where
53
    V: FromZval<'a> + Eq + Hash,
54
    H: BuildHasher + Default,
55
{
56
    const TYPE: DataType = DataType::Array;
57

58
    fn from_zval(zval: &'a Zval) -> Option<Self> {
1✔
59
        zval.array().and_then(|arr| arr.try_into().ok())
6✔
60
    }
61
}
62

63
impl<V, H> IntoZval for HashSet<V, H>
64
where
65
    V: IntoZval,
66
    H: BuildHasher,
67
{
68
    const TYPE: DataType = DataType::Array;
69
    const NULLABLE: bool = false;
70

NEW
71
    fn set_zval(self, zv: &mut Zval, _: bool) -> Result<()> {
×
NEW
72
        let arr = self.try_into()?;
×
NEW
73
        zv.set_hashtable(arr);
×
NEW
74
        Ok(())
×
75
    }
76
}
77

78
#[cfg(test)]
79
#[cfg(feature = "embed")]
80
#[allow(clippy::unwrap_used)]
81
mod tests {
82
    use std::collections::HashSet;
83

84
    use crate::boxed::ZBox;
85
    use crate::convert::FromZval;
86
    use crate::embed::Embed;
87
    use crate::types::{ZendHashTable, Zval};
88

89
    #[test]
90
    fn test_hash_table_try_from_hash_set() {
91
        Embed::run(|| {
92
            let mut set = HashSet::new();
93
            set.insert("one");
94
            let ht: ZBox<ZendHashTable> = set.try_into().unwrap();
95
            assert_eq!(ht.len(), 1);
96
            assert!(ht.get(0).is_some());
97
        });
98
    }
99

100
    #[test]
101
    fn test_hash_set_try_from_hash_table() {
102
        Embed::run(|| {
103
            let mut ht = ZendHashTable::new();
104
            ht.insert(0, "value1").unwrap();
105
            ht.insert(1, "value2").unwrap();
106
            ht.insert(2, "value3").unwrap();
107
            let mut zval = Zval::new();
108
            zval.set_hashtable(ht);
109

110
            let map = HashSet::<String>::from_zval(&zval).unwrap();
111
            assert_eq!(map.len(), 3);
112
            assert!(map.contains("value1"));
113
            assert!(map.contains("value2"));
114
            assert!(map.contains("value3"));
115
        });
116
    }
117
}
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