1use core::fmt::Debug;
4use core::ops::{Add, AddAssign, Deref};
5
6#[cfg(feature = "alloc")]
7use alloc::{
8 boxed::Box,
9 string::String,
10};
11
12use crate::{TinyString, TinyVec};
13
14pub 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 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 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 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 pub const fn is_borrowed(&self) -> bool {
78 matches!(self, Cow::Borrowed(_))
79 }
80
81 pub const fn is_owned(&self) -> bool {
83 matches!(self, Cow::Owned(_))
84 }
85
86 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 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 pub const fn as_bytes(&self) -> &[u8] {
107 match self {
108 Cow::Borrowed(b) => b.as_bytes(),
109 Cow::Owned(s) => s.as_bytes(),
110 }
111 }
112}
113
114impl<'borrow, const N: usize> Deref for Cow<'borrow, N> {
115 type Target = str;
116
117 fn deref(&self) -> &Self::Target {
118 self.as_str()
119 }
120}
121
122impl<'borrow, const N: usize> From<&'borrow str> for Cow<'borrow, N> {
123 fn from(value: &'borrow str) -> Self {
124 Self::Borrowed(value)
125 }
126}
127
128impl<'borrow, 'b2, const N: usize> From<&'b2 Cow<'borrow, N>> for Cow<'b2, N> {
129 fn from(value: &'b2 Cow<'borrow, N>) -> Self {
130 Cow::Borrowed(value.as_str())
131 }
132}
133
134impl<'borrow, const N: usize> From<TinyString<N>> for Cow<'borrow, N> {
135 fn from(value: TinyString<N>) -> Self {
136 Self::Owned(value)
137 }
138}
139
140impl<'borrow, const N: usize> From<&'borrow TinyString<N>> for Cow<'borrow, N> {
141 fn from(value: &'borrow TinyString<N>) -> Self {
142 Self::Borrowed(value)
143 }
144}
145
146#[cfg(feature = "alloc")]
147impl<'borrow, const N: usize> From<String> for Cow<'borrow, N> {
148 fn from(value: String) -> Self {
149 Self::Owned(TinyString::from(value))
150 }
151}
152
153#[cfg(feature = "alloc")]
154impl<'borrow, const N: usize> From<Box<str>> for Cow<'borrow, N> {
155 fn from(value: Box<str>) -> Self {
156 Self::Owned(TinyString::from(value))
157 }
158}
159
160impl<'borrow, const N: usize> Debug for Cow<'borrow, N> {
161 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
162 match self {
163 Self::Borrowed(arg0) => f.debug_tuple("Borrowed").field(arg0).finish(),
164 Self::Owned(arg0) => f.debug_tuple("Owned").field(arg0).finish(),
165 }
166 }
167}
168
169impl<'borrow, const N: usize> Eq for Cow<'borrow, N> {}
170impl<'borrow, const N: usize> Ord for Cow<'borrow, N> {
171 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
172 self.as_bytes().cmp(other.as_bytes())
173 }
174}
175
176impl<'borrow, const N: usize> PartialEq<Cow<'borrow, N>> for Cow<'borrow, N> {
177 fn eq(&self, other: &Cow<'borrow, N>) -> bool {
178 other.as_bytes() == self.as_bytes()
179 }
180}
181
182impl<'borrow, const N: usize> PartialOrd<Cow<'borrow, N>> for Cow<'borrow, N> {
183 fn partial_cmp(&self, other: &Cow<'borrow, N>) -> Option<core::cmp::Ordering> {
184 Some(self.cmp(other))
185 }
186}
187
188impl<'borrow, const N: usize> PartialEq<str> for Cow<'borrow, N> {
189 fn eq(&self, other: &str) -> bool {
190 self.as_str() == other
191 }
192}
193
194impl<'borrow, const N: usize> PartialEq<Cow<'borrow, N>> for str {
195 fn eq(&self, other: &Cow<'borrow, N>) -> bool {
196 other.as_str() == self
197 }
198}
199
200impl<'borrow, const N: usize> PartialEq<&str> for Cow<'borrow, N> {
201 fn eq(&self, other: &&str) -> bool {
202 self.as_str() == *other
203 }
204}
205
206impl<'borrow, const N: usize> PartialEq<Cow<'borrow, N>> for &str {
207 fn eq(&self, other: &Cow<'borrow, N>) -> bool {
208 other.as_str() == *self
209 }
210}
211
212impl<'borrow, const N: usize> PartialEq<[u8]> for Cow<'borrow, N> {
213 fn eq(&self, other: &[u8]) -> bool {
214 self.as_bytes() == other
215 }
216}
217
218impl<'borrow, const N: usize> PartialEq<Cow<'borrow, N>> for [u8]{
219 fn eq(&self, other: &Cow<'borrow, N>) -> bool {
220 other.as_bytes() == self
221 }
222}
223
224impl<'borrow, const N: usize> PartialOrd<[u8]> for Cow<'borrow, N> {
225 fn partial_cmp(&self, other: &[u8]) -> Option<core::cmp::Ordering> {
226 self.as_bytes().partial_cmp(other)
227 }
228}
229
230impl<'borrow, const N: usize> PartialOrd<Cow<'borrow, N>> for [u8]{
231 fn partial_cmp(&self, other: &Cow<'borrow, N>) -> Option<core::cmp::Ordering> {
232 self.partial_cmp(other.as_bytes())
233 }
234}
235
236impl<'borrow, const N: usize> PartialOrd<str> for Cow<'borrow, N> {
237 fn partial_cmp(&self, other: &str) -> Option<core::cmp::Ordering> {
238 self.as_str().partial_cmp(other)
239 }
240}
241
242impl<'borrow, const N: usize> PartialOrd<Cow<'borrow, N>> for str {
243 fn partial_cmp(&self, other: &Cow<'borrow, N>) -> Option<core::cmp::Ordering> {
244 self.partial_cmp(other.as_str())
245 }
246}
247
248impl<'borrow, const N: usize> PartialOrd<&str> for Cow<'borrow, N> {
249 fn partial_cmp(&self, other: &&str) -> Option<core::cmp::Ordering> {
250 self.as_str().partial_cmp(*other)
251 }
252}
253
254impl<'borrow, const N: usize> PartialOrd<Cow<'borrow, N>> for &str {
255 fn partial_cmp(&self, other: &Cow<'borrow, N>) -> Option<core::cmp::Ordering> {
256 self.partial_cmp(&other.as_str())
257 }
258}
259
260impl<'borrow, const N: usize> Clone for Cow<'borrow, N> {
261 fn clone(&self) -> Self {
262 match self {
263 Self::Borrowed(arg0) => Self::Borrowed(arg0),
264 Self::Owned(arg0) => Self::Owned(arg0.clone()),
265 }
266 }
267}
268
269impl<'borrow, const N: usize> Default for Cow<'borrow, N> {
270 fn default() -> Self {
271 Self::Borrowed("")
272 }
273}
274
275impl<'borrow, const N: usize> Add for Cow<'borrow, N> {
276 type Output = Cow<'borrow, N>;
277
278 fn add(mut self, rhs: Self) -> Self::Output {
279 self += rhs;
280 self
281 }
282}
283
284impl<'borrow, const N: usize> Add<&'borrow str> for Cow<'borrow, N> {
285 type Output = Cow<'borrow, N>;
286
287 fn add(mut self, rhs: &'borrow str) -> Self::Output {
288 self += rhs;
289 self
290 }
291}
292
293impl<'borrow, const N: usize> AddAssign<&'borrow str> for Cow<'borrow, N> {
294 fn add_assign(&mut self, rhs: &'borrow str) {
295 if self.is_empty() {
296 *self = Cow::Borrowed(rhs)
297 } else if !rhs.is_empty() {
298 if let Cow::Borrowed(b) = self {
299 let mut s = TinyString::with_capacity(b.len() + rhs.len());
300 s.push_str(b);
301 *self = Cow::Owned(s);
302 }
303 self.to_mut().push_str(rhs);
304 }
305 }
306}
307
308impl<'borrow, const N: usize> AddAssign<Cow<'borrow, N>> for Cow<'borrow, N> {
309 fn add_assign(&mut self, rhs: Cow<'borrow, N>) {
310 if self.is_empty() {
311 *self = rhs;
312 } else if !rhs.is_empty() {
313 if let Cow::Borrowed(b) = self {
314 let mut s = TinyString::with_capacity(b.len() + rhs.len());
315 s.push_str(b);
316 *self = Cow::Owned(s);
317 }
318 self.to_mut().push_str(&rhs);
319 }
320 }
321}
322
323#[cfg(test)]
324mod test {
325 use super::*;
326
327 #[test]
328 fn partial_eq() {
329 let s = TinyString::<10>::from("ABCDEF");
330 let cow = Cow::from(s);
331
332 assert_eq!("ABCDEF", cow);
333 }
334}