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")]
128 pub fn parse_owned_bytes(bytes: Box<[u8]>) -> Result<Self, UleError> {
129 V::validate_bytes(&bytes)?;
130 let bytes = ManuallyDrop::new(bytes);
131 let buf: NonNull<[u8]> = (&**bytes).into();
132 let raw = RawVarZeroCow {
133 buf,
137 owned: true,
138 };
139 Ok(Self {
140 raw,
141 marker1: PhantomData,
142 #[cfg(feature = "alloc")]
143 marker2: PhantomData,
144 })
145 }
146
147 pub const unsafe fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
154 unsafe {
155 let buf: NonNull<[u8]> = NonNull::new_unchecked(bytes as *const [u8] as *mut [u8]);
157 let raw = RawVarZeroCow {
158 buf,
162 #[cfg(feature = "alloc")]
163 owned: false,
164 };
165 Self::from_raw(raw)
167 }
168 }
169
170 #[cfg(feature = "alloc")]
176 pub fn from_encodeable<E: EncodeAsVarULE<V>>(encodeable: &E) -> Self {
177 let b = crate::ule::encode_varule_to_box(encodeable);
178 Self::new_owned(b)
179 }
180
181 pub fn new_borrowed(val: &'a V) -> Self {
183 unsafe {
184 Self::from_bytes_unchecked(val.as_bytes())
186 }
187 }
188
189 #[cfg(feature = "alloc")]
193 pub fn new_owned(val: Box<V>) -> Self {
194 let val = ManuallyDrop::new(val);
195 let buf: NonNull<[u8]> = val.as_bytes().into();
196 let raw = RawVarZeroCow {
197 buf,
201 #[cfg(feature = "alloc")]
202 owned: true,
203 };
204 unsafe { Self::from_raw(raw) }
206 }
207}
208
209impl<'a, V: ?Sized> VarZeroCow<'a, V> {
210 pub fn is_owned(&self) -> bool {
212 self.raw.is_owned()
213 }
214
215 pub fn as_bytes(&self) -> &[u8] {
220 self.raw.as_bytes()
222 }
223
224 const unsafe fn from_raw(raw: RawVarZeroCow) -> Self {
226 Self {
227 raw,
229 marker1: PhantomData,
230 #[cfg(feature = "alloc")]
231 marker2: PhantomData,
232 }
233 }
234}
235
236impl RawVarZeroCow {
237 #[inline]
239 pub fn is_owned(&self) -> bool {
240 #[cfg(feature = "alloc")]
241 return self.owned;
242 #[cfg(not(feature = "alloc"))]
243 return false;
244 }
245
246 #[inline]
248 pub fn as_bytes(&self) -> &[u8] {
249 unsafe { self.buf.as_ref() }
251 }
252}
253
254impl<'a, V: VarULE + ?Sized> Deref for VarZeroCow<'a, V> {
255 type Target = V;
256 fn deref(&self) -> &V {
257 unsafe { V::from_bytes_unchecked(self.as_bytes()) }
259 }
260}
261
262impl<'a, V: VarULE + ?Sized> From<&'a V> for VarZeroCow<'a, V> {
263 fn from(other: &'a V) -> Self {
264 Self::new_borrowed(other)
265 }
266}
267
268#[cfg(feature = "alloc")]
269impl<'a, V: VarULE + ?Sized> From<Box<V>> for VarZeroCow<'a, V> {
270 fn from(other: Box<V>) -> Self {
271 Self::new_owned(other)
272 }
273}
274
275impl<'a, V: VarULE + ?Sized + fmt::Debug> fmt::Debug for VarZeroCow<'a, V> {
276 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
277 self.deref().fmt(f)
278 }
279}
280
281impl<'a, V: VarULE + ?Sized + PartialEq> PartialEq for VarZeroCow<'a, V> {
283 fn eq(&self, other: &Self) -> bool {
284 self.deref().eq(other.deref())
285 }
286}
287
288impl<'a, V: VarULE + ?Sized + Eq> Eq for VarZeroCow<'a, V> {}
289
290impl<'a, V: VarULE + ?Sized + PartialOrd> PartialOrd for VarZeroCow<'a, V> {
291 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
292 self.deref().partial_cmp(other.deref())
293 }
294}
295
296impl<'a, V: VarULE + ?Sized + Ord> Ord for VarZeroCow<'a, V> {
297 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
298 self.deref().cmp(other.deref())
299 }
300}
301
302unsafe impl<'a, V: VarULE + ?Sized> EncodeAsVarULE<V> for VarZeroCow<'a, V> {
308 fn encode_var_ule_as_slices<R>(&self, _: impl FnOnce(&[&[u8]]) -> R) -> R {
309 unreachable!()
311 }
312
313 #[inline]
314 fn encode_var_ule_len(&self) -> usize {
315 self.as_bytes().len()
316 }
317
318 #[inline]
319 fn encode_var_ule_write(&self, dst: &mut [u8]) {
320 dst.copy_from_slice(self.as_bytes())
321 }
322}
323
324#[cfg(feature = "serde")]
325impl<'a, V: VarULE + ?Sized + serde::Serialize> serde::Serialize for VarZeroCow<'a, V> {
326 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
327 where
328 S: serde::Serializer,
329 {
330 if serializer.is_human_readable() {
331 <V as serde::Serialize>::serialize(self.deref(), serializer)
332 } else {
333 serializer.serialize_bytes(self.as_bytes())
334 }
335 }
336}
337
338#[cfg(all(feature = "serde", feature = "alloc"))]
339impl<'a, 'de: 'a, V: VarULE + ?Sized> serde::Deserialize<'de> for VarZeroCow<'a, V>
340where
341 Box<V>: serde::Deserialize<'de>,
342{
343 fn deserialize<Des>(deserializer: Des) -> Result<Self, Des::Error>
344 where
345 Des: serde::Deserializer<'de>,
346 {
347 if deserializer.is_human_readable() {
348 let b = Box::<V>::deserialize(deserializer)?;
349 Ok(Self::new_owned(b))
350 } else {
351 let bytes = <&[u8]>::deserialize(deserializer)?;
352 Self::parse_bytes(bytes).map_err(serde::de::Error::custom)
353 }
354 }
355}
356
357#[cfg(feature = "databake")]
358impl<'a, V: VarULE + ?Sized> databake::Bake for VarZeroCow<'a, V> {
359 fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream {
360 env.insert("zerovec");
361 let bytes = self.as_bytes().bake(env);
362 databake::quote! {
363 unsafe {
365 zerovec::VarZeroCow::from_bytes_unchecked(#bytes)
366 }
367 }
368 }
369}
370
371#[cfg(feature = "databake")]
372impl<'a, V: VarULE + ?Sized> databake::BakeSize for VarZeroCow<'a, V> {
373 fn borrows_size(&self) -> usize {
374 self.as_bytes().len()
375 }
376}
377
378impl<'a, V: VarULE + ?Sized> ZeroFrom<'a, V> for VarZeroCow<'a, V> {
379 #[inline]
380 fn zero_from(other: &'a V) -> Self {
381 Self::new_borrowed(other)
382 }
383}
384
385impl<'a, 'b, V: VarULE + ?Sized> ZeroFrom<'a, VarZeroCow<'b, V>> for VarZeroCow<'a, V> {
386 #[inline]
387 fn zero_from(other: &'a VarZeroCow<'b, V>) -> Self {
388 Self::new_borrowed(other)
389 }
390}
391
392#[cfg(test)]
393mod tests {
394 use super::VarZeroCow;
395 use crate::ule::tuplevar::Tuple3VarULE;
396 use crate::vecs::VarZeroSlice;
397 #[test]
398 fn test_cow_roundtrip() {
399 type Messy = Tuple3VarULE<str, [u8], VarZeroSlice<str>>;
400 let vec = vec!["one", "two", "three"];
401 let messy: VarZeroCow<Messy> =
402 VarZeroCow::from_encodeable(&("hello", &b"g\xFF\xFFdbye"[..], vec));
403
404 assert_eq!(messy.a(), "hello");
405 assert_eq!(messy.b(), b"g\xFF\xFFdbye");
406 assert_eq!(&messy.c()[1], "two");
407
408 #[cfg(feature = "serde")]
409 {
410 let bincode = bincode::serialize(&messy).unwrap();
411 let deserialized: VarZeroCow<Messy> = bincode::deserialize(&bincode).unwrap();
412 assert_eq!(
413 messy, deserialized,
414 "Single element roundtrips with bincode"
415 );
416 assert!(!deserialized.is_owned());
417
418 let json = serde_json::to_string(&messy).unwrap();
419 let deserialized: VarZeroCow<Messy> = serde_json::from_str(&json).unwrap();
420 assert_eq!(messy, deserialized, "Single element roundtrips with serde");
421 }
422 }
423
424 struct TwoCows<'a> {
425 cow1: VarZeroCow<'a, str>,
426 cow2: VarZeroCow<'a, str>,
427 }
428
429 #[test]
430 fn test_eyepatch_works() {
431 let mut two = TwoCows {
433 cow1: VarZeroCow::new_borrowed("hello"),
434 cow2: VarZeroCow::new_owned("world".into()),
435 };
436 let three = VarZeroCow::new_borrowed(&*two.cow2);
437 two.cow1 = three;
438
439 }
444}