1use std::any::Any;
12use std::fmt;
13use std::ops::Deref;
14use std::ptr::NonNull;
15use std::sync::Arc;
16
17pub enum Buffer<T> {
19 Owned(Arc<Vec<T>>),
21 Borrowed {
24 ptr: NonNull<T>,
25 len: usize,
26 guard: Arc<dyn Any + Send + Sync>,
27 },
28}
29
30unsafe impl<T: Send + Sync> Send for Buffer<T> {}
34unsafe impl<T: Send + Sync> Sync for Buffer<T> {}
35
36impl<T> Buffer<T> {
37 #[inline]
39 pub fn from_vec(v: Vec<T>) -> Self {
40 Buffer::Owned(Arc::new(v))
41 }
42
43 #[inline]
49 pub unsafe fn from_foreign(ptr: NonNull<T>, len: usize, guard: Arc<dyn Any + Send + Sync>) -> Self {
50 Buffer::Borrowed { ptr, len, guard }
51 }
52
53 #[inline]
54 pub fn len(&self) -> usize {
55 match self {
56 Buffer::Owned(a) => a.len(),
57 Buffer::Borrowed { len, .. } => *len,
58 }
59 }
60
61 #[inline]
62 pub fn is_empty(&self) -> bool {
63 self.len() == 0
64 }
65
66 #[inline]
67 pub fn as_slice(&self) -> &[T] {
68 match self {
69 Buffer::Owned(a) => a.as_slice(),
70 Buffer::Borrowed { ptr, len, .. } => unsafe {
72 std::slice::from_raw_parts(ptr.as_ptr(), *len)
73 },
74 }
75 }
76
77 #[inline]
79 pub fn as_ptr(&self) -> *const T {
80 self.as_slice().as_ptr()
81 }
82}
83
84impl<T: Send + Sync + 'static> Buffer<T> {
85 #[inline]
90 pub fn keepalive(&self) -> Arc<dyn Any + Send + Sync> {
91 match self {
92 Buffer::Owned(a) => a.clone(),
93 Buffer::Borrowed { guard, .. } => guard.clone(),
94 }
95 }
96}
97
98impl<T: Clone> Buffer<T> {
99 #[inline]
102 pub fn make_mut(&mut self) -> &mut Vec<T> {
103 if matches!(self, Buffer::Borrowed { .. }) {
104 let owned = self.as_slice().to_vec();
105 *self = Buffer::Owned(Arc::new(owned));
106 }
107 match self {
108 Buffer::Owned(a) => Arc::make_mut(a),
109 Buffer::Borrowed { .. } => unreachable!("materialised to Owned above"), }
111 }
112
113 #[inline]
115 pub fn into_vec(self) -> Vec<T> {
116 match self {
117 Buffer::Owned(a) => Arc::try_unwrap(a).unwrap_or_else(|a| (*a).clone()),
118 Buffer::Borrowed { .. } => self.as_slice().to_vec(),
119 }
120 }
121}
122
123impl<T> Deref for Buffer<T> {
124 type Target = [T];
125 #[inline]
126 fn deref(&self) -> &[T] {
127 self.as_slice()
128 }
129}
130
131impl<T: Clone> Clone for Buffer<T> {
132 #[inline]
133 fn clone(&self) -> Self {
134 match self {
135 Buffer::Owned(a) => Buffer::Owned(Arc::clone(a)),
136 Buffer::Borrowed { ptr, len, guard } => Buffer::Borrowed {
137 ptr: *ptr,
138 len: *len,
139 guard: Arc::clone(guard),
140 },
141 }
142 }
143}
144
145impl<T: PartialEq> PartialEq for Buffer<T> {
146 #[inline]
147 fn eq(&self, other: &Self) -> bool {
148 self.as_slice() == other.as_slice()
149 }
150}
151
152impl<T: fmt::Debug> fmt::Debug for Buffer<T> {
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154 f.debug_list().entries(self.as_slice().iter()).finish()
155 }
156}
157
158impl<T> From<Vec<T>> for Buffer<T> {
159 #[inline]
160 fn from(v: Vec<T>) -> Self {
161 Buffer::from_vec(v)
162 }
163}
164
165#[cfg(test)]
166mod tests {
167 use super::*;
168
169 fn borrowed(v: Vec<f64>) -> Buffer<f64> {
172 let arc = Arc::new(v);
173 let ptr = NonNull::new(arc.as_slice().as_ptr() as *mut f64).unwrap();
174 let len = arc.len();
175 unsafe { Buffer::from_foreign(ptr, len, arc) }
177 }
178
179 #[test]
180 fn owned_basics() {
181 let b = Buffer::from_vec(vec![1.0, 2.0, 3.0]);
182 assert_eq!(b.len(), 3);
183 assert!(!b.is_empty());
184 assert_eq!(b.as_slice(), &[1.0, 2.0, 3.0]);
185 assert_eq!(&*b, &[1.0, 2.0, 3.0]); assert!(Buffer::<f64>::from_vec(vec![]).is_empty());
187 assert_eq!(Buffer::from(vec![1.0]).into_vec(), vec![1.0]); assert_eq!(format!("{:?}", b), "[1.0, 2.0, 3.0]"); assert_eq!(b, b.clone()); }
191
192 #[test]
193 fn borrowed_reads_zero_copy() {
194 let b = borrowed(vec![1.0, 2.0, 3.0]);
195 assert_eq!(b.len(), 3);
196 assert!(!b.is_empty());
197 assert_eq!(b.as_slice(), &[1.0, 2.0, 3.0]);
198 let c = b.clone(); assert_eq!(c.as_slice(), &[1.0, 2.0, 3.0]);
200 assert_eq!(b, c); assert_eq!(format!("{:?}", b), "[1.0, 2.0, 3.0]");
202 }
203
204 #[test]
205 fn borrowed_make_mut_materialises_cow() {
206 let mut b = borrowed(vec![1.0, 2.0]);
207 assert!(matches!(b, Buffer::Borrowed { .. }));
208 b.make_mut().push(3.0); assert!(matches!(b, Buffer::Owned(_)));
210 assert_eq!(b.as_slice(), &[1.0, 2.0, 3.0]);
211 b.make_mut().push(4.0);
213 assert_eq!(b.as_slice(), &[1.0, 2.0, 3.0, 4.0]);
214 }
215
216 #[test]
217 fn borrowed_into_vec_copies() {
218 assert_eq!(borrowed(vec![7.0, 8.0]).into_vec(), vec![7.0, 8.0]);
219 let a = Buffer::from_vec(vec![5.0]);
221 let _alias = a.clone();
222 assert_eq!(a.into_vec(), vec![5.0]);
223 }
224}