1#[cfg(feature = "bstr")]
9pub use bstr;
10#[cfg(feature = "bstr")]
11use bstr::BStr;
12pub use byteorder;
13#[cfg(feature = "bytes")]
14pub use bytes;
15
16use byteorder::{BE, ByteOrder, LE, NativeEndian};
17use std::{fmt::Debug, hash::Hash, mem, str::Utf8Error};
18
19pub const U8: usize = 1;
21pub const U16: usize = 2;
23pub const U24: usize = 3;
25pub const U32: usize = 4;
27pub const U64: usize = 8;
29pub const U128: usize = 16;
31pub const I8: usize = 1;
33pub const I16: usize = 2;
35pub const I24: usize = 3;
37pub const I32: usize = 4;
39pub const I64: usize = 8;
41pub const I128: usize = 16;
43pub const F32: usize = 4;
45pub const F64: usize = 8;
47
48#[must_use]
52#[allow(clippy::cast_sign_loss, clippy::cast_possible_wrap)]
53pub fn padding(offset: usize, align: usize) -> usize {
54 let padding = -(offset as isize) as usize & (align - 1);
55 debug_assert_eq!(padding, (align - offset % align) % align);
56 padding
57}
58
59#[must_use]
63#[allow(clippy::cast_sign_loss, clippy::cast_possible_wrap)]
64pub fn aligned(offset: usize, align: usize) -> usize {
65 let aligned = (offset + align - 1) & -(align as isize) as usize;
66 debug_assert_eq!(aligned, offset + padding(offset, align));
67 aligned
68}
69
70pub trait InSitu<Scope = ()>: AsRef<[u8]> {
79 fn swap_size(&self) -> usize;
83 fn is_be(&self) -> bool;
85 fn is_le(&self) -> bool {
87 !self.is_be()
88 }
89 fn is_native(&self) -> bool {
91 self.is_be() == (NativeEndian::read_u16(&[0, 1]) == 1)
92 }
93 fn order(&self) -> Order {
95 if self.is_be() { Order::BE } else { Order::LE }
96 }
97 fn at(&self, offset: usize, word_size: usize) -> usize {
101 if self.is_be() || self.swap_size() < word_size {
102 offset
103 } else {
104 offset ^ (self.swap_size() - word_size)
105 }
106 }
107 fn utf8(&self, offset: usize, length: usize) -> Result<&str, Utf8Error> {
115 std::str::from_utf8(&self.as_ref()[offset..][..length])
116 }
117 #[cfg(feature = "bstr")]
119 fn bstr(&self, offset: usize, length: usize) -> &BStr {
120 BStr::new(&self.as_ref()[offset..][..length])
121 }
122 fn bool(&self, offset: usize) -> bool {
124 self.u8(offset) != 0
125 }
126 fn u8(&self, offset: usize) -> u8 {
128 let offset = self.at(offset, U8);
129 self.as_ref()[offset]
130 }
131 fn u16(&self, offset: usize) -> u16 {
133 let offset = self.at(offset, U16);
134 if self.is_be() {
135 BE::read_u16(&self.as_ref()[offset..])
136 } else {
137 LE::read_u16(&self.as_ref()[offset..])
138 }
139 }
140 fn u24(&self, offset: usize) -> u32 {
143 let offset = self.at(offset, U24);
144 if self.is_be() {
145 BE::read_u24(&self.as_ref()[offset..])
146 } else {
147 LE::read_u24(&self.as_ref()[offset..])
148 }
149 }
150 fn u32(&self, offset: usize) -> u32 {
152 let offset = self.at(offset, U32);
153 if self.is_be() {
154 BE::read_u32(&self.as_ref()[offset..])
155 } else {
156 LE::read_u32(&self.as_ref()[offset..])
157 }
158 }
159 fn u64(&self, offset: usize) -> u64 {
161 let offset = self.at(offset, U64);
162 if self.is_be() {
163 BE::read_u64(&self.as_ref()[offset..])
164 } else {
165 LE::read_u64(&self.as_ref()[offset..])
166 }
167 }
168 fn u128(&self, offset: usize) -> u128 {
170 let offset = self.at(offset, U128);
171 if self.is_be() {
172 BE::read_u128(&self.as_ref()[offset..])
173 } else {
174 LE::read_u128(&self.as_ref()[offset..])
175 }
176 }
177 fn uint(&self, offset: usize, word_size: usize) -> u64 {
180 let offset = self.at(offset, word_size);
181 if self.is_be() {
182 BE::read_uint(&self.as_ref()[offset..], word_size)
183 } else {
184 LE::read_uint(&self.as_ref()[offset..], word_size)
185 }
186 }
187 fn uint128(&self, offset: usize, word_size: usize) -> u128 {
190 let offset = self.at(offset, word_size);
191 if self.is_be() {
192 BE::read_uint128(&self.as_ref()[offset..], word_size)
193 } else {
194 LE::read_uint128(&self.as_ref()[offset..], word_size)
195 }
196 }
197 #[allow(clippy::cast_possible_wrap)]
199 fn i8(&self, offset: usize) -> i8 {
200 let offset = self.at(offset, I8);
201 self.as_ref()[offset] as i8
202 }
203 fn i16(&self, offset: usize) -> i16 {
205 let offset = self.at(offset, I16);
206 if self.is_be() {
207 BE::read_i16(&self.as_ref()[offset..])
208 } else {
209 LE::read_i16(&self.as_ref()[offset..])
210 }
211 }
212 fn i24(&self, offset: usize) -> i32 {
215 let offset = self.at(offset, I24);
216 if self.is_be() {
217 BE::read_i24(&self.as_ref()[offset..])
218 } else {
219 LE::read_i24(&self.as_ref()[offset..])
220 }
221 }
222 fn i32(&self, offset: usize) -> i32 {
224 let offset = self.at(offset, I32);
225 if self.is_be() {
226 BE::read_i32(&self.as_ref()[offset..])
227 } else {
228 LE::read_i32(&self.as_ref()[offset..])
229 }
230 }
231 fn i64(&self, offset: usize) -> i64 {
233 let offset = self.at(offset, I64);
234 if self.is_be() {
235 BE::read_i64(&self.as_ref()[offset..])
236 } else {
237 LE::read_i64(&self.as_ref()[offset..])
238 }
239 }
240 fn i128(&self, offset: usize) -> i128 {
242 let offset = self.at(offset, I128);
243 if self.is_be() {
244 BE::read_i128(&self.as_ref()[offset..])
245 } else {
246 LE::read_i128(&self.as_ref()[offset..])
247 }
248 }
249 fn int(&self, offset: usize, word_size: usize) -> i64 {
252 let offset = self.at(offset, word_size);
253 if self.is_be() {
254 BE::read_int(&self.as_ref()[offset..], word_size)
255 } else {
256 LE::read_int(&self.as_ref()[offset..], word_size)
257 }
258 }
259 fn int128(&self, offset: usize, word_size: usize) -> i128 {
262 let offset = self.at(offset, word_size);
263 if self.is_be() {
264 BE::read_int128(&self.as_ref()[offset..], word_size)
265 } else {
266 LE::read_int128(&self.as_ref()[offset..], word_size)
267 }
268 }
269 fn f32(&self, offset: usize) -> f32 {
271 let offset = self.at(offset, F32);
272 if self.is_be() {
273 BE::read_f32(&self.as_ref()[offset..])
274 } else {
275 LE::read_f32(&self.as_ref()[offset..])
276 }
277 }
278 fn f64(&self, offset: usize) -> f64 {
280 let offset = self.at(offset, F64);
281 if self.is_be() {
282 BE::read_f64(&self.as_ref()[offset..])
283 } else {
284 LE::read_f64(&self.as_ref()[offset..])
285 }
286 }
287}
288
289pub trait InSituMut<Scope = ()>: InSitu<Scope> + AsMut<[u8]> {
299 fn set_bool(&mut self, offset: usize, value: bool) {
302 self.set_u8(offset, value.into());
303 }
304 fn set_u8(&mut self, offset: usize, value: u8) {
306 let at = self.at(offset, U8);
307 self.as_mut()[at] = value;
308 }
309 fn set_u16(&mut self, offset: usize, value: u16) {
312 let offset = self.at(offset, U16);
313 if self.is_be() {
314 BE::write_u16(&mut self.as_mut()[offset..], value);
315 } else {
316 LE::write_u16(&mut self.as_mut()[offset..], value);
317 }
318 }
319 fn set_u24(&mut self, offset: usize, value: u32) {
322 let offset = self.at(offset, U24);
323 if self.is_be() {
324 BE::write_u24(&mut self.as_mut()[offset..], value);
325 } else {
326 LE::write_u24(&mut self.as_mut()[offset..], value);
327 }
328 }
329 fn set_u32(&mut self, offset: usize, value: u32) {
332 let offset = self.at(offset, U32);
333 if self.is_be() {
334 BE::write_u32(&mut self.as_mut()[offset..], value);
335 } else {
336 LE::write_u32(&mut self.as_mut()[offset..], value);
337 }
338 }
339 fn set_u64(&mut self, offset: usize, value: u64) {
342 let offset = self.at(offset, U64);
343 if self.is_be() {
344 BE::write_u64(&mut self.as_mut()[offset..], value);
345 } else {
346 LE::write_u64(&mut self.as_mut()[offset..], value);
347 }
348 }
349 fn set_u128(&mut self, offset: usize, value: u128) {
352 let offset = self.at(offset, U128);
353 if self.is_be() {
354 BE::write_u128(&mut self.as_mut()[offset..], value);
355 } else {
356 LE::write_u128(&mut self.as_mut()[offset..], value);
357 }
358 }
359 fn set_uint(&mut self, offset: usize, value: u64, word_size: usize) {
362 let offset = self.at(offset, word_size);
363 if self.is_be() {
364 BE::write_uint(&mut self.as_mut()[offset..], value, word_size);
365 } else {
366 LE::write_uint(&mut self.as_mut()[offset..], value, word_size);
367 }
368 }
369 fn set_uint128(&mut self, offset: usize, value: u128, word_size: usize) {
372 let offset = self.at(offset, word_size);
373 if self.is_be() {
374 BE::write_uint128(&mut self.as_mut()[offset..], value, word_size);
375 } else {
376 LE::write_uint128(&mut self.as_mut()[offset..], value, word_size);
377 }
378 }
379 #[allow(clippy::cast_sign_loss)]
381 fn set_i8(&mut self, offset: usize, value: i8) {
382 let at = self.at(offset, I8);
383 self.as_mut()[at] = value as u8;
384 }
385 fn set_i16(&mut self, offset: usize, value: i16) {
388 let offset = self.at(offset, I16);
389 if self.is_be() {
390 BE::write_i16(&mut self.as_mut()[offset..], value);
391 } else {
392 LE::write_i16(&mut self.as_mut()[offset..], value);
393 }
394 }
395 fn set_i24(&mut self, offset: usize, value: i32) {
398 let offset = self.at(offset, I24);
399 if self.is_be() {
400 BE::write_i24(&mut self.as_mut()[offset..], value);
401 } else {
402 LE::write_i24(&mut self.as_mut()[offset..], value);
403 }
404 }
405 fn set_i32(&mut self, offset: usize, value: i32) {
408 let offset = self.at(offset, I32);
409 if self.is_be() {
410 BE::write_i32(&mut self.as_mut()[offset..], value);
411 } else {
412 LE::write_i32(&mut self.as_mut()[offset..], value);
413 }
414 }
415 fn set_i64(&mut self, offset: usize, value: i64) {
418 let offset = self.at(offset, I64);
419 if self.is_be() {
420 BE::write_i64(&mut self.as_mut()[offset..], value);
421 } else {
422 LE::write_i64(&mut self.as_mut()[offset..], value);
423 }
424 }
425 fn set_i128(&mut self, offset: usize, value: i128) {
428 let offset = self.at(offset, I128);
429 if self.is_be() {
430 BE::write_i128(&mut self.as_mut()[offset..], value);
431 } else {
432 LE::write_i128(&mut self.as_mut()[offset..], value);
433 }
434 }
435 fn set_int(&mut self, offset: usize, value: i64, word_size: usize) {
438 let offset = self.at(offset, word_size);
439 if self.is_be() {
440 BE::write_int(&mut self.as_mut()[offset..], value, word_size);
441 } else {
442 LE::write_int(&mut self.as_mut()[offset..], value, word_size);
443 }
444 }
445 fn set_int128(&mut self, offset: usize, value: i128, word_size: usize) {
448 let offset = self.at(offset, word_size);
449 if self.is_be() {
450 BE::write_int128(&mut self.as_mut()[offset..], value, word_size);
451 } else {
452 LE::write_int128(&mut self.as_mut()[offset..], value, word_size);
453 }
454 }
455 fn set_f32(&mut self, offset: usize, value: f32) {
458 let offset = self.at(offset, F32);
459 if self.is_be() {
460 BE::write_f32(&mut self.as_mut()[offset..], value);
461 } else {
462 LE::write_f32(&mut self.as_mut()[offset..], value);
463 }
464 }
465 fn set_f64(&mut self, offset: usize, value: f64) {
468 let offset = self.at(offset, F64);
469 if self.is_be() {
470 BE::write_f64(&mut self.as_mut()[offset..], value);
471 } else {
472 LE::write_f64(&mut self.as_mut()[offset..], value);
473 }
474 }
475}
476
477pub trait Raw: AsRef<[u8]> + Default + PartialEq + Eq + PartialOrd + Ord + Debug + Hash {
489 #[must_use]
494 fn split_off(&mut self, at: usize) -> Self;
495 #[must_use]
500 fn split_to(&mut self, at: usize) -> Self;
501}
502
503pub trait RawMut: Raw + AsMut<[u8]> {}
510
511impl<T: Raw + AsMut<[u8]>> RawMut for T {}
513
514impl Raw for &[u8] {
515 fn split_off(&mut self, at: usize) -> Self {
516 let (l, r) = self.split_at(at);
517 *self = l;
518 r
519 }
520 fn split_to(&mut self, at: usize) -> Self {
521 let (l, r) = self.split_at(at);
522 *self = r;
523 l
524 }
525}
526
527impl Raw for &mut [u8] {
528 fn split_off(&mut self, at: usize) -> Self {
529 let slice = mem::take(self);
530 let (l, r) = slice.split_at_mut(at);
531 *self = l;
532 r
533 }
534 fn split_to(&mut self, at: usize) -> Self {
535 let slice = mem::take(self);
536 let (l, r) = slice.split_at_mut(at);
537 *self = r;
538 l
539 }
540}
541
542#[cfg(feature = "bytes")]
543impl Raw for bytes::Bytes {
544 fn split_off(&mut self, at: usize) -> Self {
545 self.split_off(at)
546 }
547 fn split_to(&mut self, at: usize) -> Self {
548 self.split_to(at)
549 }
550}
551
552#[cfg(feature = "bytes")]
553impl Raw for bytes::BytesMut {
554 fn split_off(&mut self, at: usize) -> Self {
555 self.split_off(at)
556 }
557 fn split_to(&mut self, at: usize) -> Self {
558 self.split_to(at)
559 }
560}
561
562#[derive(Debug, Clone, Copy, PartialEq, Eq)]
564pub enum Order {
565 BE,
567 LE,
569}
570
571#[derive(Debug, Clone, Copy, PartialEq, Eq)]
573pub enum Take {
574 Header,
576 Packet,
578}