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

davidcole1340 / ext-php-rs / 16392720284

19 Jul 2025 09:04PM UTC coverage: 24.784%. Remained the same
16392720284

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

79 of 299 new or added lines in 5 files covered. (26.42%)

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

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<'_> {
NEW
19
    fn from(value: String) -> Self {
×
NEW
20
        Self::String(value)
×
21
    }
22
}
23

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

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

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

39
    fn try_from(value: ArrayKey<'_>) -> std::result::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]
NEW
55
    pub fn is_long(&self) -> bool {
×
NEW
56
        match self {
×
NEW
57
            ArrayKey::Long(_) => true,
×
NEW
58
            ArrayKey::String(_) | ArrayKey::Str(_) => false,
×
59
        }
60
    }
61
}
62

63
impl Display for ArrayKey<'_> {
NEW
64
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
×
NEW
65
        match self {
×
NEW
66
            ArrayKey::Long(key) => write!(f, "{key}"),
×
NEW
67
            ArrayKey::String(key) => write!(f, "{key}"),
×
NEW
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> {
20✔
89
        if let Some(key) = zval.long() {
31✔
NEW
90
            return Some(ArrayKey::Long(key));
×
91
        }
92
        if let Some(key) = zval.string() {
18✔
NEW
93
            return Some(ArrayKey::String(key));
×
94
        }
NEW
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!(result.is_err());
121
        assert!(matches!(result.unwrap_err(), Error::InvalidProperty));
122

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

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

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

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

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

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

© 2025 Coveralls, Inc