bstr/
cow.rs

1#[cfg(feature = "std")]
2use std::borrow::Cow;
3use core::ops;
4
5use bstr::BStr;
6#[cfg(feature = "std")]
7use bstring::BString;
8
9/// A specialized copy-on-write BStr.
10///
11/// The purpose of this type is to permit usage of a "borrowed or owned byte
12/// string" in a way that keeps std/no-std compatibility. That is, in no-std
13/// mode, this type devolves into a simple &BStr with no owned variant
14/// availble.
15#[derive(Clone, Debug)]
16pub struct CowBStr<'a>(Imp<'a>);
17
18#[cfg(feature = "std")]
19#[derive(Clone, Debug)]
20struct Imp<'a>(Cow<'a, BStr>);
21
22#[cfg(not(feature = "std"))]
23#[derive(Clone, Debug)]
24struct Imp<'a>(&'a BStr);
25
26impl<'a> ops::Deref for CowBStr<'a> {
27    type Target = BStr;
28
29    fn deref(&self) -> &BStr {
30        self.as_bstr()
31    }
32}
33
34impl<'a> CowBStr<'a> {
35    /// Create a new borrowed CowBStr.
36    pub fn new<B: ?Sized + AsRef<[u8]>>(bytes: &'a B) -> CowBStr<'a> {
37        CowBStr(Imp::new(BStr::new(bytes)))
38    }
39
40    /// Create a new owned CowBStr.
41    #[cfg(feature = "std")]
42    pub fn new_owned(bytes: BString) -> CowBStr<'static> {
43        CowBStr(Imp(Cow::Owned(bytes)))
44    }
45
46    /// Return a borrowed byte string, regardless of whether this is an owned
47    /// or borrowed byte string internally.
48    pub fn as_bstr(&self) -> &BStr {
49        self.0.as_bstr()
50    }
51
52    /// Return an owned version of this copy-on-write byte string.
53    ///
54    /// If this is already an owned byte string internally, then this is a
55    /// no-op. Otherwise, the internal byte string is copied.
56    #[cfg(feature = "std")]
57    pub fn into_owned(self) -> CowBStr<'static> {
58        match (self.0).0 {
59            Cow::Borrowed(b) => CowBStr::new_owned(b.to_bstring()),
60            Cow::Owned(b) => CowBStr::new_owned(b),
61        }
62    }
63}
64
65impl<'a> Imp<'a> {
66    #[cfg(feature = "std")]
67    pub fn new(bytes: &'a BStr) -> Imp<'a> {
68        Imp(Cow::Borrowed(bytes))
69    }
70
71    #[cfg(not(feature = "std"))]
72    pub fn new(bytes: &'a BStr) -> Imp<'a> {
73        Imp(bytes)
74    }
75
76    #[cfg(feature = "std")]
77    pub fn as_bstr(&self) -> &BStr {
78        // &*self.0
79        match self.0 {
80            Cow::Owned(ref x) => x,
81            Cow::Borrowed(x) => x,
82        }
83    }
84
85    #[cfg(not(feature = "std"))]
86    pub fn as_bstr(&self) -> &BStr {
87        self.0
88    }
89}