Coverage Report

Created: 2025-06-24 06:35

/rust/registry/src/index.crates.io-6f17d22bba15001f/memchr-2.7.5/src/cow.rs
Line
Count
Source (jump to first uncovered line)
1
use core::ops;
2
3
/// A specialized copy-on-write byte string.
4
///
5
/// The purpose of this type is to permit usage of a "borrowed or owned
6
/// byte string" in a way that keeps std/no-std compatibility. That is, in
7
/// no-std/alloc mode, this type devolves into a simple &[u8] with no owned
8
/// variant available. We can't just use a plain Cow because Cow is not in
9
/// core.
10
#[derive(Clone, Debug)]
11
pub struct CowBytes<'a>(Imp<'a>);
12
13
// N.B. We don't use alloc::borrow::Cow here since we can get away with a
14
// Box<[u8]> for our use case, which is 1/3 smaller than the Vec<u8> that
15
// a Cow<[u8]> would use.
16
#[cfg(feature = "alloc")]
17
#[derive(Clone, Debug)]
18
enum Imp<'a> {
19
    Borrowed(&'a [u8]),
20
    Owned(alloc::boxed::Box<[u8]>),
21
}
22
23
#[cfg(not(feature = "alloc"))]
24
#[derive(Clone, Debug)]
25
struct Imp<'a>(&'a [u8]);
26
27
impl<'a> ops::Deref for CowBytes<'a> {
28
    type Target = [u8];
29
30
    #[inline(always)]
31
0
    fn deref(&self) -> &[u8] {
32
0
        self.as_slice()
33
0
    }
34
}
35
36
impl<'a> CowBytes<'a> {
37
    /// Create a new borrowed CowBytes.
38
    #[inline(always)]
39
0
    pub(crate) fn new<B: ?Sized + AsRef<[u8]>>(bytes: &'a B) -> CowBytes<'a> {
40
0
        CowBytes(Imp::new(bytes.as_ref()))
41
0
    }
42
43
    /// Create a new owned CowBytes.
44
    #[cfg(feature = "alloc")]
45
    #[inline(always)]
46
0
    fn new_owned(bytes: alloc::boxed::Box<[u8]>) -> CowBytes<'static> {
47
0
        CowBytes(Imp::Owned(bytes))
48
0
    }
49
50
    /// Return a borrowed byte string, regardless of whether this is an owned
51
    /// or borrowed byte string internally.
52
    #[inline(always)]
53
0
    pub(crate) fn as_slice(&self) -> &[u8] {
54
0
        self.0.as_slice()
55
0
    }
56
57
    /// Return an owned version of this copy-on-write byte string.
58
    ///
59
    /// If this is already an owned byte string internally, then this is a
60
    /// no-op. Otherwise, the internal byte string is copied.
61
    #[cfg(feature = "alloc")]
62
    #[inline(always)]
63
0
    pub(crate) fn into_owned(self) -> CowBytes<'static> {
64
0
        match self.0 {
65
0
            Imp::Borrowed(b) => {
66
0
                CowBytes::new_owned(alloc::boxed::Box::from(b))
67
            }
68
0
            Imp::Owned(b) => CowBytes::new_owned(b),
69
        }
70
0
    }
71
}
72
73
impl<'a> Imp<'a> {
74
    #[inline(always)]
75
0
    pub fn new(bytes: &'a [u8]) -> Imp<'a> {
76
0
        #[cfg(feature = "alloc")]
77
0
        {
78
0
            Imp::Borrowed(bytes)
79
0
        }
80
0
        #[cfg(not(feature = "alloc"))]
81
0
        {
82
0
            Imp(bytes)
83
0
        }
84
0
    }
85
86
    #[cfg(feature = "alloc")]
87
    #[inline(always)]
88
0
    pub fn as_slice(&self) -> &[u8] {
89
0
        #[cfg(feature = "alloc")]
90
0
        {
91
0
            match self {
92
0
                Imp::Owned(ref x) => x,
93
0
                Imp::Borrowed(x) => x,
94
            }
95
        }
96
        #[cfg(not(feature = "alloc"))]
97
        {
98
            self.0
99
        }
100
0
    }
101
102
    #[cfg(not(feature = "alloc"))]
103
    #[inline(always)]
104
    pub fn as_slice(&self) -> &[u8] {
105
        self.0
106
    }
107
}