binary_layout/utils/
data.rs1use core::fmt::Debug;
2use core::ops::{Bound, Deref, DerefMut, Range, RangeBounds};
3
4#[derive(Clone)]
15pub struct Data<S> {
16 storage: S,
17 region: Range<usize>,
20}
21
22impl<S> Data<S> {
25 #[inline(always)]
27 pub fn len(&self) -> usize {
28 self.region.len()
29 }
30
31 #[inline(always)]
33 pub fn is_empty(&self) -> bool {
34 self.region.is_empty()
35 }
36
37 #[inline]
46 pub fn into_subregion(self, range: impl RangeBounds<usize> + Debug) -> Self {
47 let start_bound_diff = match range.start_bound() {
48 Bound::Unbounded => 0,
49 Bound::Included(&x) => x,
50 Bound::Excluded(&x) => x + 1,
51 };
52 let panic_end_out_of_bounds = || {
53 panic!(
54 "Range end out of bounds. Tried to access subregion {:?} for a Data instance of length {}",
55 range,
56 self.region.len(),
57 );
58 };
59 let end_bound_diff = match range.end_bound() {
60 Bound::Unbounded => 0,
61 Bound::Included(&x) => self
62 .region
63 .len()
64 .checked_sub(x + 1)
65 .unwrap_or_else(panic_end_out_of_bounds),
66 Bound::Excluded(&x) => self
67 .region
68 .len()
69 .checked_sub(x)
70 .unwrap_or_else(panic_end_out_of_bounds),
71 };
72 Self {
73 storage: self.storage,
74 region: Range {
75 start: self.region.start + start_bound_diff,
76 end: self.region.end - end_bound_diff,
77 },
78 }
79 }
80}
81
82impl<S> From<S> for Data<S>
83where
84 S: AsRef<[u8]>,
85{
86 #[inline(always)]
88 fn from(data: S) -> Data<S> {
89 let len = data.as_ref().len();
90 Self {
91 storage: data,
92 region: 0..len,
93 }
94 }
95}
96
97impl<S> AsRef<[u8]> for Data<S>
98where
99 S: AsRef<[u8]>,
100{
101 #[inline(always)]
102 fn as_ref(&self) -> &[u8] {
103 &self.storage.as_ref()[self.region.clone()]
104 }
105}
106
107impl<S> AsMut<[u8]> for Data<S>
108where
109 S: AsMut<[u8]>,
110{
111 #[inline(always)]
112 fn as_mut(&mut self) -> &mut [u8] {
113 &mut self.storage.as_mut()[self.region.clone()]
114 }
115}
116
117impl<S> Deref for Data<S>
119where
120 S: AsRef<[u8]>,
121{
122 type Target = [u8];
123
124 #[inline(always)]
125 fn deref(&self) -> &[u8] {
126 self.as_ref()
127 }
128}
129
130impl<S> DerefMut for Data<S>
132where
133 S: AsRef<[u8]> + AsMut<[u8]>,
134{
135 #[inline(always)]
136 fn deref_mut(&mut self) -> &mut [u8] {
137 self.as_mut()
138 }
139}
140
141impl<'a> Data<&'a [u8]> {
142 pub fn into_slice(self) -> &'a [u8] {
168 &self.storage[self.region]
169 }
170}
171
172impl<'a> Data<&'a mut [u8]> {
173 pub fn into_slice(self) -> &'a mut [u8] {
199 &mut self.storage[self.region]
200 }
201}
202
203#[cfg(test)]
204#[cfg(feature = "std")] mod tests {
206 use super::*;
207 use rand::{rngs::StdRng, RngCore, SeedableRng};
208
209 fn data_region(size: usize, seed: u64) -> Vec<u8> {
210 let mut rng = StdRng::seed_from_u64(seed);
211 let mut res = vec![0; size];
212 rng.fill_bytes(&mut res);
213 res
214 }
215
216 #[test]
217 fn given_fullrangedata_when_callingasref() {
218 let data: Data<_> = data_region(1024, 0).into();
219 assert_eq!(data.as_ref(), &data_region(1024, 0));
220 }
221
222 #[test]
223 fn given_fullrangedata_when_callingasmut() {
224 let mut data: Data<_> = data_region(1024, 0).into();
225 assert_eq!(data.as_mut(), &data_region(1024, 0));
226 }
227
228 #[test]
229 fn given_fullsubregiondata_when_callingasref() {
230 let data: Data<_> = data_region(1024, 0).into();
231 let subdata = data.into_subregion(..);
232 assert_eq!(subdata.as_ref(), &data_region(1024, 0));
233 }
234
235 #[test]
236 fn given_fullsubregiondata_when_callingasmut() {
237 let data: Data<_> = data_region(1024, 0).into();
238 let mut subdata = data.into_subregion(..);
239 assert_eq!(subdata.as_mut(), &data_region(1024, 0));
240 }
241
242 #[test]
243 fn given_openendsubregiondata_when_callingasref() {
244 let data: Data<_> = data_region(1024, 0).into();
245 let subdata = data.into_subregion(5..);
246 assert_eq!(subdata.as_ref(), &data_region(1024, 0)[5..]);
247 }
248
249 #[test]
250 fn given_openendsubregiondata_when_callingasmut() {
251 let data: Data<_> = data_region(1024, 0).into();
252 let mut subdata = data.into_subregion(5..);
253 assert_eq!(subdata.as_mut(), &data_region(1024, 0)[5..]);
254 }
255
256 #[test]
257 fn given_openbeginningexclusivesubregiondata_when_callingasref() {
258 let data: Data<_> = data_region(1024, 0).into();
259 let subdata = data.into_subregion(..1000);
260 assert_eq!(subdata.as_ref(), &data_region(1024, 0)[..1000]);
261 }
262
263 #[test]
264 fn given_openbeginningexclusivesubregiondata_when_callingasmut() {
265 let data: Data<_> = data_region(1024, 0).into();
266 let mut subdata = data.into_subregion(..1000);
267 assert_eq!(subdata.as_mut(), &data_region(1024, 0)[..1000]);
268 }
269
270 #[test]
271 fn given_openbeginninginclusivesubregiondata_when_callingasref() {
272 let data: Data<_> = data_region(1024, 0).into();
273 let subdata = data.into_subregion(..=1000);
274 assert_eq!(subdata.as_ref(), &data_region(1024, 0)[..=1000]);
275 }
276
277 #[test]
278 fn given_openbeginninginclusivesubregiondata_when_callingasmut() {
279 let data: Data<_> = data_region(1024, 0).into();
280 let mut subdata = data.into_subregion(..=1000);
281 assert_eq!(subdata.as_mut(), &data_region(1024, 0)[..=1000]);
282 }
283
284 #[test]
285 fn given_exclusivesubregiondata_when_callingasref() {
286 let data: Data<_> = data_region(1024, 0).into();
287 let subdata = data.into_subregion(5..1000);
288 assert_eq!(subdata.as_ref(), &data_region(1024, 0)[5..1000]);
289 }
290
291 #[test]
292 fn given_exclusivesubregiondata_when_callingasmut() {
293 let data: Data<_> = data_region(1024, 0).into();
294 let mut subdata = data.into_subregion(5..1000);
295 assert_eq!(subdata.as_mut(), &data_region(1024, 0)[5..1000]);
296 }
297
298 #[test]
299 fn given_inclusivesubregiondata_when_callingasref() {
300 let data: Data<_> = data_region(1024, 0).into();
301 let subdata = data.into_subregion(5..=1000);
302 assert_eq!(subdata.as_ref(), &data_region(1024, 0)[5..=1000]);
303 }
304
305 #[test]
306 fn given_inclusivesubregiondata_when_callingasmut() {
307 let data: Data<_> = data_region(1024, 0).into();
308 let mut subdata = data.into_subregion(5..=1000);
309 assert_eq!(subdata.as_mut(), &data_region(1024, 0)[5..=1000]);
310 }
311
312 #[test]
313 fn nested_subregions_still_do_the_right_thing() {
314 let data: Data<_> = data_region(1024, 0).into();
315 let subdata = data
316 .into_subregion(..)
317 .into_subregion(5..)
318 .into_subregion(..1000)
319 .into_subregion(..=950)
320 .into_subregion(10..900)
321 .into_subregion(3..=800)
322 .into_subregion(..)
324 .into_subregion(5..)
325 .into_subregion(..700)
326 .into_subregion(..=650)
327 .into_subregion(10..600)
328 .into_subregion(3..=500);
329 assert_eq!(
330 subdata.as_ref(),
331 &data_region(1024, 0)[..][5..][..1000][..=950][10..900][3..=800][..][5..][..700]
332 [..=650][10..600][3..=500]
333 );
334 }
335
336 #[test]
337 #[should_panic(
338 expected = "Range end out of bounds. Tried to access subregion ..=1024 for a Data instance of length 1024"
339 )]
340 fn given_fullrangedata_when_tryingtogrowendbeyondlength_with_inclusiverange_then_panics() {
341 let data: Data<_> = data_region(1024, 0).into();
342 data.into_subregion(..=1024);
343 }
344
345 #[test]
346 #[should_panic(
347 expected = "Range end out of bounds. Tried to access subregion ..=100 for a Data instance of length 100"
348 )]
349 fn given_subrangedata_when_tryingtogrowendbeyondlength_with_inclusiverange_then_panics() {
350 let data: Data<_> = data_region(1024, 0).into();
351 let data = data.into_subregion(0..100);
352 data.into_subregion(..=100);
353 }
354
355 #[test]
356 #[should_panic(
357 expected = "Range end out of bounds. Tried to access subregion ..1025 for a Data instance of length 1024"
358 )]
359 fn given_fullrangedata_when_tryingtogrowendbeyondlength_with_exclusiverange_then_panics() {
360 let data: Data<_> = data_region(1024, 0).into();
361 data.into_subregion(..1025);
362 }
363
364 #[test]
365 #[should_panic(
366 expected = "Range end out of bounds. Tried to access subregion ..101 for a Data instance of length 100"
367 )]
368 fn given_subrangedata_when_tryingtogrowendbeyondlength_with_exclusiverange_then_panics() {
369 let data: Data<_> = data_region(1024, 0).into();
370 let data = data.into_subregion(0..100);
371 data.into_subregion(..101);
372 }
373
374 #[test]
375 fn given_fullrangedata_when_tryingtogrowstartbeyondend_then_returnszerolengthrange() {
376 let data: Data<_> = data_region(1024, 0).into();
377 #[allow(clippy::reversed_empty_ranges)]
378 let data = data.into_subregion(5000..400);
379 assert_eq!(0, data.len());
380 }
381}