tiny_str/
cow.rs

1//! Cow implementation for TinyVec
2
3use core::fmt::Debug;
4use core::ops::Deref;
5
6#[cfg(feature = "alloc")]
7use alloc::{
8    boxed::Box,
9    string::String,
10};
11
12use crate::{TinyString, TinyVec};
13
14/// A Copy-on-Write struct for a TinyVec
15///
16/// This struct contains either a borrowed reference of [T],
17/// or an owned TinyVec
18///
19/// # Example
20/// ```
21/// use tiny_str::{TinyString, Cow};
22///
23/// let string = TinyString::<5>::from("Hello, wo");
24/// let string = Cow::from(string);
25/// assert_eq!(&string, "Hello, wo");
26/// assert!(string.is_owned());
27///
28/// let mut borrowed_cow = Cow::from(&string);
29/// assert_eq!(borrowed_cow.as_str(), "Hello, wo");
30/// assert!(borrowed_cow.is_borrowed());
31///
32/// borrowed_cow.to_mut().push_str("rld!");
33/// assert_eq!(&string, "Hello, wo");
34/// assert_eq!(borrowed_cow.as_str(), "Hello, world!");
35/// assert!(borrowed_cow.is_owned());
36/// ```
37pub enum Cow<'borrow, const N: usize> {
38    Borrowed(&'borrow str),
39    Owned(TinyString<N>),
40}
41
42impl<'borrow, const N: usize> Cow<'borrow, N> {
43    /// Converts this [Cow] into an [Owned](Cow::Owned) variant
44    pub fn to_owned(&mut self) {
45        if let Cow::Borrowed(b) = self {
46            unsafe {
47                let utf8 = TinyVec::from_slice_copied(b.as_bytes());
48                let tv = TinyString::<N>::from_utf8_unchecked(utf8);
49                *self = Cow::Owned(tv)
50            }
51        }
52    }
53
54    /// Consumes this [Cow] and returns an [Owned](Cow::Owned) variant
55    pub fn into_owned(mut self) -> TinyString<N> {
56        self.to_owned();
57        match self {
58            Cow::Owned(w) => w,
59            Cow::Borrowed(_) => unreachable!("Self::to_owned must've turn self into an Owned variant"),
60        }
61    }
62
63    /// Gets a mutable reference to the [Owned] variant.
64    /// If this `Cow` is borrowed, it turns it into an [Owned]
65    /// variant first
66    ///
67    /// [Owned]: Cow::Owned
68    pub fn to_mut(&mut self) -> &mut TinyString<N> {
69        self.to_owned();
70        match self {
71            Cow::Owned(w) => w,
72            Cow::Borrowed(_) => unreachable!("Self::to_owned must've turn self into an Owned variant"),
73        }
74    }
75
76    /// Returns true if `self` is a [Borrowed](Cow::Borrowed) variant
77    pub const fn is_borrowed(&self) -> bool {
78        matches!(self, Cow::Borrowed(_))
79    }
80
81    /// Returns true if `self` is an [Owned](Cow::Owned) variant
82    pub const fn is_owned(&self) -> bool {
83        matches!(self, Cow::Owned(_))
84    }
85
86    /// Returns true if this [Cow] lives on the stack.
87    /// This is:
88    /// - It is a [Borrowed](Cow::Borrowed) variant
89    /// - It is an [Owned](Cow::Owned) variant that lives on the stack
90    pub const fn lives_on_stack(&self) -> bool {
91        match self {
92            Cow::Borrowed(_) => true,
93            Cow::Owned(v) => v.lives_on_stack(),
94        }
95    }
96
97    /// Returns `self` as a string reference
98    pub const fn as_str(&self) -> &str {
99        match self {
100            Cow::Borrowed(items) => items,
101            Cow::Owned(tiny_string) => tiny_string.as_str()
102        }
103    }
104}
105
106impl<'borrow, const N: usize> Deref for Cow<'borrow, N> {
107    type Target = str;
108
109    fn deref(&self) -> &Self::Target {
110        self.as_str()
111    }
112}
113
114impl<'borrow, const N: usize> From<&'borrow str> for Cow<'borrow, N> {
115    fn from(value: &'borrow str) -> Self {
116        Self::Borrowed(value)
117    }
118}
119
120impl<'borrow, 'b2, const N: usize> From<&'b2 Cow<'borrow, N>> for Cow<'b2, N> {
121    fn from(value: &'b2 Cow<'borrow, N>) -> Self {
122        Cow::Borrowed(value.as_str())
123    }
124}
125
126impl<'borrow, const N: usize> From<TinyString<N>> for Cow<'borrow, N> {
127    fn from(value: TinyString<N>) -> Self {
128        Self::Owned(value)
129    }
130}
131
132impl<'borrow, const N: usize> From<&'borrow TinyString<N>> for Cow<'borrow, N> {
133    fn from(value: &'borrow TinyString<N>) -> Self {
134        Self::Borrowed(value)
135    }
136}
137
138#[cfg(feature = "alloc")]
139impl<'borrow, const N: usize> From<String> for Cow<'borrow, N> {
140    fn from(value: String) -> Self {
141        Self::Owned(TinyString::from(value))
142    }
143}
144
145#[cfg(feature = "alloc")]
146impl<'borrow, const N: usize> From<Box<str>> for Cow<'borrow, N> {
147    fn from(value: Box<str>) -> Self {
148        Self::Owned(TinyString::from(value))
149    }
150}
151
152impl<'borrow, const N: usize> Debug for Cow<'borrow, N> {
153    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
154        match self {
155            Self::Borrowed(arg0) => f.debug_tuple("Borrowed").field(arg0).finish(),
156            Self::Owned(arg0) => f.debug_tuple("Owned").field(arg0).finish(),
157        }
158    }
159}
160
161impl<'borrow, const N: usize> PartialEq for Cow<'borrow, N> {
162    fn eq(&self, other: &Self) -> bool {
163        match (self, other) {
164            (Self::Borrowed(l0), Self::Borrowed(r0)) => l0 == r0,
165            (Self::Owned(l0), Self::Owned(r0)) => l0 == r0,
166            _ => false,
167        }
168    }
169}
170
171impl<'borrow, const N: usize> PartialEq<str> for Cow<'borrow, N> {
172    fn eq(&self, other: &str) -> bool {
173        self.as_str() == other
174    }
175}
176
177impl<'borrow, const N: usize> PartialEq<Cow<'borrow, N>> for str {
178    fn eq(&self, other: &Cow<'borrow, N>) -> bool {
179        self == other.as_str()
180    }
181}
182
183impl<'borrow, const N: usize> Clone for Cow<'borrow, N> {
184    fn clone(&self) -> Self {
185        match self {
186            Self::Borrowed(arg0) => Self::Borrowed(arg0),
187            Self::Owned(arg0) => Self::Owned(arg0.clone()),
188        }
189    }
190}
191
192impl<'borrow, const N: usize> Default for Cow<'borrow, N> {
193    fn default() -> Self {
194        Self::Borrowed("")
195    }
196}