1use std::{
2 borrow::Borrow,
3 mem::{self, MaybeUninit},
4 slice,
5};
6
7#[derive(Clone, Debug, Default)]
8pub struct UntypedBytes {
9 bytes: Vec<u8>,
10}
11
12#[inline]
14unsafe fn as_bytes<T: Copy + Send + Sync + 'static>(value: &T) -> &[u8] {
15 slice::from_raw_parts(value as *const T as _, mem::size_of::<T>())
16}
17
18#[inline]
20unsafe fn as_bytes_slice<T: Copy + Send + Sync + 'static>(value: &[T]) -> &[u8] {
21 slice::from_raw_parts(value.as_ptr() as _, mem::size_of_val(value))
22}
23
24impl UntypedBytes {
25 pub fn new() -> Self {
26 Default::default()
27 }
28
29 pub fn with_capacity(capacity: usize) -> Self {
30 Self {
31 bytes: Vec::with_capacity(capacity),
32 }
33 }
34
35 pub fn from_vec<T: Copy + 'static>(mut value: Vec<T>) -> Self {
37 let size = mem::size_of::<T>();
38 let bytes = unsafe {
39 Vec::from_raw_parts(
40 value.as_mut_ptr() as _,
41 value.len() * size,
42 value.capacity() * size,
43 )
44 };
45 mem::forget(value);
46 Self { bytes }
47 }
48
49 pub fn from_slice<T, V>(value: V) -> Self
50 where
51 T: Copy + Send + Sync + 'static,
52 V: Borrow<[T]>,
53 {
54 let borrowed = value.borrow();
55 let mut result = Self::with_capacity(mem::size_of_val(borrowed));
56 let raw = unsafe { as_bytes_slice(borrowed) };
57 result.bytes.extend(raw);
58 result
59 }
60
61 pub fn is_empty(&self) -> bool {
62 self.bytes.is_empty()
63 }
64
65 pub fn len(&self) -> usize {
66 self.bytes.len()
67 }
68
69 pub fn clear(&mut self) {
70 self.bytes.clear()
71 }
72
73 pub fn push<T: Copy + Send + Sync + 'static>(&mut self, value: T) {
74 let raw = unsafe { as_bytes(&value) };
75 self.bytes.extend(raw)
76 }
77
78 #[inline]
79 pub fn extend_from_slice<T, V>(&mut self, value: V)
80 where
81 T: Copy + Send + Sync + 'static,
82 V: Borrow<[T]>,
83 {
84 let raw = unsafe { as_bytes_slice(value.borrow()) };
85 self.bytes.extend_from_slice(raw)
86 }
87
88 pub unsafe fn as_slice(&self) -> &[u8] {
92 &self.bytes
93 }
94
95 pub unsafe fn cast<T: Copy + Send + Sync + 'static>(&self) -> T {
98 debug_assert_eq!(
99 mem::size_of::<T>(),
100 self.len(),
101 "Attempt to cast `UntypedBytes` to a value of a different size"
102 );
103 let mut result = MaybeUninit::uninit();
104 self.as_slice()
105 .as_ptr()
106 .copy_to_nonoverlapping(result.as_mut_ptr() as *mut u8, mem::size_of::<T>());
107 result.assume_init()
108 }
109}
110
111impl<T: Copy + Send + Sync + 'static> From<T> for UntypedBytes {
112 fn from(value: T) -> Self {
113 Self::from_vec(vec![value])
114 }
115}
116
117impl<A: Copy + Send + Sync + 'static> Extend<A> for UntypedBytes {
118 #[inline]
119 fn extend<T: IntoIterator<Item = A>>(&mut self, value: T) {
120 if std::any::type_name::<T>()
121 == std::any::type_name::<std::iter::Copied<std::slice::Iter<'_, A>>>()
122 {
123 let raw = unsafe { mem::transmute_copy::<_, std::slice::Iter<'_, A>>(&value) };
124 self.extend_from_slice(raw.as_slice())
125 } else if std::any::type_name::<T>()
126 == std::any::type_name::<std::iter::Cloned<std::slice::Iter<'_, A>>>()
127 {
128 let raw = unsafe { mem::transmute_copy::<_, std::slice::Iter<'_, A>>(&value) };
129 self.extend_from_slice(raw.as_slice())
130 } else if std::any::type_name::<T>()
131 == std::any::type_name::<std::iter::Copied<std::slice::IterMut<'_, A>>>()
132 {
133 let raw = unsafe { mem::transmute_copy::<_, std::slice::IterMut<'_, A>>(&value) };
134 self.extend_from_slice(raw.into_slice())
135 } else if std::any::type_name::<T>()
136 == std::any::type_name::<std::iter::Cloned<std::slice::IterMut<'_, A>>>()
137 {
138 let raw = unsafe { mem::transmute_copy::<_, std::slice::IterMut<'_, A>>(&value) };
139 self.extend_from_slice(raw.into_slice())
140 } else if std::any::type_name::<T>() == std::any::type_name::<std::vec::IntoIter<A>>() {
141 let raw = unsafe { mem::transmute_copy::<_, std::vec::IntoIter<A>>(&value) };
142 std::mem::forget(value);
143 self.extend_from_slice(raw.as_slice())
144 } else if std::any::type_name::<T>() == std::any::type_name::<Vec<A>>() {
145 let raw = unsafe { mem::transmute_copy::<_, Vec<A>>(&value) };
146 std::mem::forget(value);
147 self.extend_from_slice(raw.as_slice())
148 } else {
149 for elem in value {
150 self.push(elem)
151 }
152 }
153 }
154}