leaprs/
sized_with_trailing_data.rs1use std::alloc::Layout;
2
3#[repr(C, packed)]
5pub(crate) struct SizedWithTrailingData<T> {
6 pub sized: T,
7 pub trailing: [u8],
8}
9
10impl<T> SizedWithTrailingData<T> {
11 pub fn allocate(sized: T, trailing_size: usize) -> Box<Self> {
14 let (layout, arr_base) = Layout::array::<usize>(trailing_size)
16 .and_then(|arr_layout| Layout::new::<T>().extend(arr_layout))
17 .unwrap();
18 let ptr = unsafe { std::alloc::alloc(layout) };
19 if ptr.is_null() {
21 panic!("Internal allocation error");
22 }
23
24 unsafe {
25 ptr.cast::<T>().write(sized);
26 let tmp_ptr = ptr.add(arr_base).cast::<usize>();
27 (0..trailing_size).for_each(|i| tmp_ptr.add(i).write(0));
29
30 Box::from_raw(
32 std::ptr::slice_from_raw_parts_mut(ptr as *mut usize, trailing_size)
33 as *mut SizedWithTrailingData<T>,
34 )
35 }
36 }
37
38 pub fn size(&self) -> usize {
39 std::mem::size_of::<T>() + std::mem::size_of_val(&self.trailing)
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use leap_sys::LEAP_TRACKING_EVENT;
46
47 use super::*;
48
49 #[test]
50 pub fn event_with_trailing() {
51 let mut tracking_event: LEAP_TRACKING_EVENT;
52
53 unsafe {
54 tracking_event = std::mem::zeroed();
55 tracking_event.tracking_frame_id = 42;
56 }
57 let mut dst = SizedWithTrailingData::allocate(tracking_event, 4);
58 dst.sized.tracking_frame_id = 42;
59 dst.trailing[0] = 1;
60 dst.trailing[1] = 3;
61 dst.trailing[2] = 5;
62 dst.trailing[3] = 7;
63
64 let sized = dst.sized;
65 let frame = sized.tracking_frame_id;
66 assert_eq!(frame, 42);
67 assert_eq!(dst.trailing[0], 1);
68 assert_eq!(dst.trailing[1], 3);
69 assert_eq!(dst.trailing[2], 5);
70 assert_eq!(dst.trailing[3], 7);
71 }
72
73 #[test]
74 pub fn string_with_trailing() {
75 let mut tracking_event: LEAP_TRACKING_EVENT;
76
77 unsafe {
78 tracking_event = std::mem::zeroed();
79 tracking_event.tracking_frame_id = 42;
80 }
81 let mut dst = SizedWithTrailingData::allocate("hello".to_string(), 4);
82 dst.trailing[0] = 1;
83 dst.trailing[1] = 3;
84 dst.trailing[2] = 5;
85 dst.trailing[3] = 7;
86
87 let sized = dst.sized;
88 assert_eq!(sized, "hello".to_string());
89 assert_eq!(dst.trailing[0], 1);
90 assert_eq!(dst.trailing[1], 3);
91 assert_eq!(dst.trailing[2], 5);
92 assert_eq!(dst.trailing[3], 7);
93 }
94}