1use crate::ule::{EncodeAsVarULE, UleError, VarULE};
6#[cfg(feature = "alloc")]
7use alloc::boxed::Box;
8use core::fmt;
9use core::marker::PhantomData;
10#[cfg(feature = "alloc")]
11use core::mem::ManuallyDrop;
12use core::ops::Deref;
13use core::ptr::NonNull;
14use zerofrom::ZeroFrom;
15
16pub struct VarZeroCow<'a, V: ?Sized> {
34 raw: RawVarZeroCow,
37 marker1: PhantomData<&'a V>,
38 #[cfg(feature = "alloc")]
39 marker2: PhantomData<Box<V>>,
40}
41
42struct RawVarZeroCow {
47 buf: NonNull<[u8]>,
55 #[cfg(feature = "alloc")]
57 owned: bool,
58 }
61
62#[cfg(feature = "alloc")]
63impl Drop for RawVarZeroCow {
64 fn drop(&mut self) {
65 if self.owned {
67 unsafe {
68 let _ = Box::<[u8]>::from_raw(self.buf.as_ptr());
71 }
72 }
73 }
74}
75
76unsafe impl Send for RawVarZeroCow {}
78unsafe impl Sync for RawVarZeroCow {}
79
80impl Clone for RawVarZeroCow {
81 fn clone(&self) -> Self {
82 #[cfg(feature = "alloc")]
83 if self.is_owned() {
84 let b: Box<[u8]> = self.as_bytes().into();
86 let b = ManuallyDrop::new(b);
87 let buf: NonNull<[u8]> = (&**b).into();
88 return Self {
89 buf,
93 owned: true,
94 };
95 }
96 Self {
98 buf: self.buf,
102 #[cfg(feature = "alloc")]
103 owned: false,
104 }
105 }
106}
107
108impl<'a, V: ?Sized> Clone for VarZeroCow<'a, V> {
109 fn clone(&self) -> Self {
110 let raw = self.raw.clone();
111 unsafe { Self::from_raw(raw) }
114 }
115}
116
117impl<'a, V: VarULE + ?Sized> VarZeroCow<'a, V> {
118 pub fn parse_bytes(bytes: &'a [u8]) -> Result<Self, UleError> {
120 let val = V::parse_bytes(bytes)?;
121 Ok(Self::new_borrowed(val))
122 }
123
124 #[cfg(feature = "alloc")]
126 pub fn parse_owned_bytes(bytes: Box<[u8]>) -> Result<Self, UleError> {
127 V::validate_bytes(&bytes)?;
128 let bytes = ManuallyDrop::new(bytes);
129 let buf: NonNull<[u8]> = (&**bytes).into();
130 let raw = RawVarZeroCow {
131 buf,
135 owned: true,
136 };
137 Ok(Self {
138 raw,
139 marker1: PhantomData,
140 #[cfg(feature = "alloc")]
141 marker2: PhantomData,
142 })
143 }
144
145 pub const unsafe fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
152 unsafe {
153 let buf: NonNull<[u8]> = NonNull::new_unchecked(bytes as *const [u8] as *mut [u8]);
155 let raw = RawVarZeroCow {
156 buf,
160 #[cfg(feature = "alloc")]
161 owned: false,
162 };
163 Self::from_raw(raw)
165 }
166 }
167
168 #[cfg(feature = "alloc")]
172 pub fn from_encodeable<E: EncodeAsVarULE<V>>(encodeable: &E) -> Self {
173 let b = crate::ule::encode_varule_to_box(encodeable);
174 Self::new_owned(b)
175 }
176
177 pub fn new_borrowed(val: &'a V) -> Self {
179 unsafe {
180 Self::from_bytes_unchecked(val.as_bytes())
182 }
183 }
184
185 #[cfg(feature = "alloc")]
187 pub fn new_owned(val: Box<V>) -> Self {
188 let val = ManuallyDrop::new(val);
189 let buf: NonNull<[u8]> = val.as_bytes().into();
190 let raw = RawVarZeroCow {
191 buf,
195 #[cfg(feature = "alloc")]
196 owned: true,
197 };
198 unsafe { Self::from_raw(raw) }
200 }
201}
202
203impl<'a, V: ?Sized> VarZeroCow<'a, V> {
204 pub fn is_owned(&self) -> bool {
206 self.raw.is_owned()
207 }
208
209 pub fn as_bytes(&self) -> &[u8] {
214 self.raw.as_bytes()
216 }
217
218 const unsafe fn from_raw(raw: RawVarZeroCow) -> Self {
220 Self {
221 raw,
223 marker1: PhantomData,
224 #[cfg(feature = "alloc")]
225 marker2: PhantomData,
226 }
227 }
228}
229
230impl RawVarZeroCow {
231 #[inline]
233 pub fn is_owned(&self) -> bool {
234 #[cfg(feature = "alloc")]
235 return self.owned;
236 #[cfg(not(feature = "alloc"))]
237 return false;
238 }
239
240 #[inline]
242 pub fn as_bytes(&self) -> &[u8] {
243 unsafe { self.buf.as_ref() }
245 }
246}
247
248impl<'a, V: VarULE + ?Sized> Deref for VarZeroCow<'a, V> {
249 type Target = V;
250 fn deref(&self) -> &V {
251 unsafe { V::from_bytes_unchecked(self.as_bytes()) }
253 }
254}
255
256impl<'a, V: VarULE + ?Sized> From<&'a V> for VarZeroCow<'a, V> {
257 fn from(other: &'a V) -> Self {
258 Self::new_borrowed(other)
259 }
260}
261
262#[cfg(feature = "alloc")]
263impl<'a, V: VarULE + ?Sized> From<Box<V>> for VarZeroCow<'a, V> {
264 fn from(other: Box<V>) -> Self {
265 Self::new_owned(other)
266 }
267}
268
269impl<'a, V: VarULE + ?Sized + fmt::Debug> fmt::Debug for VarZeroCow<'a, V> {
270 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
271 self.deref().fmt(f)
272 }
273}
274
275impl<'a, V: VarULE + ?Sized + PartialEq> PartialEq for VarZeroCow<'a, V> {
277 fn eq(&self, other: &Self) -> bool {
278 self.deref().eq(other.deref())
279 }
280}
281
282impl<'a, V: VarULE + ?Sized + Eq> Eq for VarZeroCow<'a, V> {}
283
284impl<'a, V: VarULE + ?Sized + PartialOrd> PartialOrd for VarZeroCow<'a, V> {
285 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
286 self.deref().partial_cmp(other.deref())
287 }
288}
289
290impl<'a, V: VarULE + ?Sized + Ord> Ord for VarZeroCow<'a, V> {
291 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
292 self.deref().cmp(other.deref())
293 }
294}
295
296unsafe impl<'a, V: VarULE + ?Sized> EncodeAsVarULE<V> for VarZeroCow<'a, V> {
302 fn encode_var_ule_as_slices<R>(&self, _: impl FnOnce(&[&[u8]]) -> R) -> R {
303 unreachable!()
305 }
306
307 #[inline]
308 fn encode_var_ule_len(&self) -> usize {
309 self.as_bytes().len()
310 }
311
312 #[inline]
313 fn encode_var_ule_write(&self, dst: &mut [u8]) {
314 dst.copy_from_slice(self.as_bytes())
315 }
316}
317
318#[cfg(feature = "serde")]
319impl<'a, V: VarULE + ?Sized + serde::Serialize> serde::Serialize for VarZeroCow<'a, V> {
320 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
321 where
322 S: serde::Serializer,
323 {
324 if serializer.is_human_readable() {
325 <V as serde::Serialize>::serialize(self.deref(), serializer)
326 } else {
327 serializer.serialize_bytes(self.as_bytes())
328 }
329 }
330}
331
332#[cfg(feature = "serde")]
333impl<'a, 'de: 'a, V: VarULE + ?Sized> serde::Deserialize<'de> for VarZeroCow<'a, V>
334where
335 Box<V>: serde::Deserialize<'de>,
336{
337 fn deserialize<Des>(deserializer: Des) -> Result<Self, Des::Error>
338 where
339 Des: serde::Deserializer<'de>,
340 {
341 if deserializer.is_human_readable() {
342 let b = Box::<V>::deserialize(deserializer)?;
343 Ok(Self::new_owned(b))
344 } else {
345 let bytes = <&[u8]>::deserialize(deserializer)?;
346 Self::parse_bytes(bytes).map_err(serde::de::Error::custom)
347 }
348 }
349}
350
351#[cfg(feature = "databake")]
352impl<'a, V: VarULE + ?Sized> databake::Bake for VarZeroCow<'a, V> {
353 fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream {
354 env.insert("zerovec");
355 let bytes = self.as_bytes().bake(env);
356 databake::quote! {
357 unsafe {
359 zerovec::VarZeroCow::from_bytes_unchecked(#bytes)
360 }
361 }
362 }
363}
364
365#[cfg(feature = "databake")]
366impl<'a, V: VarULE + ?Sized> databake::BakeSize for VarZeroCow<'a, V> {
367 fn borrows_size(&self) -> usize {
368 self.as_bytes().len()
369 }
370}
371
372impl<'a, V: VarULE + ?Sized> ZeroFrom<'a, V> for VarZeroCow<'a, V> {
373 #[inline]
374 fn zero_from(other: &'a V) -> Self {
375 Self::new_borrowed(other)
376 }
377}
378
379impl<'a, 'b, V: VarULE + ?Sized> ZeroFrom<'a, VarZeroCow<'b, V>> for VarZeroCow<'a, V> {
380 #[inline]
381 fn zero_from(other: &'a VarZeroCow<'b, V>) -> Self {
382 Self::new_borrowed(other)
383 }
384}
385
386#[cfg(test)]
387mod tests {
388 use super::VarZeroCow;
389 use crate::ule::tuplevar::Tuple3VarULE;
390 use crate::vecs::VarZeroSlice;
391 #[test]
392 fn test_cow_roundtrip() {
393 type Messy = Tuple3VarULE<str, [u8], VarZeroSlice<str>>;
394 let vec = vec!["one", "two", "three"];
395 let messy: VarZeroCow<Messy> =
396 VarZeroCow::from_encodeable(&("hello", &b"g\xFF\xFFdbye"[..], vec));
397
398 assert_eq!(messy.a(), "hello");
399 assert_eq!(messy.b(), b"g\xFF\xFFdbye");
400 assert_eq!(&messy.c()[1], "two");
401
402 #[cfg(feature = "serde")]
403 {
404 let bincode = bincode::serialize(&messy).unwrap();
405 let deserialized: VarZeroCow<Messy> = bincode::deserialize(&bincode).unwrap();
406 assert_eq!(
407 messy, deserialized,
408 "Single element roundtrips with bincode"
409 );
410 assert!(!deserialized.is_owned());
411
412 let json = serde_json::to_string(&messy).unwrap();
413 let deserialized: VarZeroCow<Messy> = serde_json::from_str(&json).unwrap();
414 assert_eq!(messy, deserialized, "Single element roundtrips with serde");
415 }
416 }
417
418 struct TwoCows<'a> {
419 cow1: VarZeroCow<'a, str>,
420 cow2: VarZeroCow<'a, str>,
421 }
422
423 #[test]
424 fn test_eyepatch_works() {
425 let mut two = TwoCows {
427 cow1: VarZeroCow::new_borrowed("hello"),
428 cow2: VarZeroCow::new_owned("world".into()),
429 };
430 let three = VarZeroCow::new_borrowed(&*two.cow2);
431 two.cow1 = three;
432
433 }
438}