Coverage Report

Created: 2026-11-12 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rust-cssparser/src/cow_rc_str.rs
Line
Count
Source
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
use std::borrow::{Borrow, Cow};
6
use std::rc::Rc;
7
use std::{cmp, fmt, hash, marker, mem, ops, ptr, slice, str};
8
9
/// A string that is either shared (heap-allocated and reference-counted) or borrowed.
10
///
11
/// Equivalent to `enum { Borrowed(&'a str), Shared(Rc<String>) }`, but stored more compactly.
12
///
13
/// * If `borrowed_len_or_max == usize::MAX`, then `ptr` represents `NonZero<*const String>`
14
///   from `Rc::into_raw`.
15
///   The lifetime parameter `'a` is irrelevant in this case.
16
///
17
/// * Otherwise, `ptr` represents the `NonZero<*const u8>` data component of `&'a str`,
18
///   and `borrowed_len_or_max` its length.
19
pub struct CowRcStr<'a> {
20
    ptr: ptr::NonNull<()>,
21
    borrowed_len_or_max: usize,
22
23
    phantom: marker::PhantomData<Result<&'a str, Rc<String>>>,
24
}
25
26
fn _static_assert_same_size() {
27
    // "Instantiate" the generic function without calling it.
28
    let _ = mem::transmute::<CowRcStr<'_>, Option<CowRcStr<'_>>>;
29
}
30
31
impl<'a> From<Cow<'a, str>> for CowRcStr<'a> {
32
    #[inline]
33
    fn from(s: Cow<'a, str>) -> Self {
34
        match s {
35
            Cow::Borrowed(s) => CowRcStr::from(s),
36
            Cow::Owned(s) => CowRcStr::from(s),
37
        }
38
    }
39
}
40
41
impl<'a> From<&'a str> for CowRcStr<'a> {
42
    #[inline]
43
832k
    fn from(s: &'a str) -> Self {
44
832k
        let len = s.len();
45
        // Guaranteed by https://doc.rust-lang.org/stable/reference/types/numeric.html:
46
        //     The theoretical upper bound on object and array size is the maximum isize value
47
        // (which by definition is smaller than usize::MAX).
48
832k
        debug_assert!(len < usize::MAX);
49
832k
        CowRcStr {
50
832k
            ptr: unsafe { ptr::NonNull::new_unchecked(s.as_ptr() as *mut ()) },
51
832k
            borrowed_len_or_max: len,
52
832k
            phantom: marker::PhantomData,
53
832k
        }
54
832k
    }
55
}
56
57
impl From<String> for CowRcStr<'_> {
58
    #[inline]
59
158k
    fn from(s: String) -> Self {
60
158k
        CowRcStr::from_rc(Rc::new(s))
61
158k
    }
62
}
63
64
impl<'a> CowRcStr<'a> {
65
    #[inline]
66
158k
    fn from_rc(s: Rc<String>) -> Self {
67
158k
        let ptr = unsafe { ptr::NonNull::new_unchecked(Rc::into_raw(s) as *mut ()) };
68
158k
        CowRcStr {
69
158k
            ptr,
70
158k
            borrowed_len_or_max: usize::MAX,
71
158k
            phantom: marker::PhantomData,
72
158k
        }
73
158k
    }
74
75
    #[inline]
76
1.96M
    fn unpack(&self) -> Result<&'a str, *const String> {
77
1.96M
        if self.borrowed_len_or_max == usize::MAX {
78
310k
            Err(self.ptr.as_ptr() as *const String)
79
        } else {
80
            unsafe {
81
1.65M
                Ok(str::from_utf8_unchecked(slice::from_raw_parts(
82
1.65M
                    self.ptr.as_ptr() as *const u8,
83
1.65M
                    self.borrowed_len_or_max,
84
1.65M
                )))
85
            }
86
        }
87
1.96M
    }
<cssparser::cow_rc_str::CowRcStr>::unpack
Line
Count
Source
76
928k
    fn unpack(&self) -> Result<&'a str, *const String> {
77
928k
        if self.borrowed_len_or_max == usize::MAX {
78
144k
            Err(self.ptr.as_ptr() as *const String)
79
        } else {
80
            unsafe {
81
783k
                Ok(str::from_utf8_unchecked(slice::from_raw_parts(
82
783k
                    self.ptr.as_ptr() as *const u8,
83
783k
                    self.borrowed_len_or_max,
84
783k
                )))
85
            }
86
        }
