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

davidcole1340 / ext-php-rs / 14942826149

10 May 2025 06:37AM UTC coverage: 20.927% (+6.8%) from 14.14%
14942826149

Pull #431

github

Xenira
test(class): add extends and implements tests

Refs: #326
Pull Request #431: fix(class)!: generate correct stubs for extends and implements

34 of 58 new or added lines in 7 files covered. (58.62%)

1 existing line in 1 file now uncovered.

822 of 3928 relevant lines covered (20.93%)

2.04 hits per line

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

72.5
/src/describe/abi.rs
1
//! ABI-stable standard library types.
2
//!
3
//! The description module is used by the `cargo-php` sub-command to retrieve
4
//! information about the extension. As Rust does not have a stable ABI, it is
5
//! not as simple as working in the Rust domain, as if the CLI and extension
6
//! Rust versions do not match, it cannot be assumed that the types have the
7
//! same memory layout.
8
//!
9
//! This module contains thin wrappers around standard library types used by the
10
//! describe function to provide some sort of ABI-stability.
11
//!
12
//! As a general rule of thumb, no Rust type is ABI-stable. Strictly speaking,
13
//! [`usize`] should not be in use, but rather `size_t` or a similar type,
14
//! however these are currently unstable.
15

16
use std::{fmt::Display, ops::Deref, vec::Vec as StdVec};
17

18
/// An immutable, ABI-stable [`Vec`][std::vec::Vec].
19
#[repr(C)]
20
#[derive(Debug)]
21
pub struct Vec<T> {
22
    ptr: *mut T,
23
    len: usize,
24
}
25

26
impl<T> Deref for Vec<T> {
27
    type Target = [T];
28

29
    fn deref(&self) -> &Self::Target {
56✔
30
        unsafe { std::slice::from_raw_parts(self.ptr, self.len) }
56✔
31
    }
32
}
33

34
impl<T> Drop for Vec<T> {
35
    fn drop(&mut self) {
59✔
36
        unsafe {
37
            let _ = Box::from_raw(std::ptr::slice_from_raw_parts_mut(self.ptr, self.len));
59✔
38
        };
39
    }
40
}
41

42
impl<T> From<StdVec<T>> for Vec<T> {
43
    fn from(vec: StdVec<T>) -> Self {
59✔
44
        let vec = vec.into_boxed_slice();
59✔
45
        let len = vec.len();
59✔
46
        let ptr = Box::into_raw(vec).cast::<T>();
59✔
47

48
        Self { ptr, len }
49
    }
50
}
51

52
impl<T> PartialEq for Vec<T>
53
where
54
    T: PartialEq,
55
{
56
    fn eq(&self, other: &Self) -> bool {
21✔
57
        self.len == other.len && self.as_ref() == other.as_ref()
42✔
58
    }
59
}
60

61
/// An immutable, ABI-stable borrowed [`&'static str`][str].
62
#[repr(C)]
63
#[derive(Debug)]
64
pub struct Str {
65
    ptr: *const u8,
66
    len: usize,
67
}
68

69
impl Str {
70
    /// Returns the string as a string slice.
71
    ///
72
    /// The lifetime is `'static` and can outlive the [`Str`] object, as you can
73
    /// only initialize a [`Str`] through a static reference.
74
    #[must_use]
75
    pub fn str(&self) -> &'static str {
6✔
76
        unsafe { std::str::from_utf8_unchecked(std::slice::from_raw_parts(self.ptr, self.len)) }
6✔
77
    }
78
}
79

80
impl From<&'static str> for Str {
81
    fn from(val: &'static str) -> Self {
14✔
82
        let ptr = val.as_ptr();
14✔
83
        let len = val.len();
14✔
84
        Self { ptr, len }
85
    }
86
}
87

88
impl AsRef<str> for Str {
89
    fn as_ref(&self) -> &str {
×
90
        self.str()
×
91
    }
92
}
93

94
impl Display for Str {
95
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
×
96
        self.str().fmt(f)
×
97
    }
98
}
99

100
impl PartialEq for Str {
101
    fn eq(&self, other: &Self) -> bool {
3✔
102
        self.len == other.len && self.str() == other.str()
6✔
103
    }
104
}
105

106
/// An ABI-stable String
107
#[repr(C)]
108
#[derive(Debug, PartialEq)]
109
pub struct RString {
110
    inner: Vec<u8>,
111
}
112

113
impl RString {
114
    /// Returns the string as a string slice.
115
    ///
116
    /// # Panics
117
    ///
118
    /// * If the string is not valid UTF-8
119
    #[must_use]
120
    pub fn as_str(&self) -> &str {
×
121
        std::str::from_utf8(&self.inner).expect("RString value is not valid UTF-8")
×
122
    }
123
}
124

125
impl From<&str> for RString {
126
    fn from(s: &str) -> Self {
19✔
127
        Self {
128
            inner: s.as_bytes().to_vec().into(),
19✔
129
        }
130
    }
131
}
132

133
impl From<String> for RString {
134
    fn from(s: String) -> Self {
12✔
135
        Self {
136
            inner: s.into_bytes().into(),
12✔
137
        }
138
    }
139
}
140

141
impl AsRef<str> for RString {
142
    fn as_ref(&self) -> &str {
×
143
        self.as_str()
×
144
    }
145
}
146

147
impl Display for RString {
148
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
×
149
        self.as_str().fmt(f)
×
150
    }
151
}
152

153
/// An ABI-stable [`Option`][std::option::Option].
154
#[repr(C, u8)]
155
#[derive(Debug)]
156
pub enum Option<T> {
157
    /// [`Option::Some`][std::option::Option::Some] variant.
158
    Some(T),
159
    /// [`Option::None`][std::option::Option::None] variant.
160
    None,
161
}
162

163
impl<T> From<std::option::Option<T>> for Option<T> {
164
    fn from(opt: std::option::Option<T>) -> Self {
11✔
165
        match opt {
11✔
166
            Some(val) => Self::Some(val),
7✔
167
            None => Self::None,
4✔
168
        }
169
    }
170
}
171

172
impl<T> PartialEq for Option<T>
173
where
174
    T: PartialEq,
175
{
176
    fn eq(&self, other: &Self) -> bool {
12✔
177
        match (self, other) {
12✔
178
            (Self::Some(a), Self::Some(b)) => a == b,
7✔
179
            (Self::None, Self::None) => true,
5✔
NEW
180
            _ => false,
×
181
        }
182
    }
183
}
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