1use crate::bytes::*;
8use crate::vtable::VTable;
9use dync_derive::dync_trait_method;
10use std::fmt;
11use std::hash::{Hash, Hasher};
12use std::mem::{ManuallyDrop, MaybeUninit};
13
14pub trait DropBytes {
15 #[doc(hidden)]
16 unsafe fn drop_bytes(bytes: &mut [MaybeUninit<u8>]);
17}
18
19pub trait CloneBytes: Clone {
20 #[dync_trait_method]
21 fn clone(&self) -> Self;
22 #[dync_trait_method]
24 fn clone_from(&mut self, src: &Self);
25 #[doc(hidden)]
28 unsafe fn clone_into_raw_bytes(src: &[MaybeUninit<u8>], dst: &mut [MaybeUninit<u8>]);
29}
30
31pub trait PartialEqBytes: PartialEq {
32 #[dync_trait_method]
33 fn eq(&self, other: &Self) -> bool;
34 }
36
37pub trait HashBytes: Hash {
38 #[dync_trait_method]
39 fn hash<H: Hasher>(&self, state: &mut H);
40 }
42
43pub trait DebugBytes: fmt::Debug {
44 #[dync_trait_method]
45 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>;
46 }
48
49impl<T: 'static> DropBytes for T {
50 #[inline]
51 unsafe fn drop_bytes(bytes: &mut [MaybeUninit<u8>]) {
52 let md: &mut ManuallyDrop<T> = Bytes::from_bytes_mut(bytes);
53 ManuallyDrop::drop(md);
54 }
55}
56
57impl<T: Clone + 'static> CloneBytes for T {
58 #[inline]
59 unsafe fn clone_bytes(src: &[MaybeUninit<u8>]) -> Box<[MaybeUninit<u8>]> {
60 let typed_src: &T = Bytes::from_bytes(src);
61 Bytes::box_into_box_bytes(Box::new(typed_src.clone()))
62 }
63 #[inline]
64 unsafe fn clone_from_bytes(dst: &mut [MaybeUninit<u8>], src: &[MaybeUninit<u8>]) {
65 let typed_src: &T = Bytes::from_bytes(src);
66 let typed_dst: &mut T = Bytes::from_bytes_mut(dst);
67 typed_dst.clone_from(typed_src);
68 }
69 #[inline]
70 unsafe fn clone_into_raw_bytes(src: &[MaybeUninit<u8>], dst: &mut [MaybeUninit<u8>]) {
71 let typed_src: &T = Bytes::from_bytes(src);
72 let cloned = T::clone(typed_src);
73 let cloned_bytes = Bytes::as_bytes(&cloned);
74 dst.copy_from_slice(cloned_bytes);
75 let _ = ManuallyDrop::new(cloned);
76 }
77}
78
79impl<T: PartialEq + 'static> PartialEqBytes for T {
80 #[inline]
81 unsafe fn eq_bytes(a: &[MaybeUninit<u8>], b: &[MaybeUninit<u8>]) -> bool {
82 let (a, b): (&T, &T) = (Bytes::from_bytes(a), Bytes::from_bytes(b));
83 a.eq(b)
84 }
85}
86
87impl<T: Hash + 'static> HashBytes for T {
88 #[inline]
89 unsafe fn hash_bytes(bytes: &[MaybeUninit<u8>], mut state: &mut dyn Hasher) {
90 let typed_data: &T = Bytes::from_bytes(bytes);
91 typed_data.hash(&mut state)
92 }
93}
94
95impl<T: fmt::Debug + 'static> DebugBytes for T {
96 #[inline]
97 unsafe fn fmt_bytes(
98 bytes: &[MaybeUninit<u8>],
99 f: &mut fmt::Formatter,
100 ) -> Result<(), fmt::Error> {
101 let typed_data: &T = Bytes::from_bytes(bytes);
102 typed_data.fmt(f)
103 }
104}
105
106pub type CloneFn = unsafe fn(&[MaybeUninit<u8>]) -> Box<[MaybeUninit<u8>]>;
107pub type CloneFromFn = unsafe fn(&mut [MaybeUninit<u8>], &[MaybeUninit<u8>]);
108pub type CloneIntoRawFn = unsafe fn(&[MaybeUninit<u8>], &mut [MaybeUninit<u8>]);
109pub type EqFn = unsafe fn(&[MaybeUninit<u8>], &[MaybeUninit<u8>]) -> bool;
110pub type HashFn = unsafe fn(&[MaybeUninit<u8>], &mut dyn Hasher);
111pub type FmtFn = unsafe fn(&[MaybeUninit<u8>], &mut fmt::Formatter) -> Result<(), fmt::Error>;
112pub type DropFn = unsafe fn(&mut [MaybeUninit<u8>]);
113
114use downcast_rs::{impl_downcast, Downcast};
115
116pub trait HasDrop: Downcast {
117 fn drop_fn(&self) -> &DropFn;
118}
119
120impl_downcast!(HasDrop);
121
122pub trait HasClone {
123 fn clone_fn(&self) -> &CloneFn;
124 fn clone_from_fn(&self) -> &CloneFromFn;
125 fn clone_into_raw_fn(&self) -> &CloneIntoRawFn;
126}
127
128pub trait HasHash {
129 fn hash_fn(&self) -> &HashFn;
130}
131
132pub trait HasPartialEq {
133 fn eq_fn(&self) -> &EqFn;
134}
135
136pub trait HasEq: HasPartialEq {}
137
138pub trait HasDebug {
139 fn fmt_fn(&self) -> &FmtFn;
140}
141
142pub unsafe trait HasSend {}
146
147pub unsafe trait HasSync {}
151
152#[derive(Clone)]
153pub struct DropVTable(pub DropFn);
154#[derive(Clone)]
155pub struct CloneVTable(pub DropFn, pub CloneFn, pub CloneFromFn, pub CloneIntoRawFn);
156#[derive(Clone)]
157pub struct PartialEqVTable(pub DropFn, pub EqFn);
158#[derive(Clone)]
159pub struct EqVTable(pub DropFn, pub EqFn);
160#[derive(Clone)]
161pub struct HashVTable(pub DropFn, pub HashFn);
162#[derive(Clone)]
163pub struct DebugVTable(pub DropFn, pub FmtFn);
164#[derive(Clone)]
165pub struct SendVTable(pub DropFn);
166#[derive(Clone)]
167pub struct SyncVTable(pub DropFn);
168
169impl<T: DropBytes> VTable<T> for DropVTable {
171 fn build_vtable() -> Self {
172 DropVTable(T::drop_bytes)
173 }
174}
175
176impl<T: DropBytes + CloneBytes> VTable<T> for CloneVTable {
177 fn build_vtable() -> Self {
178 CloneVTable(
179 T::drop_bytes,
180 T::clone_bytes,
181 T::clone_from_bytes,
182 T::clone_into_raw_bytes,
183 )
184 }
185}
186
187impl<T: DropBytes + PartialEqBytes> VTable<T> for PartialEqVTable {
188 fn build_vtable() -> Self {
189 PartialEqVTable(T::drop_bytes, T::eq_bytes)
190 }
191}
192
193impl<T: DropBytes + PartialEqBytes> VTable<T> for EqVTable {
194 fn build_vtable() -> Self {
195 EqVTable(T::drop_bytes, T::eq_bytes)
196 }
197}
198
199impl<T: DropBytes + HashBytes> VTable<T> for HashVTable {
200 fn build_vtable() -> Self {
201 HashVTable(T::drop_bytes, T::hash_bytes)
202 }
203}
204
205impl<T: DropBytes> VTable<T> for SendVTable {
206 fn build_vtable() -> Self {
207 SendVTable(T::drop_bytes)
208 }
209}
210
211impl<T: DropBytes> VTable<T> for SyncVTable {
212 fn build_vtable() -> Self {
213 SyncVTable(T::drop_bytes)
214 }
215}
216
217impl<T: DropBytes + DebugBytes> VTable<T> for DebugVTable {
218 fn build_vtable() -> Self {
219 DebugVTable(T::drop_bytes, T::fmt_bytes)
220 }
221}
222
223macro_rules! impl_has_drop {
224 ($($trait:ident),*) => {
225 $(
226 impl HasDrop for $trait {
227 fn drop_fn(&self) -> &DropFn {
228 &self.0
229 }
230 }
231 )*
232 }
233}
234
235impl_has_drop!(
236 DropVTable,
237 CloneVTable,
238 PartialEqVTable,
239 EqVTable,
240 HashVTable,
241 DebugVTable,
242 SendVTable,
243 SyncVTable
244);
245
246impl HasClone for CloneVTable {
247 fn clone_fn(&self) -> &CloneFn {
248 &self.1
249 }
250 fn clone_from_fn(&self) -> &CloneFromFn {
251 &self.2
252 }
253 fn clone_into_raw_fn(&self) -> &CloneIntoRawFn {
254 &self.3
255 }
256}
257
258impl HasHash for HashVTable {
259 fn hash_fn(&self) -> &HashFn {
260 &self.1
261 }
262}
263
264impl HasPartialEq for PartialEqVTable {
265 fn eq_fn(&self) -> &EqFn {
266 &self.1
267 }
268}
269
270impl HasPartialEq for EqVTable {
271 fn eq_fn(&self) -> &EqFn {
272 &self.1
273 }
274}
275
276impl HasEq for EqVTable {}
277
278impl HasDebug for DebugVTable {
279 fn fmt_fn(&self) -> &FmtFn {
280 &self.1
281 }
282}
283
284#[cfg(test)]
285mod tests {
286 use super::*;
287 use crate::vec_dyn::VecDyn;
288
289 #[test]
290 fn drop() {
291 let vd = VecDyn::<DropVTable>::with_type::<u32>();
293 let v = vd.into_vec::<u32>().unwrap();
294 assert_eq!(v, Vec::new());
295
296 let vd = VecDyn::<DropVTable>::from(vec![1u32, 2]);
298 let v = vd.into_vec::<u32>().unwrap();
299 assert_eq!(v, vec![1u32, 2]);
300 }
301
302 #[test]
303 fn clone() {
304 let v = VecDyn::<CloneVTable>::from(vec![1u32, 2]);
305 let v_clone = v.clone();
306 assert_eq!(
307 v.into_vec::<u32>().unwrap(),
308 v_clone.into_vec::<u32>().unwrap()
309 );
310 }
311
312 #[test]
313 fn partial_eq() {
314 let a = VecDyn::<PartialEqVTable>::from(vec![1, 2]);
315 let b = VecDyn::<PartialEqVTable>::from(vec![1, 2]);
316 assert!(a == b);
317
318 let a = VecDyn::<EqVTable>::from(vec![1, 2]);
319 let b = VecDyn::<EqVTable>::from(vec![1, 2]);
320 assert!(a == b);
321 }
322
323 #[test]
324 fn hash() {
325 use std::collections::hash_map::DefaultHasher;
326 let a = VecDyn::<HashVTable>::from(vec![1, 2]);
327 let b = VecDyn::<HashVTable>::from(vec![1, 2]);
328
329 let mut s = DefaultHasher::new();
330 a.hash(&mut s);
331 let a_hash = s.finish();
332
333 let mut s = DefaultHasher::new();
334 b.hash(&mut s);
335 let b_hash = s.finish();
336 assert_eq!(a_hash, b_hash);
337 }
338
339 #[test]
340 fn debug() {
341 let a = VecDyn::<DebugVTable>::from(vec![1, 2]);
342 eprintln!("{:?}", a);
343 }
344}