inspect_format/container/
common.rs1use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
6
7pub trait BlockContainer {
8 type Data;
9 type ShareableData;
10
11 fn len(&self) -> usize;
13
14 fn is_empty(&self) -> bool {
16 self.len() == 0
17 }
18}
19
20pub trait ReadBytes: BlockContainer {
22 fn get_slice_at(&self, offset: usize, size: usize) -> Option<&[u8]>;
24
25 #[inline]
28 fn get_slice(&self, size: usize) -> Option<&[u8]> {
29 self.get_slice_at(0, size)
30 }
31
32 #[inline]
34 fn get_value<T: ContainerValue>(&self, offset: usize) -> Option<T> {
35 self.get_slice_at(offset, std::mem::size_of::<T>())
36 .and_then(|slice| T::read_from_bytes(slice).ok())
37 }
38}
39
40pub trait CopyBytes: BlockContainer {
41 fn copy_bytes_at(&self, offset: usize, dst: &mut [u8]);
42
43 fn copy_bytes(&self, dst: &mut [u8]) {
44 self.copy_bytes_at(0, dst)
45 }
46}
47
48pub trait ContainerValue:
50 FromBytes + IntoBytes + KnownLayout + Immutable + Copy + private::Sealed + 'static
51{
52}
53
54mod private {
55 pub trait Sealed {}
56}
57
58macro_rules! impl_container_value {
59 ($($type:ty),*) => {
60 $(
61 impl private::Sealed for $type {}
62 impl ContainerValue for $type {}
63 )*
64 };
65}
66
67impl_container_value!(u8, u16, u32, u64, i64, f64);
68
69pub trait WriteBytes {
71 fn get_slice_mut_at(&mut self, offset: usize, size: usize) -> Option<&mut [u8]>;
74
75 #[inline]
78 fn get_slice_mut(&mut self, size: usize) -> Option<&mut [u8]> {
79 self.get_slice_mut_at(0, size)
80 }
81
82 #[inline]
83 fn copy_from_slice_at(&mut self, offset: usize, bytes: &[u8]) {
84 if let Some(slice) = self.get_slice_mut_at(offset, bytes.len()) {
86 slice.copy_from_slice(bytes);
87 }
88 }
89
90 #[inline]
91 fn copy_from_slice(&mut self, bytes: &[u8]) {
92 self.copy_from_slice_at(0, bytes);
93 }
94
95 #[inline]
97 fn set_value<T: ContainerValue>(
98 &mut self,
99 offset: usize,
100 value: T,
101 ) -> Result<(), crate::Error> {
102 if let Some(slice) = self.get_slice_mut_at(offset, std::mem::size_of::<T>()) {
103 slice.copy_from_slice(value.as_bytes());
104 Ok(())
105 } else {
106 Err(crate::Error::InvalidOffset(offset))
107 }
108 }
109}
110
111impl BlockContainer for Vec<u8> {
112 type Data = Self;
113 type ShareableData = ();
114
115 #[inline]
117 fn len(&self) -> usize {
118 self.as_slice().len()
119 }
120}
121
122impl ReadBytes for Vec<u8> {
123 #[inline]
124 fn get_slice_at(&self, offset: usize, size: usize) -> Option<&[u8]> {
125 self.as_slice().get_slice_at(offset, size)
126 }
127}
128
129impl CopyBytes for Vec<u8> {
130 #[inline]
131 fn copy_bytes_at(&self, offset: usize, dst: &mut [u8]) {
132 if let Some(slice) = self.as_slice().get_slice_at(offset, dst.len()) {
133 dst.copy_from_slice(slice);
134 }
135 }
136}
137
138impl BlockContainer for [u8] {
139 type Data = ();
140 type ShareableData = ();
141
142 #[inline]
143 fn len(&self) -> usize {
144 <[u8]>::len(self)
145 }
146}
147
148impl ReadBytes for [u8] {
149 #[inline]
150 fn get_slice_at(&self, offset: usize, size: usize) -> Option<&[u8]> {
151 let upper_bound = offset.checked_add(size)?;
152 if offset >= self.len() || upper_bound > self.len() {
153 return None;
154 }
155 Some(&self[offset..upper_bound])
156 }
157}
158
159impl<const N: usize> BlockContainer for [u8; N] {
160 type Data = Self;
161 type ShareableData = ();
162
163 #[inline]
165 fn len(&self) -> usize {
166 self.as_slice().len()
167 }
168}
169
170impl<const N: usize> ReadBytes for [u8; N] {
171 #[inline]
172 fn get_slice_at(&self, offset: usize, size: usize) -> Option<&[u8]> {
173 self.as_slice().get_slice_at(offset, size)
174 }
175}
176
177impl<const N: usize> WriteBytes for [u8; N] {
179 #[inline]
180 fn get_slice_mut_at(&mut self, offset: usize, size: usize) -> Option<&mut [u8]> {
181 if offset >= self.len() {
182 return None;
183 }
184 let upper_bound = offset.checked_add(size)?;
185 if upper_bound > self.len() {
186 return None;
187 }
188 Some(&mut self[offset..upper_bound])
189 }
190}