xref: /aosp_15_r20/external/cronet/third_party/rust/chromium_crates_io/vendor/memchr-2.7.2/src/cow.rs (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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)]
deref(&self) -> &[u8]31     fn deref(&self) -> &[u8] {
32         self.as_slice()
33     }
34 }
35 
36 impl<'a> CowBytes<'a> {
37     /// Create a new borrowed CowBytes.
38     #[inline(always)]
new<B: ?Sized + AsRef<[u8]>>(bytes: &'a B) -> CowBytes<'a>39     pub(crate) fn new<B: ?Sized + AsRef<[u8]>>(bytes: &'a B) -> CowBytes<'a> {
40         CowBytes(Imp::new(bytes.as_ref()))
41     }
42 
43     /// Create a new owned CowBytes.
44     #[cfg(feature = "alloc")]
45     #[inline(always)]
new_owned(bytes: alloc::boxed::Box<[u8]>) -> CowBytes<'static>46     fn new_owned(bytes: alloc::boxed::Box<[u8]>) -> CowBytes<'static> {
47         CowBytes(Imp::Owned(bytes))
48     }
49 
50     /// Return a borrowed byte string, regardless of whether this is an owned
51     /// or borrowed byte string internally.
52     #[inline(always)]
as_slice(&self) -> &[u8]53     pub(crate) fn as_slice(&self) -> &[u8] {
54         self.0.as_slice()
55     }
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)]
into_owned(self) -> CowBytes<'static>63     pub(crate) fn into_owned(self) -> CowBytes<'static> {
64         match self.0 {
65             Imp::Borrowed(b) => {
66                 CowBytes::new_owned(alloc::boxed::Box::from(b))
67             }
68             Imp::Owned(b) => CowBytes::new_owned(b),
69         }
70     }
71 }
72 
73 impl<'a> Imp<'a> {
74     #[inline(always)]
new(bytes: &'a [u8]) -> Imp<'a>75     pub fn new(bytes: &'a [u8]) -> Imp<'a> {
76         #[cfg(feature = "alloc")]
77         {
78             Imp::Borrowed(bytes)
79         }
80         #[cfg(not(feature = "alloc"))]
81         {
82             Imp(bytes)
83         }
84     }
85 
86     #[cfg(feature = "alloc")]
87     #[inline(always)]
as_slice(&self) -> &[u8]88     pub fn as_slice(&self) -> &[u8] {
89         #[cfg(feature = "alloc")]
90         {
91             match self {
92                 Imp::Owned(ref x) => x,
93                 Imp::Borrowed(x) => x,
94             }
95         }
96         #[cfg(not(feature = "alloc"))]
97         {
98             self.0
99         }
100     }
101 
102     #[cfg(not(feature = "alloc"))]
103     #[inline(always)]
as_slice(&self) -> &[u8]104     pub fn as_slice(&self) -> &[u8] {
105         self.0
106     }
107 }
108