87
928k
    }
<cssparser::cow_rc_str::CowRcStr>::unpack
Line
Count
Source
76
1.03M
    fn unpack(&self) -> Result<&'a str, *const String> {
77
1.03M
        if self.borrowed_len_or_max == usize::MAX {
78
166k
            Err(self.ptr.as_ptr() as *const String)
79
        } else {
80
            unsafe {
81
873k
                Ok(str::from_utf8_unchecked(slice::from_raw_parts(
82
873k
                    self.ptr.as_ptr() as *const u8,
83
873k
                    self.borrowed_len_or_max,
84
873k
                )))
85
            }
86
        }
87
1.03M
    }
88
}
89
90
impl Clone for CowRcStr<'_> {
91
    #[inline]
92
    fn clone(&self) -> Self {
93
        match self.unpack() {
94
            Err(ptr) => {
95
                let rc = unsafe { Rc::from_raw(ptr) };
96
                let new_rc = rc.clone();
97
                mem::forget(rc); // Don’t actually take ownership of this strong reference
98
                CowRcStr::from_rc(new_rc)
99
            }
100
            Ok(_) => CowRcStr { ..*self },
101
        }
102
    }
103
}
104
105
#[cold]
106
#[inline(never)]
107
158k
unsafe fn drop_slow(ptr: *const String) {
108
158k
    unsafe { mem::drop(Rc::from_raw(ptr)) }
109
158k
}
110
111
impl Drop for CowRcStr<'_> {
112
    #[inline]
113
990k
    fn drop(&mut self) {
114
990k
        if let Err(ptr) = self.unpack() {
115
158k
            unsafe { drop_slow(ptr) }
116
832k
        }
117
990k
    }
118
}
119
120
impl ops::Deref for CowRcStr<'_> {
121
    type Target = str;
122
123
    #[inline]
124
977k
    fn deref(&self) -> &str {
125
977k
        self.unpack().unwrap_or_else(|ptr| unsafe { &**ptr })
126
977k
    }
<cssparser::cow_rc_str::CowRcStr as core::ops::deref::Deref>::deref
Line
Count
Source
124
928k
    fn deref(&self) -> &str {
125
928k
        self.unpack().unwrap_or_else(|ptr| unsafe { &**ptr })
126
928k
    }
<cssparser::cow_rc_str::CowRcStr as core::ops::deref::Deref>::deref
Line
Count
Source
124
49.4k
    fn deref(&self) -> &str {
125
49.4k
        self.unpack().unwrap_or_else(|ptr| unsafe { &**ptr })
126
49.4k
    }
127
}
128
129
// Boilerplate / trivial impls below.
130
131
impl AsRef<str> for CowRcStr<'_> {
132
    #[inline]
133
    fn as_ref(&self) -> &str {
134
        self
135
    }
136
}
137
138
impl Borrow<str> for CowRcStr<'_> {
139
    #[inline]
140
    fn borrow(&self) -> &str {
141
        self
142
    }
143
}
144
145
impl Default for CowRcStr<'_> {
146
    #[inline]
147
    fn default() -> Self {
148
        Self::from("")
149
    }
150
}
151
152
impl hash::Hash for CowRcStr<'_> {
153
    #[inline]
154
    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
155
        str::hash(self, hasher)
156
    }
157
}
158
159
impl<T: AsRef<str>> PartialEq<T> for CowRcStr<'_> {
160
    #[inline]
161
    fn eq(&self, other: &T) -> bool {
162
        str::eq(self, other.as_ref())
163
    }
164
}
165
166
impl<T: AsRef<str>> PartialOrd<T> for CowRcStr<'_> {
167
    #[inline]
168
    fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
169
        str::partial_cmp(self, other.as_ref())
170
    }
171
}
172
173
impl Eq for CowRcStr<'_> {}
174
175
impl Ord for CowRcStr<'_> {
176
    #[inline]
177
    fn cmp(&self, other: &Self) -> cmp::Ordering {
178
        str::cmp(self, other)
179
    }
180
}
181
182
impl fmt::Display for CowRcStr<'_> {
183
    #[inline]
184
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
185
        str::fmt(self, formatter)
186
    }
187
}
188
189
impl fmt::Debug for CowRcStr<'_> {
190
    #[inline]
191
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
192
        str::fmt(self, formatter)
193
    }
194
}