1use std::ops::Deref;
2use std::{fmt, mem, ptr, slice, str};
3
4#[derive(Clone)]
5pub struct CowStr<'a>(CowVec<'a, u8>);
6
7impl<'a> CowStr<'a> {
8 #[inline]
9 pub fn borrowed(b: &'a str) -> Self {
10 CowStr(CowVec::borrowed(b.as_bytes()))
11 }
12
13 #[inline]
14 pub fn owned(v: String) -> Self {
15 CowStr(CowVec::owned(v.into_bytes()))
16 }
17
18 #[inline]
19 pub fn into_owned(self) -> String {
20 unsafe { String::from_utf8_unchecked(self.0.into_owned()) }
21 }
22
23 #[inline]
24 pub fn try_owned(self) -> Option<String> {
25 self.0
26 .try_owned()
27 .map(|v| unsafe { String::from_utf8_unchecked(v) })
28 }
29}
30
31impl<'a> PartialEq<&'a str> for CowStr<'a> {
32 fn eq(&self, other: &&str) -> bool {
33 self.as_ref() == *other
34 }
35}
36
37impl<'a> PartialEq<String> for CowStr<'a> {
38 fn eq(&self, other: &String) -> bool {
39 *self == &**other
40 }
41}
42
43impl<'a> PartialEq for CowStr<'a> {
44 fn eq(&self, other: &Self) -> bool {
45 *self == other.as_ref()
46 }
47}
48
49impl<'a> fmt::Debug for CowStr<'a> {
50 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51 self.as_ref().fmt(f)
52 }
53}
54
55impl<'a> fmt::Display for CowStr<'a> {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 self.as_ref().fmt(f)
58 }
59}
60
61impl<'a> From<&'a str> for CowStr<'a> {
62 fn from(other: &'a str) -> Self {
63 CowStr::borrowed(other)
64 }
65}
66
67impl From<String> for CowStr<'static> {
68 fn from(other: String) -> Self {
69 CowStr::owned(other)
70 }
71}
72
73impl<'a> AsRef<str> for CowStr<'a> {
74 #[inline]
75 fn as_ref(&self) -> &str {
76 unsafe { str::from_utf8_unchecked(self.0.as_ref()) }
77 }
78}
79
80impl<'a> Deref for CowStr<'a> {
81 type Target = str;
82
83 #[inline]
84 fn deref(&self) -> &str {
85 unsafe { str::from_utf8_unchecked(self.0.deref()) }
86 }
87}
88
89pub struct CowVec<'a, T: 'a> {
90 ptr: *const T,
91 len: usize,
92 cap: usize,
93 _marker: ::std::marker::PhantomData<&'a [T]>,
94}
95
96impl<'a, T> CowVec<'a, T> {
97 #[inline]
98 pub fn borrowed(b: &'a [T]) -> Self {
99 CowVec {
100 ptr: b.as_ptr(),
101 len: b.len(),
102 cap: 0,
103 _marker: Default::default(),
104 }
105 }
106
107 #[inline]
108 pub fn owned(v: Vec<T>) -> Self {
109 let out = CowVec {
110 ptr: v.as_ptr(),
111 len: v.len(),
112 cap: v.capacity(),
113 _marker: Default::default(),
114 };
115
116 mem::forget(v);
117
118 out
119 }
120
121 #[inline]
122 pub fn into_owned(self) -> Vec<T>
123 where
124 T: Clone,
125 {
126 self.owned_or(|x| x, |a: &_| Vec::from(a))
127 }
128
129 #[inline]
130 pub fn try_owned(self) -> Option<Vec<T>> {
131 self.owned_or(Some, |_: &_| None)
132 }
133
134 fn owned_or<Out, MF, OF>(self, map: MF, or: OF) -> Out
135 where
136 MF: FnOnce(Vec<T>) -> Out,
137 OF: FnOnce(&[T]) -> Out,
138 {
139 let out = if self.cap == 0 {
140 or(self.as_ref())
141 } else {
142 map(unsafe { Vec::from_raw_parts(self.ptr as *mut T, self.len, self.cap) })
143 };
144
145 mem::forget(self);
146
147 out
148 }
149}
150
151impl<'a, T> Clone for CowVec<'a, T>
152where
153 T: Clone,
154{
155 fn clone(&self) -> Self {
156 if self.cap == 0 {
157 CowVec { ..*self }
158 } else {
159 Vec::from(self.as_ref()).into()
160 }
161 }
162}
163
164impl<'a, T> PartialEq<&'a [T]> for CowVec<'a, T>
165where
166 for<'any> &'any [T]: PartialEq,
167{
168 fn eq(&self, other: &&[T]) -> bool {
169 self.as_ref() == *other
170 }
171}
172
173impl<'a, T> PartialEq<Vec<T>> for CowVec<'a, T>
174where
175 for<'any> &'any [T]: PartialEq,
176{
177 fn eq(&self, other: &Vec<T>) -> bool {
178 *self == &**other
179 }
180}
181
182impl<'a, T> PartialEq for CowVec<'a, T>
183where
184 for<'any> &'any [T]: PartialEq,
185{
186 fn eq(&self, other: &Self) -> bool {
187 *self == other.as_ref()
188 }
189}
190
191impl<'a, T> fmt::Debug for CowVec<'a, T>
192where
193 for<'any> &'any [T]: fmt::Debug,
194{
195 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196 self.as_ref().fmt(f)
197 }
198}
199
200impl<'a, T> From<&'a [T]> for CowVec<'a, T> {
201 fn from(other: &'a [T]) -> Self {
202 CowVec::borrowed(other)
203 }
204}
205
206impl<'a, T> From<Vec<T>> for CowVec<'a, T> {
207 fn from(other: Vec<T>) -> Self {
208 CowVec::owned(other)
209 }
210}
211
212impl<'a, T> AsRef<[T]> for CowVec<'a, T> {
213 #[inline]
214 fn as_ref(&self) -> &[T] {
215 unsafe { slice::from_raw_parts(self.ptr, self.len) }
216 }
217}
218
219impl<'a, T> Drop for CowVec<'a, T> {
220 #[inline]
221 fn drop(&mut self) {
222 let _ = unsafe { ptr::read(self) }.try_owned();
223 }
224}
225
226impl<'a, T> Deref for CowVec<'a, T> {
227 type Target = [T];
228
229 #[inline]
230 fn deref(&self) -> &[T] {
231 self.as_ref()
232 }
233}
234
235#[cfg(test)]
236mod tests {
237 use super::{CowStr, CowVec};
238
239 #[test]
240 fn borrowed() {
241 let arr = &[1, 2, 3, 4, 5];
242 let v = CowVec::borrowed(arr);
243
244 assert_eq!(arr, &*v);
245 }
246
247 #[test]
248 fn owned() {
249 let arr = vec![1, 2, 3, 4, 5];
250 let v = CowVec::owned(arr.clone());
251
252 assert_eq!(arr, &*v);
253 }
254
255 #[test]
256 fn borrowed_str() {
257 let msg = "Hello, world!";
258 let v = CowStr::borrowed(msg);
259
260 assert_eq!(msg, &*v);
261 }
262
263 #[test]
264 fn owned_str() {
265 let msg = "Hello, world!".to_owned();
266 let v = CowStr::owned(msg.clone());
267
268 assert_eq!(msg, &*v);
269 }
270}