Coverage Report

Created: 2026-03-26 07:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rkyv-0.8.15/src/ffi.rs
Line
Count
Source
1
//! Archived versions of FFI types.
2
3
use core::{
4
    borrow::Borrow,
5
    cmp,
6
    ffi::CStr,
7
    fmt, hash,
8
    ops::{Deref, Index, RangeFull},
9
};
10
11
use munge::munge;
12
use rancor::Fallible;
13
14
use crate::{
15
    primitive::FixedUsize, ser::Writer, ArchiveUnsized, Place, Portable,
16
    RelPtr, SerializeUnsized,
17
};
18
19
/// An archived [`CString`](crate::alloc::ffi::CString).
20
///
21
/// Uses a [`RelPtr`] to a `CStr` under the hood.
22
#[derive(Portable)]
23
#[rkyv(crate)]
24
#[cfg_attr(
25
    feature = "bytecheck",
26
    derive(bytecheck::CheckBytes),
27
    bytecheck(verify)
28
)]
29
#[repr(transparent)]
30
pub struct ArchivedCString {
31
    ptr: RelPtr<CStr>,
32
}
33
34
impl ArchivedCString {
35
    /// Returns the contents of this CString as a slice of bytes.
36
    ///
37
    /// The returned slice does **not** contain the trailing nul terminator, and
38
    /// it is guaranteed to not have any interior nul bytes. If you need the
39
    /// nul terminator, use
40
    /// [`as_bytes_with_nul`][ArchivedCString::as_bytes_with_nul()] instead.
41
    #[inline]
42
0
    pub fn as_bytes(&self) -> &[u8] {
43
0
        self.as_c_str().to_bytes()
44
0
    }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString>::as_bytes
Unexecuted instantiation: <rkyv::ffi::ArchivedCString>::as_bytes
45
46
    /// Equivalent to [`as_bytes`][ArchivedCString::as_bytes()] except that the
47
    /// returned slice includes the trailing nul terminator.
48
    #[inline]
49
0
    pub fn as_bytes_with_nul(&self) -> &[u8] {
50
0
        self.as_c_str().to_bytes_with_nul()
51
0
    }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString>::as_bytes_with_nul
Unexecuted instantiation: <rkyv::ffi::ArchivedCString>::as_bytes_with_nul
52
53
    /// Extracts a `CStr` slice containing the entire string.
54
    #[inline]
55
0
    pub fn as_c_str(&self) -> &CStr {
56
0
        unsafe { &*self.ptr.as_ptr() }
57
0
    }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString>::as_c_str
Unexecuted instantiation: <rkyv::ffi::ArchivedCString>::as_c_str
58
59
    /// Resolves an archived C string from the given C string and parameters.
60
    #[inline]
61
0
    pub fn resolve_from_c_str(
62
0
        c_str: &CStr,
63
0
        resolver: CStringResolver,
64
0
        out: Place<Self>,
65
0
    ) {
66
0
        munge!(let ArchivedCString { ptr } = out);
67
0
        RelPtr::emplace_unsized(
68
0
            resolver.pos as usize,
69
0
            c_str.archived_metadata(),
70
0
            ptr,
71
        );
72
0
    }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString>::resolve_from_c_str
Unexecuted instantiation: <rkyv::ffi::ArchivedCString>::resolve_from_c_str
73
74
    /// Serializes a C string.
75
0
    pub fn serialize_from_c_str<S: Fallible + Writer + ?Sized>(
76
0
        c_str: &CStr,
77
0
        serializer: &mut S,
78
0
    ) -> Result<CStringResolver, S::Error> {
79
        Ok(CStringResolver {
80
0
            pos: c_str.serialize_unsized(serializer)? as FixedUsize,
81
        })
82
0
    }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString>::serialize_from_c_str::<_>
Unexecuted instantiation: <rkyv::ffi::ArchivedCString>::serialize_from_c_str::<_>
83
}
84
85
impl AsRef<CStr> for ArchivedCString {
86
0
    fn as_ref(&self) -> &CStr {
87
0
        self.as_c_str()
88
0
    }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::convert::AsRef<core::ffi::c_str::CStr>>::as_ref
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::convert::AsRef<core::ffi::c_str::CStr>>::as_ref
89
}
90
91
impl Borrow<CStr> for ArchivedCString {
92
    #[inline]
93
0
    fn borrow(&self) -> &CStr {
94
0
        self.as_c_str()
95
0
    }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::borrow::Borrow<core::ffi::c_str::CStr>>::borrow
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::borrow::Borrow<core::ffi::c_str::CStr>>::borrow
96
}
97
98
impl fmt::Debug for ArchivedCString {
99
    #[inline]
100
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101
0
        self.as_c_str().fmt(f)
102
0
    }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::fmt::Debug>::fmt
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::fmt::Debug>::fmt
103
}
104
105
impl Deref for ArchivedCString {
106
    type Target = CStr;
107
108
    #[inline]
109
0
    fn deref(&self) -> &Self::Target {
110
0
        self.as_c_str()
111
0
    }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::ops::deref::Deref>::deref
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::ops::deref::Deref>::deref
112
}
113
114
impl Eq for ArchivedCString {}
115
116
impl hash::Hash for ArchivedCString {
117
0
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
118
0
        self.as_bytes_with_nul().hash(state);
119
0
    }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::hash::Hash>::hash::<_>
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::hash::Hash>::hash::<_>
120
}
121
122
impl Index<RangeFull> for ArchivedCString {
123
    type Output = CStr;
124
125
    #[inline]
126
0
    fn index(&self, _: RangeFull) -> &Self::Output {
127
0
        self.as_c_str()
128
0
    }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::ops::index::Index<core::ops::range::RangeFull>>::index
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::ops::index::Index<core::ops::range::RangeFull>>::index
129
}
130
131
impl Ord for ArchivedCString {
132
    #[inline]
133
0
    fn cmp(&self, other: &Self) -> cmp::Ordering {
134
0
        self.as_bytes().cmp(other.as_bytes())
135
0
    }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::cmp::Ord>::cmp
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::cmp::Ord>::cmp
136
}
137
138
impl PartialEq for ArchivedCString {
139
    #[inline]
140
0
    fn eq(&self, other: &Self) -> bool {
141
0
        self.as_bytes() == other.as_bytes()
142
0
    }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::cmp::PartialEq>::eq
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::cmp::PartialEq>::eq
143
}
144
145
impl PartialEq<&CStr> for ArchivedCString {
146
    #[inline]
147
0
    fn eq(&self, other: &&CStr) -> bool {
148
0
        PartialEq::eq(self.as_c_str(), other)
149
0
    }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::cmp::PartialEq<&core::ffi::c_str::CStr>>::eq
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::cmp::PartialEq<&core::ffi::c_str::CStr>>::eq
150
}
151
152
impl PartialEq<ArchivedCString> for &CStr {
153
    #[inline]
154
0
    fn eq(&self, other: &ArchivedCString) -> bool {
155
0
        PartialEq::eq(other.as_c_str(), self)
156
0
    }
Unexecuted instantiation: <&core::ffi::c_str::CStr as core::cmp::PartialEq<rkyv::ffi::ArchivedCString>>::eq
Unexecuted instantiation: <&core::ffi::c_str::CStr as core::cmp::PartialEq<rkyv::ffi::ArchivedCString>>::eq
157
}
158
159
impl PartialOrd for ArchivedCString {
160
    #[inline]
161
0
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
162
0
        Some(self.cmp(other))
163
0
    }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::cmp::PartialOrd>::partial_cmp
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as core::cmp::PartialOrd>::partial_cmp
164
}
165
166
/// The resolver for `CString`.
167
pub struct CStringResolver {
168
    pos: FixedUsize,
169
}
170
171
#[cfg(feature = "bytecheck")]
172
mod verify {
173
    use core::ffi::CStr;
174
175
    use bytecheck::{
176
        rancor::{Fallible, Source},
177
        CheckBytes, Verify,
178
    };
179
180
    use crate::{
181
        ffi::ArchivedCString,
182
        validation::{ArchiveContext, ArchiveContextExt},
183
    };
184
185
    unsafe impl<C> Verify<C> for ArchivedCString
186
    where
187
        C: Fallible + ArchiveContext + ?Sized,
188
        C::Error: Source,
189
    {
190
0
        fn verify(&self, context: &mut C) -> Result<(), C::Error> {
191
0
            let ptr = self.ptr.as_ptr_wrapping();
192
0
            context.in_subtree(ptr, |context| unsafe {
193
0
                CStr::check_bytes(ptr, context)
194
0
            })
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as bytecheck::Verify<_>>::verify::{closure#0}
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as bytecheck::Verify<_>>::verify::{closure#0}
195
0
        }
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as bytecheck::Verify<_>>::verify
Unexecuted instantiation: <rkyv::ffi::ArchivedCString as bytecheck::Verify<_>>::verify
196
    }
197
}