beef/
generic.rs

1//! This module contains the actual, albeit generic, implementaiton of the `Cow`,
2//! and the traits that are available to it.
3
4use alloc::borrow::{Borrow, Cow as StdCow};
5use alloc::string::String;
6use alloc::vec::Vec;
7use core::cmp::Ordering;
8use core::fmt;
9use core::hash::{Hash, Hasher};
10use core::marker::PhantomData;
11use core::mem::ManuallyDrop;
12use core::ptr::NonNull;
13
14#[cfg(target_pointer_width = "64")]
15use crate::lean::internal::Lean;
16use crate::traits::{Beef, Capacity};
17use crate::wide::internal::Wide;
18
19/// A clone-on-write smart pointer, mostly compatible with [`std::borrow::Cow`](https://doc.rust-lang.org/std/borrow/enum.Cow.html).
20///
21/// This type is using a generic `U: Capacity`. Use either [`beef::Cow`](../type.Cow.html) or [`beef::lean::Cow`](../lean/type.Cow.html) in your code.
22pub struct Cow<'a, T: Beef + ?Sized + 'a, U: Capacity> {
23    /// Pointer to data
24    ptr: NonNull<T::PointerT>,
25
26    /// This usize contains length, but it may contain other
27    /// information pending on impl of `Capacity`, and must therefore
28    /// always go through `U::len` or `U::unpack`
29    fat: usize,
30
31    /// Capacity field. For `beef::lean::Cow` this is 0-sized!
32    cap: U::Field,
33
34    /// Lifetime marker
35    marker: PhantomData<&'a T>,
36}
37
38impl<T, U> Cow<'_, T, U>
39where
40    T: Beef + ?Sized,
41    U: Capacity,
42{
43    /// Owned data.
44    ///
45    /// # Example
46    ///
47    /// ```rust
48    /// use beef::Cow;
49    ///
50    /// let owned: Cow<str> = Cow::owned("I own my content".to_string());
51    /// ```
52    #[inline]
53    pub fn owned(val: T::Owned) -> Self {
54        let (ptr, fat, cap) = T::owned_into_parts::<U>(val);
55
56        Cow {
57            ptr,
58            fat,
59            cap,
60            marker: PhantomData,
61        }
62    }
63}
64
65impl<'a, T, U> Cow<'a, T, U>
66where
67    T: Beef + ?Sized,
68    U: Capacity,
69{
70    /// Borrowed data.
71    ///
72    /// # Example
73    ///
74    /// ```rust
75    /// use beef::Cow;
76    ///
77    /// let borrowed: Cow<str> = Cow::borrowed("I'm just a borrow");
78    /// ```
79    #[inline]
80    pub fn borrowed(val: &'a T) -> Self {
81        let (ptr, fat, cap) = T::ref_into_parts::<U>(val);
82
83        Cow {
84            ptr,
85            fat,
86            cap,
87            marker: PhantomData,
88        }
89    }
90
91    /// Extracts the owned data.
92    ///
93    /// Clones the data if it is not already owned.
94    #[inline]
95    pub fn into_owned(self) -> T::Owned {
96        let cow = ManuallyDrop::new(self);
97
98        match cow.capacity() {
99            Some(capacity) => unsafe { T::owned_from_parts::<U>(cow.ptr, cow.fat, capacity) },
100            None => unsafe { &*T::ref_from_parts::<U>(cow.ptr, cow.fat) }.to_owned(),
101        }
102    }
103
104    /// Extracts borrowed data.
105    ///
106    /// Panics: If the data is owned.
107    #[inline]
108    pub fn unwrap_borrowed(self) -> &'a T {
109        if self.capacity().is_some() {
110            panic!("Can not turn owned beef::Cow into a borrowed value")
111        }
112        unsafe { &*T::ref_from_parts::<U>(self.ptr, self.fat) }
113    }
114
115    /// Returns `true` if data is borrowed or had no capacity.
116    ///
117    /// # Example
118    ///
119    /// ```rust
120    /// use beef::Cow;
121    ///
122    /// let borrowed: Cow<str> = Cow::borrowed("Borrowed");
123    /// let no_capacity: Cow<str> = Cow::owned(String::new());
124    /// let owned: Cow<str> = Cow::owned(String::from("Owned"));
125    ///
126    /// assert_eq!(borrowed.is_borrowed(), true);
127    /// assert_eq!(no_capacity.is_borrowed(), true);
128    /// assert_eq!(owned.is_borrowed(), false);
129    /// ```
130    #[inline]
131    pub fn is_borrowed(&self) -> bool {
132        self.capacity().is_none()
133    }
134
135    /// Returns `true` if data is owned and has non-0 capacity.
136    ///
137    /// # Example
138    ///
139    /// ```rust
140    /// use beef::Cow;
141    ///
142    /// let borrowed: Cow<str> = Cow::borrowed("Borrowed");
143    /// let no_capacity: Cow<str> = Cow::owned(String::new());
144    /// let owned: Cow<str> = Cow::owned(String::from("Owned"));
145    ///
146    /// assert_eq!(borrowed.is_owned(), false);
147    /// assert_eq!(no_capacity.is_owned(), false);
148    /// assert_eq!(owned.is_owned(), true);
149    /// ```
150    #[inline]
151    pub fn is_owned(&self) -> bool {
152        self.capacity().is_some()
153    }
154
155    /// Internal convenience method for casting `ptr` into a `&T`
156    #[inline]
157    fn borrow(&self) -> &T {
158        unsafe { &*T::ref_from_parts::<U>(self.ptr, self.fat) }
159    }
160
161    #[inline]
162    fn capacity(&self) -> Option<U::NonZero> {
163        U::maybe(self.fat, self.cap)
164    }
165}
166
167impl<'a> Cow<'a, str, Wide> {
168    /// Borrowed data.
169    ///
170    /// This is functionally identical to [`borrow`](./generic/struct.Cow.html#method.borrow).
171    /// We use impl specialization to allow this function to be `const`.
172    ///
173    /// # Example
174    ///
175    /// ```rust
176    /// use beef::Cow;
177    ///
178    /// const HELLO: Cow<str> = Cow::const_str("Hello");
179    /// ```
180    pub const fn const_str(val: &'a str) -> Self {
181        Cow {
182            // We are casting *const T to *mut T, however for all borrowed values
183            // this raw pointer is only ever dereferenced back to &T.
184            ptr: unsafe { NonNull::new_unchecked(val.as_ptr() as *mut u8) },
185            fat: val.len(),
186            cap: None,
187            marker: PhantomData,
188        }
189    }
190}
191
192#[cfg(target_pointer_width = "64")]
193impl<'a> Cow<'a, str, Lean> {
194    /// Borrowed data.
195    ///
196    /// This is functionally identical to [`borrow`](./generic/struct.Cow.html#method.borrow).
197    /// We use impl specialization to allow this function to be `const`.
198    ///
199    /// # Example
200    ///
201    /// ```rust
202    /// use beef::lean::Cow;
203    ///
204    /// const HELLO: Cow<str> = Cow::const_str("Hello");
205    /// ```
206    pub const fn const_str(val: &'a str) -> Self {
207        Cow {
208            // We are casting *const T to *mut T, however for all borrowed values
209            // this raw pointer is only ever dereferenced back to &T.
210            ptr: unsafe { NonNull::new_unchecked(val.as_ptr() as *mut u8) },
211            fat: Lean::mask_len(val.len()),
212            cap: Lean,
213            marker: PhantomData,
214        }
215    }
216}
217
218// This requires nightly:
219// https://github.com/rust-lang/rust/issues/57563
220#[cfg(feature = "const_fn")]
221impl<'a, T> Cow<'a, [T], Wide>
222where
223    T: Clone,
224{
225    /// Borrowed data.
226    ///
227    /// This is functionally identical to [`borrow`](./generic/struct.Cow.html#method.borrow).
228    /// We use impl specialization to allow this function to be `const`.
229    ///
230    /// # Example
231    ///
232    /// ```rust
233    /// use beef::Cow;
234    ///
235    /// const HELLO: Cow<[u8]> = Cow::const_slice(&[1, 2, 3]);
236    /// ```
237    pub const fn const_slice(val: &'a [T]) -> Self {
238        Cow {
239            // We are casting *const T to *mut T, however for all borrowed values
240            // this raw pointer is only ever dereferenced back to &T.
241            ptr: unsafe { NonNull::new_unchecked(val.as_ptr() as *mut T) },
242            fat: val.len(),
243            cap: None,
244            marker: PhantomData,
245        }
246    }
247}
248
249// This requires nightly:
250// https://github.com/rust-lang/rust/issues/57563
251#[cfg(all(feature = "const_fn", target_pointer_width = "64"))]
252impl<'a, T> Cow<'a, [T], Lean>
253where
254    T: Clone,
255{
256    /// Borrowed data.
257    ///
258    /// This i functionally identical to [`borrow`](./generic/struct.Cow.html#method.borrow).
259    /// We use impl specialization to allow this function to be `const`.
260    ///
261    /// # Example
262    ///
263    /// ```rust
264    /// use beef::lean::Cow;
265    ///
266    /// const HELLO: Cow<[u8]> = Cow::const_slice(&[1, 2, 3]);
267    /// ```
268    pub const fn const_slice(val: &'a [T]) -> Self {
269        Cow {
270            // We are casting *const T to *mut T, however for all borrowed values
271            // this raw pointer is only ever dereferenced back to &T.
272            ptr: unsafe { NonNull::new_unchecked(val.as_ptr() as *mut T) },
273            fat: Lean::mask_len(val.len()),
274            cap: Lean,
275            marker: PhantomData,
276        }
277    }
278}
279
280impl<T, U> Hash for Cow<'_, T, U>
281where
282    T: Hash + Beef + ?Sized,
283    U: Capacity,
284{
285    #[inline]
286    fn hash<H: Hasher>(&self, state: &mut H) {
287        self.borrow().hash(state)
288    }
289}
290
291impl<'a, T, U> Default for Cow<'a, T, U>
292where
293    T: Beef + ?Sized,
294    U: Capacity,
295    &'a T: Default,
296{
297    #[inline]
298    fn default() -> Self {
299        Cow::borrowed(Default::default())
300    }
301}
302
303impl<T, U> Eq for Cow<'_, T, U>
304where
305    T: Eq + Beef + ?Sized,
306    U: Capacity,
307{
308}
309
310impl<A, B, U, V> PartialOrd<Cow<'_, B, V>> for Cow<'_, A, U>
311where
312    A: Beef + ?Sized + PartialOrd<B>,
313    B: Beef + ?Sized,
314    U: Capacity,
315    V: Capacity,
316{
317    #[inline]
318    fn partial_cmp(&self, other: &Cow<'_, B, V>) -> Option<Ordering> {
319        PartialOrd::partial_cmp(self.borrow(), other.borrow())
320    }
321}
322
323impl<T, U> Ord for Cow<'_, T, U>
324where
325    T: Ord + Beef + ?Sized,
326    U: Capacity,
327{
328    #[inline]
329    fn cmp(&self, other: &Self) -> Ordering {
330        Ord::cmp(self.borrow(), other.borrow())
331    }
332}
333
334impl<'a, T, U> From<&'a T> for Cow<'a, T, U>
335where
336    T: Beef + ?Sized,
337    U: Capacity,
338{
339    #[inline]
340    fn from(val: &'a T) -> Self {
341        Cow::borrowed(val)
342    }
343}
344
345impl<U> From<String> for Cow<'_, str, U>
346where
347    U: Capacity,
348{
349    #[inline]
350    fn from(s: String) -> Self {
351        Cow::owned(s)
352    }
353}
354
355impl<T, U> From<Vec<T>> for Cow<'_, [T], U>
356where
357    T: Clone,
358    U: Capacity,
359{
360    #[inline]
361    fn from(v: Vec<T>) -> Self {
362        Cow::owned(v)
363    }
364}
365
366impl<T, U> Drop for Cow<'_, T, U>
367where
368    T: Beef + ?Sized,
369    U: Capacity,
370{
371    #[inline]
372    fn drop(&mut self) {
373        if let Some(capacity) = self.capacity() {
374            unsafe { T::owned_from_parts::<U>(self.ptr, self.fat, capacity) };
375        }
376    }
377}
378
379impl<'a, T, U> Clone for Cow<'a, T, U>
380where
381    T: Beef + ?Sized,
382    U: Capacity,
383{
384    #[inline]
385    fn clone(&self) -> Self {
386        match self.capacity() {
387            Some(_) => Cow::owned(self.borrow().to_owned()),
388            None => Cow { ..*self },
389        }
390    }
391}
392
393impl<T, U> core::ops::Deref for Cow<'_, T, U>
394where
395    T: Beef + ?Sized,
396    U: Capacity,
397{
398    type Target = T;
399
400    #[inline]
401    fn deref(&self) -> &T {
402        self.borrow()
403    }
404}
405
406impl<T, U> AsRef<T> for Cow<'_, T, U>
407where
408    T: Beef + ?Sized,
409    U: Capacity,
410{
411    #[inline]
412    fn as_ref(&self) -> &T {
413        self.borrow()
414    }
415}
416
417impl<T, U> Borrow<T> for Cow<'_, T, U>
418where
419    T: Beef + ?Sized,
420    U: Capacity,
421{
422    #[inline]
423    fn borrow(&self) -> &T {
424        self.borrow()
425    }
426}
427
428impl<'a, T, U> From<StdCow<'a, T>> for Cow<'a, T, U>
429where
430    T: Beef + ?Sized,
431    U: Capacity,
432{
433    #[inline]
434    fn from(stdcow: StdCow<'a, T>) -> Self {
435        match stdcow {
436            StdCow::Borrowed(v) => Self::borrowed(v),
437            StdCow::Owned(v) => Self::owned(v),
438        }
439    }
440}
441
442impl<'a, T, U> From<Cow<'a, T, U>> for StdCow<'a, T>
443where
444    T: Beef + ?Sized,
445    U: Capacity,
446{
447    #[inline]
448    fn from(cow: Cow<'a, T, U>) -> Self {
449        let cow = ManuallyDrop::new(cow);
450
451        match cow.capacity() {
452            Some(capacity) => {
453                StdCow::Owned(unsafe { T::owned_from_parts::<U>(cow.ptr, cow.fat, capacity) })
454            }
455            None => StdCow::Borrowed(unsafe { &*T::ref_from_parts::<U>(cow.ptr, cow.fat) }),
456        }
457    }
458}
459
460impl<A, B, U, V> PartialEq<Cow<'_, B, V>> for Cow<'_, A, U>
461where
462    A: Beef + ?Sized,
463    B: Beef + ?Sized,
464    U: Capacity,
465    V: Capacity,
466    A: PartialEq<B>,
467{
468    fn eq(&self, other: &Cow<B, V>) -> bool {
469        self.borrow() == other.borrow()
470    }
471}
472
473macro_rules! impl_eq {
474    ($($(@for< $bounds:tt >)? $ptr:ty => $([$($deref:tt)+])? <$with:ty>,)*) => {$(
475        impl<U $(, $bounds)*> PartialEq<$with> for Cow<'_, $ptr, U>
476        where
477            U: Capacity,
478            $( $bounds: Clone + PartialEq, )*
479        {
480            #[inline]
481            fn eq(&self, other: &$with) -> bool {
482                self.borrow() == $($($deref)*)* other
483            }
484        }
485
486        impl<U $(, $bounds)*> PartialEq<Cow<'_, $ptr, U>> for $with
487        where
488            U: Capacity,
489            $( $bounds: Clone + PartialEq, )*
490        {
491            #[inline]
492            fn eq(&self, other: &Cow<$ptr, U>) -> bool {
493                $($($deref)*)* self == other.borrow()
494            }
495        }
496    )*};
497}
498
499impl_eq! {
500    str => <str>,
501    str => [*]<&str>,
502    str => <String>,
503    @for<T> [T] => <[T]>,
504    @for<T> [T] => [*]<&[T]>,
505    @for<T> [T] => [&**]<Vec<T>>,
506}
507
508impl<T, U> fmt::Debug for Cow<'_, T, U>
509where
510    T: Beef + fmt::Debug + ?Sized,
511    U: Capacity,
512{
513    #[inline]
514    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
515        self.borrow().fmt(f)
516    }
517}
518
519impl<T, U> fmt::Display for Cow<'_, T, U>
520where
521    T: Beef + fmt::Display + ?Sized,
522    U: Capacity,
523{
524    #[inline]
525    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
526        self.borrow().fmt(f)
527    }
528}
529
530// Safety: Same bounds as `std::borrow::Cow`.
531unsafe impl<T, U> Sync for Cow<'_, T, U>
532where
533    U: Capacity,
534    T: Beef + Sync + ?Sized,
535    T::Owned: Sync,
536{
537}
538
539unsafe impl<T, U> Send for Cow<'_, T, U>
540where
541    U: Capacity,
542    T: Beef + Sync + ?Sized,
543    T::Owned: Send,
544{
545}
546
547impl<T, U> Unpin for Cow<'_, T, U>
548where
549    U: Capacity,
550    T: Beef + ?Sized,
551    T::Owned: Unpin,
552{
553}