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

davidcole1340 / ext-php-rs / 16429134897

21 Jul 2025 10:01PM UTC coverage: 27.026% (-0.1%) from 27.144%
16429134897

Pull #535

github

web-flow
Merge 45a3cbccf into 6869625f4
Pull Request #535: feat(array): introducing BTreeMap conversion and refactoring HashMap conversion

3 of 24 new or added lines in 3 files covered. (12.5%)

92 existing lines in 2 files now uncovered.

1127 of 4170 relevant lines covered (27.03%)

5.74 hits per line

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

54.84
/src/types/array/array_key.rs
1
use std::{convert::TryFrom, fmt::Display};
2

3
use crate::{convert::FromZval, error::Error, flags::DataType, types::Zval};
4

5
/// Represents the key of a PHP array, which can be either a long or a string.
6
#[derive(Debug, Clone, PartialEq)]
7
pub enum ArrayKey<'a> {
8
    /// A numerical key.
9
    /// In Zend API it's represented by `u64` (`zend_ulong`), so the value needs
10
    /// to be cast to `zend_ulong` before passing into Zend functions.
11
    Long(i64),
12
    /// A string key.
13
    String(String),
14
    /// A string key by reference.
15
    Str(&'a str),
16
}
17

18
impl From<String> for ArrayKey<'_> {
19
    fn from(value: String) -> Self {
×
20
        Self::String(value)
×
21
    }
22
}
23

24
impl TryFrom<ArrayKey<'_>> for String {
25
    type Error = Error;
26

27
    fn try_from(value: ArrayKey<'_>) -> Result<Self, Self::Error> {
14✔
28
        match value {
14✔
29
            ArrayKey::String(s) => Ok(s),
16✔
30
            ArrayKey::Str(s) => Ok(s.to_string()),
2✔
31
            ArrayKey::Long(l) => Ok(l.to_string()),
5✔
32
        }
33
    }
34
}
35

36
impl TryFrom<ArrayKey<'_>> for i64 {
37
    type Error = Error;
38

39
    fn try_from(value: ArrayKey<'_>) -> Result<Self, Self::Error> {
11✔
40
        match value {
11✔
41
            ArrayKey::Long(i) => Ok(i),
6✔
42
            ArrayKey::String(s) => s.parse::<i64>().map_err(|_| Error::InvalidProperty),
9✔
43
            ArrayKey::Str(s) => s.parse::<i64>().map_err(|_| Error::InvalidProperty),
8✔
44
        }
45
    }
46
}
47

48
impl ArrayKey<'_> {
49
    /// Check if the key is an integer.
50
    ///
51
    /// # Returns
52
    ///
53
    /// Returns true if the key is an integer, false otherwise.
54
    #[must_use]
UNCOV
55
    pub fn is_long(&self) -> bool {
×
UNCOV
56
        match self {
×
UNCOV
57
            ArrayKey::Long(_) => true,
×
UNCOV
58
            ArrayKey::String(_) | ArrayKey::Str(_) => false,
×
59
        }
60
    }
61
}
62

63
impl Display for ArrayKey<'_> {
UNCOV
64
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
×
UNCOV
65
        match self {
×
UNCOV
66
            ArrayKey::Long(key) => write!(f, "{key}"),
×
UNCOV
67
            ArrayKey::String(key) => write!(f, "{key}"),
×
68
            ArrayKey::Str(key) => write!(f, "{key}"),
×
69
        }
70
    }
71
}
72

73
impl<'a> From<&'a str> for ArrayKey<'a> {
74
    fn from(key: &'a str) -> ArrayKey<'a> {
27✔
75
        ArrayKey::Str(key)
27✔
76
    }
77
}
78

79
impl<'a> From<i64> for ArrayKey<'a> {
80
    fn from(index: i64) -> ArrayKey<'a> {
20✔
81
        ArrayKey::Long(index)
20✔
82
    }
83
}
84

85
impl<'a> FromZval<'a> for ArrayKey<'_> {
86
    const TYPE: DataType = DataType::String;
87

88
    fn from_zval(zval: &'a Zval) -> Option<Self> {
22✔
89
        if let Some(key) = zval.long() {
35✔
UNCOV
90
            return Some(ArrayKey::Long(key));
×
91
        }
92
        if let Some(key) = zval.string() {
18✔
UNCOV
93
            return Some(ArrayKey::String(key));
×
94
        }
UNCOV
95
        None
×
96
    }
97
}
98

99
#[cfg(test)]
100
#[cfg(feature = "embed")]
101
#[allow(clippy::unwrap_used)]
102
mod tests {
103
    use crate::error::Error;
104
    use crate::types::ArrayKey;
105

106
    #[test]
107
    fn test_string_try_from_array_key() {
108
        let key = ArrayKey::String("test".to_string());
109
        let result: crate::error::Result<String, _> = key.try_into();
110
        assert!(result.is_ok());
111
        assert_eq!(result.unwrap(), "test".to_string());
112

113
        let key = ArrayKey::Str("test");
114
        let result: crate::error::Result<String, _> = key.try_into();
115
        assert!(result.is_ok());
116
        assert_eq!(result.unwrap(), "test".to_string());
117

118
        let key = ArrayKey::Long(42);
119
        let result: crate::error::Result<String, _> = key.try_into();
120
        assert_eq!(result.unwrap(), "42".to_string());
121

122
        let key = ArrayKey::String("42".to_string());
123
        let result: crate::error::Result<String, _> = key.try_into();
124
        assert!(result.is_ok());
125
        assert_eq!(result.unwrap(), "42".to_string());
126

127
        let key = ArrayKey::Str("123");
128
        let result: crate::error::Result<i64, _> = key.try_into();
129
        assert!(result.is_ok());
130
        assert_eq!(result.unwrap(), 123);
131
    }
132

133
    #[test]
134
    fn test_i64_try_from_array_key() {
135
        let key = ArrayKey::Long(42);
136
        let result: crate::error::Result<i64, _> = key.try_into();
137
        assert!(result.is_ok());
138
        assert_eq!(result.unwrap(), 42);
139

140
        let key = ArrayKey::String("42".to_string());
141
        let result: crate::error::Result<i64, _> = key.try_into();
142
        assert!(result.is_ok());
143
        assert_eq!(result.unwrap(), 42);
144

145
        let key = ArrayKey::Str("123");
146
        let result: crate::error::Result<i64, _> = key.try_into();
147
        assert!(result.is_ok());
148
        assert_eq!(result.unwrap(), 123);
149

150
        let key = ArrayKey::String("not a number".to_string());
151
        let result: crate::error::Result<i64, _> = key.try_into();
152
        assert!(result.is_err());
153
        assert!(matches!(result.unwrap_err(), Error::InvalidProperty));
154
    }
155
}
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