Coverage Report

Created: 2025-12-31 07:00

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
1.29M
    fn from(s: &'a str) -> Self {
44
1.29M
        let len = s.len();
45
1.29M
        assert!(len < usize::MAX);
46
1.29M
        CowRcStr {
47
1.29M
            ptr: unsafe { ptr::NonNull::new_unchecked(s.as_ptr() as *mut ()) },
48
1.29M
            borrowed_len_or_max: len,
49
1.29M
            phantom: marker::PhantomData,
50
1.29M
        }
51
1.29M
    }
52
}
53
54
impl From<String> for CowRcStr<'_> {
55
    #[inline]
56
495k
    fn from(s: String) -> Self {
57
495k
        CowRcStr::from_rc(Rc::new(s))
58
495k
    }
59
}
60
61
impl<'a> CowRcStr<'a> {
62
    #[inline]
63
495k
    fn from_rc(s: Rc<String>) -> Self {
64
495k
        let ptr = unsafe { ptr::NonNull::new_unchecked(Rc::into_raw(s) as *mut ()) };
65
495k
        CowRcStr {
66
495k
            ptr,
67
495k
            borrowed_len_or_max: usize::MAX,
68
495k
            phantom: marker::PhantomData,
69
495k
        }
70
495k
    }
<cssparser::cow_rc_str::CowRcStr>::from_rc
Line
Count
Source
63
2
    fn from_rc(s: Rc<String>) -> Self {
64
2
        let ptr = unsafe { ptr::NonNull::new_unchecked(Rc::into_raw(s) as *mut ()) };
65
2
        CowRcStr {
66
2
            ptr,
67
2
            borrowed_len_or_max: usize::MAX,
68
2
            phantom: marker::PhantomData,
69
2
        }
70
2
    }
<cssparser::cow_rc_str::CowRcStr>::from_rc
Line
Count
Source
63
495k
    fn from_rc(s: Rc<String>) -> Self {
64
495k
        let ptr = unsafe { ptr::NonNull::new_unchecked(Rc::into_raw(s) as *mut ()) };
65
495k
        CowRcStr {
66
495k
            ptr,
67
495k
            borrowed_len_or_max: usize::MAX,
68
495k
            phantom: marker::PhantomData,
69
495k
        }
70
495k
    }
71
72
    #[inline]
73
3.66M
    fn unpack(&self) -> Result<&'a str, *const String> {
74
3.66M
        if self.borrowed_len_or_max == usize::MAX {
75
1.09M
            Err(self.ptr.as_ptr() as *const String)
76
        } else {
77
            unsafe {
78
2.57M
                Ok(str::from_utf8_unchecked(slice::from_raw_parts(
79
2.57M
                    self.ptr.as_ptr() as *const u8,
80
2.57M
                    self.borrowed_len_or_max,
81
2.57M
                )))
82
            }
83
        }
84
3.66M
    }
<cssparser::cow_rc_str::CowRcStr>::unpack
Line
Count
Source
73
1.69M
    fn unpack(&self) -> Result<&'a str, *const String> {
74
1.69M
        if self.borrowed_len_or_max == usize::MAX {
75
485k
            Err(self.ptr.as_ptr() as *const String)
76
        } else {
77
            unsafe {
78
1.21M
                Ok(str::from_utf8_unchecked(slice::from_raw_parts(
79
1.21M
                    self.ptr.as_ptr() as *const u8,
80
1.21M
                    self.borrowed_len_or_max,
81
1.21M
                )))
82
            }
83
        }
84
1.69M
    }
<cssparser::cow_rc_str::CowRcStr>::unpack
Line
Count
Source
73
1.97M
    fn unpack(&self) -> Result<&'a str, *const String> {
74
1.97M
        if self.borrowed_len_or_max == usize::MAX {
75
613k
            Err(self.ptr.as_ptr() as *const String)
76
        } else {
77
            unsafe {
78
1.36M
                Ok(str::from_utf8_unchecked(slice::from_raw_parts(
79
1.36M
                    self.ptr.as_ptr() as *const u8,
80
1.36M
                    self.borrowed_len_or_max,
81
1.36M
                )))
82
            }
83
        }
84
1.97M
    }
85
}
86
87
impl Clone for CowRcStr<'_> {
88
    #[inline]
