1mod convert;
4mod extent;
5
6use core::marker::PhantomData;
7use core::mem::ManuallyDrop;
8use core::ptr::NonNull;
9
10use crate::imp;
11use crate::imp::Cow as _;
12
13use self::convert::{Convert, IsOwned};
14
15pub struct Cow<'a, T>
17where
18 T: ?Sized + Convert,
19{
20 ptr: NonNull<T::Ptr>,
22
23 extent: T::Extent,
26
27 marker: PhantomData<&'a T>,
29}
30
31impl<'a, T> imp::Cow<'a, T> for Cow<'a, T>
32where
33 T: ?Sized + Convert,
34{
35 #[inline]
36 fn borrowed(b: &'a T) -> Self {
37 let (ptr, extent) = T::unmake_borrowed(b);
38 Self {
39 ptr,
40 extent,
41 marker: PhantomData,
42 }
43 }
44
45 #[inline]
46 fn owned(o: T::Owned) -> Self {
47 let (ptr, extent) = T::unmake_owned(o);
48 Self {
49 ptr,
50 extent,
51 marker: PhantomData,
52 }
53 }
54
55 #[inline]
56 fn is_borrowed(&self) -> bool {
57 !self.extent.is_owned()
58 }
59
60 #[inline]
61 fn is_owned(&self) -> bool {
62 self.extent.is_owned()
63 }
64
65 #[inline]
66 fn make_ref(&self) -> &T {
67 unsafe { &*T::make_ptr(self.ptr, self.extent) }
69 }
70
71 #[inline]
72 fn into_owned(self) -> T::Owned {
73 if self.is_owned() {
74 let cow = ManuallyDrop::new(self);
75 unsafe { T::make_owned(cow.ptr, cow.extent) }
76 } else {
77 self.make_ref().to_owned()
78 }
79 }
80
81 #[inline]
82 fn apply<F>(&mut self, f: F)
83 where
84 F: FnOnce(&mut T::Owned),
85 {
86 let mut o = if self.is_owned() {
87 let o = unsafe { T::make_owned(self.ptr, self.extent) };
91 self.extent = T::Extent::default();
92 o
93 } else {
94 self.make_ref().to_owned()
95 };
96 f(&mut o);
97 let (ptr, extent) = T::unmake_owned(o);
98 self.ptr = ptr;
99 self.extent = extent;
100 }
101}
102
103impl<T> Clone for Cow<'_, T>
104where
105 T: ?Sized + Convert,
106{
107 #[inline]
108 fn clone(&self) -> Self {
109 if self.is_owned() {
110 Self::owned(self.make_ref().to_owned())
111 } else {
112 Self { ..*self }
113 }
114 }
115}
116
117impl<T> Drop for Cow<'_, T>
118where
119 T: ?Sized + Convert,
120{
121 #[inline]
122 fn drop(&mut self) {
123 if self.is_owned() {
124 unsafe { T::make_owned(self.ptr, self.extent) };
125 }
126 }
127}