smb_server_proto/
endian.rs1#[inline(always)]
12pub fn read_le(buf: &[u8], pos: usize, n: usize) -> Result<u64, crate::error::ProtoError> {
13 if pos + n > buf.len() {
14 return Err(crate::error::ProtoError::Overrun {
15 need: n,
16 at: pos,
17 have: buf.len(),
18 });
19 }
20 let mut v: u64 = 0;
21 for i in 0..n {
22 v |= (buf[pos + i] as u64) << (8 * i);
23 }
24 Ok(v)
25}
26
27#[inline(always)]
29pub fn write_le(buf: &mut [u8], pos: usize, val: u64, n: usize) {
30 for i in 0..n {
31 buf[pos + i] = ((val >> (8 * i)) & 0xff) as u8;
32 }
33}
34
35macro_rules! impl_le {
36 ($name:ident, $ty:ty, $size:expr) => {
37 #[inline(always)]
39 pub fn $name(buf: &[u8], pos: usize) -> Result<$ty, crate::error::ProtoError> {
40 if pos + $size > buf.len() {
41 return Err(crate::error::ProtoError::Overrun {
42 need: $size,
43 at: pos,
44 have: buf.len(),
45 });
46 }
47 let mut bytes = [0u8; $size];
48 bytes.copy_from_slice(&buf[pos..pos + $size]);
49 Ok(<$ty>::from_le_bytes(bytes))
50 }
51 };
52}
53
54impl_le!(read_u8_le, u8, 1);
55impl_le!(read_u16_le, u16, 2);
56impl_le!(read_u32_le, u32, 4);
57impl_le!(read_u64_le, u64, 8);
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn little_endian_reads() {
65 let buf = [0x34, 0x12, 0x78, 0x56, 0xEF, 0xCD, 0xAB, 0x90];
66 assert_eq!(read_u8_le(&buf, 0).unwrap(), 0x34);
67 assert_eq!(read_u16_le(&buf, 0).unwrap(), 0x1234);
68 assert_eq!(read_u32_le(&buf, 0).unwrap(), 0x5678_1234);
69 assert_eq!(read_u64_le(&buf, 0).unwrap(), 0x90AB_CDEF_5678_1234);
70 }
71
72 #[test]
73 fn overrun_returns_error() {
74 let buf = [0u8; 2];
75 assert!(read_u32_le(&buf, 0).is_err());
76 }
77
78 #[test]
79 fn works_on_synthetic_big_endian_host() {
80 let raw: [u8; 2] = [0x01, 0x02];
84 assert_eq!(u16::from_le_bytes(raw), 0x0201);
87 }
88}