1use 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}