89
311
    fn clone(&self) -> Self {
90
311
        match self.unpack() {
91
2
            Err(ptr) => {
92
2
                let rc = unsafe { Rc::from_raw(ptr) };
93
2
                let new_rc = rc.clone();
94
2
                mem::forget(rc); // Don’t actually take ownership of this strong reference
95
2
                CowRcStr::from_rc(new_rc)
96
            }
97
309
            Ok(_) => CowRcStr { ..*self },
98
        }
99
311
    }
<cssparser::cow_rc_str::CowRcStr as core::clone::Clone>::clone
Line
Count
Source
89
311
    fn clone(&self) -> Self {
90
311
        match self.unpack() {
91
2
            Err(ptr) => {
92
2
                let rc = unsafe { Rc::from_raw(ptr) };
93
2
                let new_rc = rc.clone();
94
2
                mem::forget(rc); // Don’t actually take ownership of this strong reference
95
2
                CowRcStr::from_rc(new_rc)
96
            }
97
309
            Ok(_) => CowRcStr { ..*self },
98
        }
99
311
    }
Unexecuted instantiation: <cssparser::cow_rc_str::CowRcStr as core::clone::Clone>::clone
100
}
101
102
impl Drop for CowRcStr<'_> {
103
    #[inline]
104
1.79M
    fn drop(&mut self) {
105
1.79M
        if let Err(ptr) = self.unpack() {
106
495k
            mem::drop(unsafe { Rc::from_raw(ptr) })
107
1.29M
        }
108
1.79M
    }
109
}
110
111
impl ops::Deref for CowRcStr<'_> {
112
    type Target = str;
113
114
    #[inline]
115
1.87M
    fn deref(&self) -> &str {
116
1.87M
        self.unpack().unwrap_or_else(|ptr| unsafe { &**ptr })
117
1.87M
    }
<cssparser::cow_rc_str::CowRcStr as core::ops::deref::Deref>::deref
Line
Count
Source
115
1.69M
    fn deref(&self) -> &str {
116
1.69M
        self.unpack().unwrap_or_else(|ptr| unsafe { &**ptr })
117
1.69M
    }
<cssparser::cow_rc_str::CowRcStr as core::ops::deref::Deref>::deref
Line
Count
Source
115
180k
    fn deref(&self) -> &str {
116
180k
        self.unpack().unwrap_or_else(|ptr| unsafe { &**ptr })
117
180k
    }
118
}
119
120
// Boilerplate / trivial impls below.
121
122
impl AsRef<str> for CowRcStr<'_> {
123
    #[inline]
124
    fn as_ref(&self) -> &str {
125
        self
126
    }
127
}
128
129
impl Borrow<str> for CowRcStr<'_> {
130
    #[inline]
131
    fn borrow(&self) -> &str {
132
        self
133
    }
134
}
135
136
impl Default for CowRcStr<'_> {
137
    #[inline]
138
    fn default() -> Self {
139
        Self::from("")
140
    }
141
}
142
143
impl hash::Hash for CowRcStr<'_> {
144
    #[inline]
145
    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
146
        str::hash(self, hasher)
147
    }
148
}
149
150
impl<T: AsRef<str>> PartialEq<T> for CowRcStr<'_> {
151
    #[inline]
152
    fn eq(&self, other: &T) -> bool {
153
        str::eq(self, other.as_ref())
154
    }
155
}
156
157
impl<T: AsRef<str>> PartialOrd<T> for CowRcStr<'_> {
158
    #[inline]
159
    fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
160
        str::partial_cmp(self, other.as_ref())
161
    }
162
}
163
164
impl Eq for CowRcStr<'_> {}
165
166
impl Ord for CowRcStr<'_> {
167
    #[inline]
168
    fn cmp(&self, other: &Self) -> cmp::Ordering {
169
        str::cmp(self, other)
170
    }
171
}
172
173
impl fmt::Display for CowRcStr<'_> {
174
    #[inline]
175
0
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
176
0
        str::fmt(self, formatter)
177
0
    }
178
}
179
180
impl fmt::Debug for CowRcStr<'_> {
181
    #[inline]
182
0
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
183
0
        str::fmt(self, formatter)
184
0
    }
185
}