rustbus/wire/
util.rs

1//! Utility functions used often in many places
2
3use crate::wire::errors::MarshalError;
4use crate::wire::errors::UnmarshalError;
5use crate::wire::unmarshal::UnmarshalResult;
6use crate::ByteOrder;
7
8#[inline(always)]
9pub fn pad_to_align(align_to: usize, buf: &mut Vec<u8>) {
10    let padding_needed = align_to - (buf.len() % align_to);
11    if padding_needed != align_to {
12        buf.resize(buf.len() + padding_needed, 0);
13        debug_assert!(buf.len() % align_to == 0);
14    }
15}
16
17pub fn write_u16(val: u16, byteorder: ByteOrder, buf: &mut Vec<u8>) {
18    match byteorder {
19        ByteOrder::LittleEndian => buf.extend(&val.to_le_bytes()[..]),
20        ByteOrder::BigEndian => buf.extend(&val.to_be_bytes()[..]),
21    }
22}
23#[inline]
24pub fn write_u32(val: u32, byteorder: ByteOrder, buf: &mut Vec<u8>) {
25    match byteorder {
26        ByteOrder::LittleEndian => buf.extend(&val.to_le_bytes()[..]),
27        ByteOrder::BigEndian => buf.extend(&val.to_be_bytes()[..]),
28    }
29}
30pub fn write_u64(val: u64, byteorder: ByteOrder, buf: &mut Vec<u8>) {
31    match byteorder {
32        ByteOrder::LittleEndian => buf.extend(&val.to_le_bytes()[..]),
33        ByteOrder::BigEndian => buf.extend(&val.to_be_bytes()[..]),
34    }
35}
36
37pub fn marshal_unixfd(
38    i: &crate::wire::UnixFd,
39    ctx: &mut crate::wire::marshal::MarshalContext,
40) -> Result<(), MarshalError> {
41    if let Some(fd) = i.get_raw_fd() {
42        let new_fd = nix::unistd::dup(fd).map_err(MarshalError::DupUnixFd)?;
43        ctx.fds.push(crate::wire::UnixFd::new(new_fd));
44
45        let idx = ctx.fds.len() - 1;
46        ctx.align_to(<crate::wire::UnixFd as crate::Signature>::alignment());
47        crate::wire::util::write_u32(idx as u32, ctx.byteorder, ctx.buf);
48        Ok(())
49    } else {
50        Err(MarshalError::EmptyUnixFd)
51    }
52}
53
54pub fn insert_u16(byteorder: ByteOrder, val: u16, buf: &mut [u8]) {
55    match byteorder {
56        ByteOrder::LittleEndian => {
57            buf[0] = (val) as u8;
58            buf[1] = (val >> 8) as u8;
59        }
60        ByteOrder::BigEndian => {
61            buf[0] = (val >> 8) as u8;
62            buf[1] = (val) as u8;
63        }
64    }
65}
66pub fn insert_u32(byteorder: ByteOrder, val: u32, buf: &mut [u8]) {
67    match byteorder {
68        ByteOrder::LittleEndian => {
69            buf[0] = (val) as u8;
70            buf[1] = (val >> 8) as u8;
71            buf[2] = (val >> 16) as u8;
72            buf[3] = (val >> 24) as u8;
73        }
74        ByteOrder::BigEndian => {
75            buf[0] = (val >> 24) as u8;
76            buf[1] = (val >> 16) as u8;
77            buf[2] = (val >> 8) as u8;
78            buf[3] = (val) as u8;
79        }
80    }
81}
82pub fn insert_u64(byteorder: ByteOrder, val: u64, buf: &mut [u8]) {
83    match byteorder {
84        ByteOrder::LittleEndian => {
85            buf[0] = (val) as u8;
86            buf[1] = (val >> 8) as u8;
87            buf[2] = (val >> 16) as u8;
88            buf[3] = (val >> 24) as u8;
89            buf[4] = (val >> 32) as u8;
90            buf[5] = (val >> 40) as u8;
91            buf[6] = (val >> 48) as u8;
92            buf[7] = (val >> 56) as u8;
93        }
94        ByteOrder::BigEndian => {
95            buf[7] = (val) as u8;
96            buf[6] = (val >> 8) as u8;
97            buf[5] = (val >> 16) as u8;
98            buf[4] = (val >> 24) as u8;
99            buf[3] = (val >> 32) as u8;
100            buf[2] = (val >> 40) as u8;
101            buf[1] = (val >> 48) as u8;
102            buf[0] = (val >> 56) as u8;
103        }
104    }
105}
106
107pub fn write_string(val: &str, byteorder: ByteOrder, buf: &mut Vec<u8>) {
108    let len = val.len() as u32;
109    write_u32(len, byteorder, buf);
110    buf.extend_from_slice(val.as_bytes());
111    buf.push(0);
112}
113
114pub fn write_signature(val: &str, buf: &mut Vec<u8>) {
115    let len = val.len() as u8;
116    buf.push(len);
117    buf.extend_from_slice(val.as_bytes());
118    buf.push(0);
119}
120
121pub fn parse_u64(number: &[u8], byteorder: ByteOrder) -> UnmarshalResult<u64> {
122    if number.len() < 8 {
123        return Err(UnmarshalError::NotEnoughBytes);
124    }
125    let val = match byteorder {
126        ByteOrder::LittleEndian => {
127            (number[0] as u64)
128                + ((number[1] as u64) << 8)
129                + ((number[2] as u64) << 16)
130                + ((number[3] as u64) << 24)
131                + ((number[4] as u64) << 32)
132                + ((number[5] as u64) << 40)
133                + ((number[6] as u64) << 48)
134                + ((number[7] as u64) << 56)
135        }
136        ByteOrder::BigEndian => {
137            (number[7] as u64)
138                + ((number[6] as u64) << 8)
139                + ((number[5] as u64) << 16)
140                + ((number[4] as u64) << 24)
141                + ((number[3] as u64) << 32)
142                + ((number[2] as u64) << 40)
143                + ((number[1] as u64) << 48)
144                + ((number[0] as u64) << 56)
145        }
146    };
147    Ok((8, val))
148}
149
150pub fn parse_u32(number: &[u8], byteorder: ByteOrder) -> UnmarshalResult<u32> {
151    if number.len() < 4 {
152        return Err(UnmarshalError::NotEnoughBytes);
153    }
154    let val = match byteorder {
155        ByteOrder::LittleEndian => {
156            (number[0] as u32)
157                + ((number[1] as u32) << 8)
158                + ((number[2] as u32) << 16)
159                + ((number[3] as u32) << 24)
160        }
161        ByteOrder::BigEndian => {
162            (number[3] as u32)
163                + ((number[2] as u32) << 8)
164                + ((number[1] as u32) << 16)
165                + ((number[0] as u32) << 24)
166        }
167    };
168    Ok((4, val))
169}
170
171pub fn parse_u16(number: &[u8], byteorder: ByteOrder) -> UnmarshalResult<u16> {
172    if number.len() < 2 {
173        return Err(UnmarshalError::NotEnoughBytes);
174    }
175    let val = match byteorder {
176        ByteOrder::LittleEndian => (number[0] as u16) + ((number[1] as u16) << 8),
177        ByteOrder::BigEndian => (number[1] as u16) + ((number[0] as u16) << 8),
178    };
179    Ok((2, val))
180}
181
182pub fn align_offset(align_to: usize, buf: &[u8], offset: usize) -> Result<usize, UnmarshalError> {
183    let padding_delete = align_to - (offset % align_to);
184    let padding_delete = if padding_delete == align_to {
185        0
186    } else {
187        padding_delete
188    };
189
190    if buf[offset..].len() < padding_delete {
191        return Err(UnmarshalError::NotEnoughBytes);
192    }
193    for x in 0..padding_delete {
194        if buf[offset + x] != b'\0' {
195            return Err(UnmarshalError::PaddingContainedData);
196        }
197    }
198    Ok(padding_delete)
199}
200
201pub fn unmarshal_signature(buf: &[u8]) -> UnmarshalResult<&str> {
202    if buf.is_empty() {
203        return Err(UnmarshalError::NotEnoughBytes);
204    }
205    let len = buf[0] as usize;
206    if buf.len() < len + 2 {
207        return Err(UnmarshalError::NotEnoughBytes);
208    }
209    let sig_buf = &buf[1..];
210    let string = std::str::from_utf8(&sig_buf[..len])
211        .map_err(|_| crate::params::validation::Error::InvalidUtf8)?;
212    Ok((len + 2, string))
213}
214
215pub fn unmarshal_string(byteorder: ByteOrder, buf: &[u8]) -> UnmarshalResult<String> {
216    let (bytes, string) = unmarshal_str(byteorder, buf)?;
217    Ok((bytes, string.into()))
218}
219
220pub fn unmarshal_str<'r, 'a: 'r>(byteorder: ByteOrder, buf: &'a [u8]) -> UnmarshalResult<&'r str> {
221    let len = parse_u32(buf, byteorder)?.1 as usize;
222    if buf.len() < len + 5 {
223        return Err(UnmarshalError::NotEnoughBytes);
224    }
225    let str_buf = &buf[4..];
226    let string = std::str::from_utf8(&str_buf[..len])
227        .map_err(|_| crate::params::validation::Error::InvalidUtf8)?;
228    if string.contains('\0') {
229        return Err(crate::params::validation::Error::StringContainsNullByte.into());
230    }
231    Ok((len + 5, string))
232}