/src/adhd/audio_processor/src/slice_cast.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2022 The ChromiumOS Authors |
2 | | // Use of this source code is governed by a BSD-style license that can be |
3 | | // found in the LICENSE file. |
4 | | |
5 | | /// Trait to support slice casting. |
6 | | pub trait SliceCast<'a> { |
7 | | /// Cast the slice. |
8 | | /// This is a "view" cast. The underlying memory is unchanged. |
9 | | /// Panics if the length or alignment is invalid for `T`. |
10 | | fn cast<T: Sized>(self) -> &'a mut [T]; |
11 | | } |
12 | | |
13 | | impl<'a, T> SliceCast<'a> for &'a mut [T] |
14 | | where |
15 | | T: Sized, |
16 | | { |
17 | 0 | fn cast<U: Sized>(self) -> &'a mut [U] { |
18 | 0 | let bytes = std::mem::size_of::<T>() * self.len(); |
19 | 0 | if bytes % std::mem::size_of::<U>() != 0 { |
20 | 0 | panic!( |
21 | 0 | "Cannot convert {} x {} to {}", |
22 | 0 | self.len(), |
23 | 0 | std::any::type_name::<T>(), |
24 | 0 | std::any::type_name::<U>(), |
25 | 0 | ); |
26 | 0 | } |
27 | 0 |
|
28 | 0 | unsafe { |
29 | 0 | if self.as_ptr() as usize % std::mem::align_of::<U>() != 0 { |
30 | 0 | panic!( |
31 | 0 | "Pointer 0x{:x} is misaligned for {}", |
32 | 0 | self.as_ptr() as usize, |
33 | 0 | std::any::type_name::<U>(), |
34 | 0 | ) |
35 | 0 | } |
36 | 0 |
|
37 | 0 | std::slice::from_raw_parts_mut( |
38 | 0 | self.as_mut_ptr().cast::<U>(), |
39 | 0 | bytes / std::mem::size_of::<U>(), |
40 | 0 | ) |
41 | 0 | } |
42 | 0 | } Unexecuted instantiation: <&mut [f32] as audio_processor::slice_cast::SliceCast>::cast::<u8> Unexecuted instantiation: <&mut [u8] as audio_processor::slice_cast::SliceCast>::cast::<f32> Unexecuted instantiation: <&mut [f32] as audio_processor::slice_cast::SliceCast>::cast::<u8> Unexecuted instantiation: <&mut [u8] as audio_processor::slice_cast::SliceCast>::cast::<f32> |
43 | | } |
44 | | |
45 | | #[cfg(test)] |
46 | | mod tests { |
47 | | use super::SliceCast; |
48 | | |
49 | | #[test] |
50 | | fn byte_to_u32() { |
51 | | let mut arr = [1u8, 2, 3, 4, 5, 6, 7, 8]; |
52 | | |
53 | | let u32slice: &mut [u32] = (&mut arr[..]).cast(); |
54 | | assert_eq!( |
55 | | u32slice, |
56 | | [ |
57 | | u32::from_ne_bytes([1u8, 2, 3, 4]), |
58 | | u32::from_ne_bytes([5u8, 6, 7, 8]), |
59 | | ] |
60 | | ); |
61 | | |
62 | | u32slice[0] = 0x12345678; |
63 | | u32slice[1] = 0x23456789; |
64 | | |
65 | | assert_eq!( |
66 | | &arr[..], |
67 | | 0x12345678u32 |
68 | | .to_ne_bytes() |
69 | | .into_iter() |
70 | | .chain(0x23456789u32.to_ne_bytes()) |
71 | | .collect::<Vec<u8>>() |
72 | | ); |
73 | | } |
74 | | |
75 | | #[test] |
76 | | fn u32_to_byte() { |
77 | | let mut arr = [0x12345678u32, 0x23456789u32]; |
78 | | |
79 | | let u8slice: &mut [u8] = (&mut arr[..]).cast(); |
80 | | assert_eq!( |
81 | | u8slice, |
82 | | 0x12345678u32 |
83 | | .to_ne_bytes() |
84 | | .into_iter() |
85 | | .chain(0x23456789u32.to_ne_bytes()) |
86 | | .collect::<Vec<u8>>() |
87 | | ); |
88 | | |
89 | | for (i, x) in u8slice.iter_mut().enumerate() { |
90 | | *x = i as u8 + 1; |
91 | | } |
92 | | assert_eq!( |
93 | | &arr[..], |
94 | | [ |
95 | | u32::from_ne_bytes([1u8, 2, 3, 4]), |
96 | | u32::from_ne_bytes([5u8, 6, 7, 8]), |
97 | | ] |
98 | | ); |
99 | | } |
100 | | |
101 | | #[test] |
102 | | #[should_panic(expected = "Cannot convert 7 x u8 to f32")] |
103 | | fn panic_incompatible_size() { |
104 | | let slice = unsafe { std::slice::from_raw_parts_mut(4 as *mut u8, 7) }; |
105 | | let _f32slice: &mut [f32] = slice.cast(); |
106 | | } |
107 | | |
108 | | #[test] |
109 | | #[should_panic(expected = "Pointer 0x32 is misaligned for f32")] |
110 | | fn panic_incompatible_alignment() { |
111 | | let slice = unsafe { std::slice::from_raw_parts_mut(50 as *mut u8, 8) }; |
112 | | let _f32slice: &mut [f32] = slice.cast(); |
113 | | } |
114 | | } |