1pub fn read_le_u64(buf: &[u8], off: usize) -> u64 {
5 u64::from_le_bytes(buf[off..off + 8].try_into().unwrap())
6}
7
8pub fn read_le_u32(buf: &[u8], off: usize) -> u32 {
10 u32::from_le_bytes(buf[off..off + 4].try_into().unwrap())
11}
12
13pub fn read_le_u16(buf: &[u8], off: usize) -> u16 {
15 u16::from_le_bytes(buf[off..off + 2].try_into().unwrap())
16}
17
18#[macro_export]
31macro_rules! field_size {
32 ($t:ty, $f:ident) => {{
33 let uninit = std::mem::MaybeUninit::<$t>::uninit();
37 let base = uninit.as_ptr();
38
39 let field_ptr = unsafe { std::ptr::addr_of!((*base).$f) };
42
43 unsafe {
50 (field_ptr.add(1) as *const u8).offset_from(field_ptr as *const u8)
51 as usize
52 }
53 }};
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59 use crate::raw::{
60 btrfs_dev_extent, btrfs_qgroup_info_item, btrfs_qgroup_limit_item,
61 btrfs_qgroup_status_item, btrfs_root_item, btrfs_stripe,
62 };
63
64 #[test]
65 fn field_size_matches_expected() {
66 assert_eq!(field_size!(btrfs_root_item, uuid), 16);
68 assert_eq!(field_size!(btrfs_root_item, parent_uuid), 16);
69 assert_eq!(field_size!(btrfs_root_item, received_uuid), 16);
70
71 assert_eq!(field_size!(btrfs_root_item, generation), 8);
73 assert_eq!(field_size!(btrfs_root_item, flags), 8);
74 assert_eq!(field_size!(btrfs_qgroup_info_item, rfer), 8);
75 assert_eq!(field_size!(btrfs_qgroup_limit_item, max_rfer), 8);
76 assert_eq!(field_size!(btrfs_qgroup_status_item, flags), 8);
77 assert_eq!(field_size!(btrfs_dev_extent, length), 8);
78
79 assert_eq!(field_size!(btrfs_stripe, dev_uuid), 16);
81 }
82
83 #[test]
84 fn read_le_u64_basic() {
85 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
86 assert_eq!(read_le_u64(&buf, 0), 0x0807060504030201);
87 }
88
89 #[test]
90 fn read_le_u64_at_offset() {
91 let buf = [0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
92 assert_eq!(read_le_u64(&buf, 2), 1);
93 }
94
95 #[test]
96 fn read_le_u32_basic() {
97 let buf = [0x78, 0x56, 0x34, 0x12];
98 assert_eq!(read_le_u32(&buf, 0), 0x12345678);
99 }
100
101 #[test]
102 fn read_le_u16_basic() {
103 let buf = [0x02, 0x01];
104 assert_eq!(read_le_u16(&buf, 0), 0x0102);
105 }
106}