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