ts_packet/lib.rs
1#![doc = include_str!("../README.md")]
2#![no_std]
3
4extern crate alloc;
5
6/// Geneve (RFC 8926) fixed-header codec for Tailscale peer-relay framing.
7pub mod geneve;
8
9use alloc::{borrow::ToOwned, string::String, vec::Vec};
10use core::{
11 fmt::{self, LowerHex, UpperHex},
12 net::IpAddr,
13 ops::{Index, IndexMut},
14 slice::{Iter, IterMut, SliceIndex},
15};
16
17use bytes::{Buf, BufMut, Bytes, BytesMut, buf::UninitSlice};
18use ts_hexdump::{AsHexExt, Case, hex_fmt};
19
20/// An immutable, contiguous sequence of bytes, specialized for networking applications.
21#[derive(Clone, Eq, PartialEq, Ord, PartialOrd)]
22pub struct Packet {
23 contents: Bytes,
24}
25
26impl Packet {
27 /// The empty packet.
28 pub const EMPTY: Packet = Packet {
29 contents: Bytes::from_static(&[]),
30 };
31
32 /// Returns `true` if this [`Packet`] has a length of 0.
33 ///
34 /// # Examples
35 /// ```
36 /// # use ts_packet::Packet;
37 /// let pkt = Packet::from(vec![]);
38 /// assert!(pkt.is_empty());
39 /// ```
40 pub fn is_empty(&self) -> bool {
41 self.contents.is_empty()
42 }
43
44 /// Returns an iterator over the bytes in this [`Packet`]. The iterator yields all bytes in
45 /// order from start to end.
46 ///
47 /// # Examples
48 /// ```
49 /// # use ts_packet::Packet;
50 /// let pkt = Packet::from(vec![0xAA, 0xBB, 0xCC]);
51 /// let mut iter = pkt.iter();
52 /// assert_eq!(iter.next(), Some(&0xAA));
53 /// assert_eq!(iter.next(), Some(&0xBB));
54 /// assert_eq!(iter.next(), Some(&0xCC));
55 /// assert_eq!(iter.next(), None);
56 /// ```
57 pub fn iter(&'_ self) -> Iter<'_, u8> {
58 self.contents.iter()
59 }
60
61 /// Returns the number of bytes contained in this [`Packet`].
62 ///
63 /// # Examples
64 /// ```
65 /// # use ts_packet::Packet;
66 /// let pkt = Packet::from(vec![1, 2, 3]);
67 /// assert_eq!(pkt.len(), 3);
68 /// ```
69 pub fn len(&self) -> usize {
70 self.contents.len()
71 }
72}
73
74impl fmt::Debug for Packet {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 write!(f, "{self:X}")
77 }
78}
79
80impl AsRef<[u8]> for Packet {
81 fn as_ref(&self) -> &[u8] {
82 self.contents.as_ref()
83 }
84}
85
86impl Buf for Packet {
87 fn remaining(&self) -> usize {
88 self.contents.remaining()
89 }
90
91 fn chunk(&self) -> &[u8] {
92 &self.contents
93 }
94
95 fn advance(&mut self, cnt: usize) {
96 self.contents.advance(cnt);
97 }
98}
99
100impl From<&[u8]> for Packet {
101 fn from(value: &[u8]) -> Self {
102 Self {
103 contents: Bytes::from(value.to_owned()),
104 }
105 }
106}
107impl From<Bytes> for Packet {
108 fn from(value: Bytes) -> Self {
109 Self { contents: value }
110 }
111}
112
113impl From<BytesMut> for Packet {
114 fn from(value: BytesMut) -> Self {
115 Self {
116 contents: value.freeze(),
117 }
118 }
119}
120
121impl From<PacketMut> for Packet {
122 fn from(value: PacketMut) -> Self {
123 value.freeze()
124 }
125}
126
127impl From<Vec<u8>> for Packet {
128 fn from(value: Vec<u8>) -> Self {
129 Self {
130 contents: value.into(),
131 }
132 }
133}
134
135impl<T> Index<T> for Packet
136where
137 // This instance is provided by implicit deref to [u8] on Bytes
138 [u8]: Index<T>,
139{
140 type Output = <[u8] as Index<T>>::Output;
141
142 #[inline]
143 fn index(&self, index: T) -> &Self::Output {
144 self.contents.index(index)
145 }
146}
147
148impl LowerHex for Packet {
149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150 write!(
151 f,
152 "{}",
153 self.iter().hex(Case::Lower).flatten().collect::<String>()
154 )
155 }
156}
157
158impl UpperHex for Packet {
159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160 write!(
161 f,
162 "{}",
163 self.iter().hex(Case::Upper).flatten().collect::<String>()
164 )
165 }
166}
167
168/// A mutable, contiguous, growable sequence of bytes, specialized for networking applications.
169#[derive(Clone, Eq, PartialEq, Ord, PartialOrd)]
170pub struct PacketMut {
171 /// The backing buffer for this packet; effectively a pointer, length, and capacity of a
172 /// contiguous slice of memory. Supports dynamic resizing/reallocation when necessary.
173 contents: BytesMut,
174}
175
176impl PacketMut {
177 /// Constructs a new [PacketMut] and allocates an underlying buffer of the given `size` on the
178 /// heap. The newly-allocated underlying buffer is filled with zero bytes (`0u8`).
179 ///
180 /// # Examples
181 /// ```
182 /// # use ts_packet::PacketMut;
183 /// let mut pkt = PacketMut::new(5);
184 /// assert_eq!(pkt.len(), 5);
185 /// assert_eq!(pkt.as_ref(), &[0, 0, 0, 0, 0]);
186 /// pkt[4] = 42;
187 /// assert_eq!(pkt.as_ref(), &[0, 0, 0, 0, 42]);
188 /// ```
189 pub fn new(size: usize) -> Self {
190 Self {
191 contents: BytesMut::zeroed(size),
192 }
193 }
194
195 /// Constructs a new [PacketMut] with at least the specified capacity. The packet will be able
196 /// to hold at least `size` bytes without reallocating.
197 ///
198 /// Note that the packet will have at least the given *capacity*, but will have a *length* of
199 /// zero until bytes are added to it.
200 ///
201 /// # Examples
202 /// ```
203 /// # use ts_packet::PacketMut;
204 /// let mut pkt = PacketMut::with_capacity(5);
205 /// assert_eq!(pkt.len(), 0);
206 /// assert_eq!(pkt.capacity(), 5);
207 /// ```
208 pub fn with_capacity(size: usize) -> Self {
209 Self {
210 contents: BytesMut::with_capacity(size),
211 }
212 }
213
214 /// Returns the number of contiguous bytes the underlying buffer can hold without reallocating.
215 ///
216 /// # Examples
217 /// ```
218 /// # use ts_packet::PacketMut;
219 /// let mut pkt = PacketMut::with_capacity(3);
220 /// assert_eq!(pkt.len(), 0);
221 /// assert_eq!(pkt.capacity(), 3);
222 /// ```
223 pub fn capacity(&self) -> usize {
224 self.contents.capacity()
225 }
226
227 /// Appends the given bytes to the end of this [`PacketMut`]. The underlying buffer is
228 /// resized if it does not have enough capacity.
229 ///
230 /// # Examples
231 /// Extending within the underlying buffer's capacity increases the length, but not the
232 /// capacity:
233 /// ```
234 /// # use ts_packet::PacketMut;
235 /// let mut pkt = PacketMut::with_capacity(3);
236 /// pkt.extend_from_slice(&[1, 2, 3]);
237 /// assert_eq!(pkt.len(), 3);
238 /// assert_eq!(pkt.capacity(), 3);
239 /// ```
240 ///
241 /// Extending *beyond* the backing buffer's capacity triggers a reallocation, changing both the
242 /// length and the capacity:
243 /// ```
244 /// # use ts_packet::PacketMut;
245 /// let mut pkt = PacketMut::with_capacity(3);
246 /// pkt.extend_from_slice(&[1, 2, 3, 4]);
247 /// assert_eq!(pkt.len(), 4);
248 /// assert_eq!(pkt.capacity(), 8);
249 /// ```
250 pub fn extend_from_slice(&mut self, slice: &[u8]) {
251 self.contents.extend_from_slice(slice);
252 }
253
254 /// Add the given number of zero bytes to the front of this `[PacketMut]`. The underlying
255 /// buffer is resized if it does not have enough capacity.
256 pub fn grow_front(&mut self, len: usize) {
257 let existing_len = self.contents.len();
258 self.contents.resize(existing_len + len, 0);
259 self.contents.copy_within(..existing_len, len);
260 self.contents[..len].fill(0);
261 }
262
263 /// Prepends the given bytes to this [`PacketMut`]. The underlying buffer is resized if it
264 /// does not have enough capacity.
265 pub fn extend_front_from_slice(&mut self, slice: &[u8]) {
266 self.grow_front(slice.len());
267 self.contents[..slice.len()].copy_from_slice(slice);
268 }
269
270 /// Returns a reference to an element or subslice depending on the type of index.
271 ///
272 /// If given a position, returns a reference to the element at that position or None if out of bounds.
273 /// If given a range, returns the subslice corresponding to that range, or None if out of bounds.
274 pub fn get<I>(&self, index: I) -> Option<&<I as SliceIndex<[u8]>>::Output>
275 where
276 I: SliceIndex<[u8]>,
277 {
278 self.contents.get(index)
279 }
280
281 /// Returns a mutable reference to an element or subslice depending on the type of index.
282 ///
283 /// If given a position, returns a reference to the element at that position or None if out of bounds.
284 /// If given a range, returns the subslice corresponding to that range, or None if out of bounds.
285 pub fn get_mut<I>(&mut self, index: I) -> Option<&mut <I as SliceIndex<[u8]>>::Output>
286 where
287 I: SliceIndex<[u8]>,
288 {
289 self.contents.get_mut(index)
290 }
291
292 /// Converts `self` into an immutable [`Packet`]. This is a zero-cost type conversion simply to
293 /// indicate the returned packet won't be mutated anymore, allowing the packet to be cheaply
294 /// cloned and moved between execution contexts (threads/async tasks).
295 ///
296 /// # Examples
297 /// ```
298 /// # use ts_packet::PacketMut;
299 /// let mut pkt_mut = PacketMut::with_capacity(4);
300 /// pkt_mut.extend_from_slice(b"hello world");
301 /// let pkt1 = pkt_mut.freeze();
302 /// let pkt2 = pkt1.clone();
303 /// assert_eq!(pkt1, pkt2);
304 /// let th = std::thread::spawn(move || {
305 /// assert_eq!(&pkt1[..], b"hello world");
306 /// });
307 /// assert_eq!(&pkt2[..], b"hello world");
308 /// th.join().unwrap();
309 /// ```
310 pub fn freeze(self) -> Packet {
311 Packet {
312 contents: self.contents.freeze(),
313 }
314 }
315
316 /// Returns `true` if this [`PacketMut`] has a length of 0.
317 ///
318 /// # Examples
319 /// ```
320 /// # use ts_packet::PacketMut;
321 /// let pkt = PacketMut::from(&[]);
322 /// assert!(pkt.is_empty());
323 /// ```
324 pub fn is_empty(&self) -> bool {
325 self.len() == 0
326 }
327
328 /// Returns an iterator over the bytes in this [`PacketMut`]. The iterator yields all bytes in
329 /// order from start to end.
330 ///
331 /// # Examples
332 /// ```
333 /// # use ts_packet::PacketMut;
334 /// let pkt = PacketMut::from(&[0xAA, 0xBB, 0xCC]);
335 /// let mut iter = pkt.iter();
336 /// assert_eq!(iter.next(), Some(&0xAA));
337 /// assert_eq!(iter.next(), Some(&0xBB));
338 /// assert_eq!(iter.next(), Some(&0xCC));
339 /// assert_eq!(iter.next(), None);
340 /// ```
341 pub fn iter(&'_ self) -> Iter<'_, u8> {
342 self.contents.iter()
343 }
344
345 /// Returns an iterator over the bytes in this [`PacketMut`] that allows modifying each value.
346 /// The iterator yields all bytes in order from start to end.
347 ///
348 /// # Examples
349 /// ```
350 /// # use ts_packet::PacketMut;
351 /// let mut pkt = PacketMut::from(&[0xAA, 0xBB, 0xCC]);
352 /// for byte in pkt.iter_mut() {
353 /// *byte += 1;
354 /// }
355 /// assert_eq!(pkt.as_ref(), &[0xAB, 0xBC, 0xCD]);
356 /// ```
357 pub fn iter_mut(&'_ mut self) -> IterMut<'_, u8> {
358 self.contents.iter_mut()
359 }
360
361 /// Returns the number of bytes contained in this [`PacketMut`].
362 ///
363 /// # Examples
364 /// ```
365 /// # use ts_packet::PacketMut;
366 /// let pkt = PacketMut::from(&[1, 2, 3]);
367 /// assert_eq!(pkt.len(), 3);
368 /// ```
369 pub fn len(&self) -> usize {
370 self.contents.len()
371 }
372
373 /// Removes the last `count` bytes from the end of this [`PacketMut`], leaving
374 /// `self.len() - count` bytes in the packet. Existing capacity is preserved and the backing
375 /// buffer is not changed.
376 ///
377 /// # Examples
378 /// ```
379 /// # use ts_packet::PacketMut;
380 /// let mut pkt = PacketMut::from(&[1, 2, 3, 4, 5]);
381 /// pkt.truncate(3);
382 /// assert_eq!(pkt, PacketMut::from(&[1, 2, 3]));
383 /// ```
384 pub fn truncate(&mut self, count: usize) {
385 self.contents.truncate(count);
386 }
387
388 /// Removes the first `count` bytes from the front of this [`PacketMut`], leaving
389 /// `self.len() - count` bytes in the packet. Existing capacity is preserved and the backing
390 /// buffer is not changed.
391 ///
392 /// # Panics
393 ///
394 /// Panics if `at > self.len()`.
395 ///
396 /// # Examples
397 /// ```
398 /// # use ts_packet::PacketMut;
399 /// let mut pkt = PacketMut::from(&[1, 2, 3, 4, 5]);
400 /// pkt.truncate_front(2);
401 /// assert_eq!(pkt, PacketMut::from(&[3, 4, 5]));
402 /// ```
403 pub fn truncate_front(&mut self, count: usize) {
404 self.contents.advance(count);
405 }
406
407 /// Splits the [`PacketMut`] into two at the given index.
408 ///
409 /// After the call, `self` will contain the bytes `[0, at)`, and the returned [`PacketMut`]
410 /// will contain the bytes `[at, capacity)`. Existing capacity is preserved, the backing buffer
411 /// is not changed, and both `self` and the returned [`PacketMut`] share the same backing
412 /// buffer.
413 ///
414 /// # Panics
415 ///
416 /// Panics if `at > len`.
417 ///
418 /// # Complexity
419 ///
420 /// O(1). Indices are adjusted and reference counts are updated, but none of the backing
421 /// buffer is traversed or cloned.
422 ///
423 /// # Examples
424 ///
425 /// ```
426 /// # use ts_packet::PacketMut;
427 /// let mut pkt1 = PacketMut::from(&[1, 2, 3, 4, 5]);
428 /// let pkt2 = pkt1.split_off(2);
429 /// assert_eq!(pkt1, PacketMut::from(&[1, 2]));
430 /// assert_eq!(pkt2, PacketMut::from(&[3, 4, 5]));
431 /// ```
432 pub fn split_off(&mut self, at: usize) -> PacketMut {
433 Self {
434 contents: self.contents.split_off(at),
435 }
436 }
437
438 /// Splits the [`PacketMut`] into two at the given index.
439 ///
440 /// After the call, `self` will contain the bytes `[at, len)`, and the returned [`PacketMut`]
441 /// will contain the bytes `[0, at)`. Existing capacity is preserved, the backing buffer
442 /// is not changed, and both `self` and the returned [`PacketMut`] share the same backing
443 /// buffer.
444 ///
445 /// # Panics
446 ///
447 /// Panics if `at > len`.
448 ///
449 /// # Complexity
450 ///
451 /// O(1). Indices are adjusted and reference counts are updated, but none of the backing
452 /// buffer is traversed or cloned.
453 ///
454 /// # Examples
455 ///
456 /// ```
457 /// # use ts_packet::PacketMut;
458 /// let mut pkt1 = PacketMut::from(&[1, 2, 3, 4, 5]);
459 /// let pkt2 = pkt1.split_to(2);
460 /// assert_eq!(pkt1, PacketMut::from(&[3, 4, 5]));
461 /// assert_eq!(pkt2, PacketMut::from(&[1, 2]));
462 /// ```
463 pub fn split_to(&mut self, at: usize) -> PacketMut {
464 Self {
465 contents: self.contents.split_to(at),
466 }
467 }
468
469 fn get_ip_family(&self) -> Option<u8> {
470 match self.get(0)? >> 4 {
471 4 => Some(4),
472 6 => Some(6),
473 _ => None,
474 }
475 }
476
477 /// Returns the bytes at idx..idx+4 interpreted as a network-endian IPv4 address.
478 fn ipv4_at(&self, idx: usize) -> Option<IpAddr> {
479 let octets: [u8; 4] = self.get(idx..idx + 4)?.try_into().unwrap();
480 Some(IpAddr::from(octets))
481 }
482
483 /// Returns the bytes at idx..idx+16 interpreted as a network-endian IPv6 address.
484 fn ipv6_at(&self, idx: usize) -> Option<IpAddr> {
485 let octets: [u8; 16] = self.get(idx..idx + 16)?.try_into().unwrap();
486 Some(IpAddr::from(octets))
487 }
488
489 /// Returns the source IP address of the packet.
490 ///
491 /// Returns None if the packet structure doesn't match an IPv4 or IPv6 datagram.
492 pub fn get_src_addr(&self) -> Option<IpAddr> {
493 match self.get_ip_family() {
494 Some(4) => self.ipv4_at(12),
495 Some(6) => self.ipv6_at(8),
496 _ => None,
497 }
498 }
499
500 /// Returns the destination IP address of the packet.
501 ///
502 /// Returns None if the packet structure doesn't match an IPv4 or IPv6 datagram.
503 pub fn get_dst_addr(&self) -> Option<IpAddr> {
504 match self.get_ip_family() {
505 Some(4) => self.ipv4_at(16),
506 Some(6) => self.ipv6_at(24),
507 _ => None,
508 }
509 }
510}
511
512impl fmt::Debug for PacketMut {
513 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
514 write!(f, "{self:X}")
515 }
516}
517
518impl AsMut<[u8]> for PacketMut {
519 fn as_mut(&mut self) -> &mut [u8] {
520 self.contents.as_mut()
521 }
522}
523
524impl AsRef<[u8]> for PacketMut {
525 fn as_ref(&self) -> &[u8] {
526 self.contents.as_ref()
527 }
528}
529
530impl Buf for PacketMut {
531 fn remaining(&self) -> usize {
532 self.contents.remaining_mut()
533 }
534
535 fn chunk(&self) -> &[u8] {
536 &self.contents
537 }
538
539 fn advance(&mut self, cnt: usize) {
540 self.contents.advance(cnt)
541 }
542}
543
544// SAFETY: `bytes::BufMut` is an `unsafe trait`, so `unsafe impl` is required by the language
545// regardless of body. Every method forwards verbatim to `self.contents: BytesMut`, whose own
546// `unsafe impl BufMut` upholds all trait invariants; we add no behavior, so those guarantees
547// carry through unchanged.
548unsafe impl BufMut for PacketMut {
549 fn remaining_mut(&self) -> usize {
550 self.contents.remaining_mut()
551 }
552
553 unsafe fn advance_mut(&mut self, cnt: usize) {
554 // SAFETY: the caller guarantees `cnt` bytes returned by `chunk_mut` were initialized; we forward
555 // that identical precondition to `BytesMut::advance_mut`, which requires exactly the same thing.
556 unsafe {
557 self.contents.advance_mut(cnt);
558 }
559 }
560
561 fn chunk_mut(&mut self) -> &mut UninitSlice {
562 self.contents.chunk_mut()
563 }
564}
565
566impl crypto_box::aead::Buffer for PacketMut {
567 fn extend_from_slice(&mut self, other: &[u8]) -> crypto_box::aead::Result<()> {
568 self.contents.extend_from_slice(other);
569 Ok(())
570 }
571
572 fn truncate(&mut self, len: usize) {
573 self.truncate(len);
574 }
575}
576
577impl From<&[u8]> for PacketMut {
578 fn from(value: &[u8]) -> Self {
579 Self {
580 contents: BytesMut::from(value),
581 }
582 }
583}
584
585impl<const N: usize> From<&[u8; N]> for PacketMut {
586 fn from(value: &[u8; N]) -> Self {
587 Self {
588 contents: BytesMut::from(value.as_ref()),
589 }
590 }
591}
592
593impl From<Vec<u8>> for PacketMut {
594 fn from(value: Vec<u8>) -> Self {
595 Self {
596 contents: BytesMut::from(value.as_slice()),
597 }
598 }
599}
600
601impl From<BytesMut> for PacketMut {
602 fn from(value: BytesMut) -> Self {
603 Self { contents: value }
604 }
605}
606
607impl<T> Index<T> for PacketMut
608where
609 // This instance is provided by implicit deref to [u8] on BytesMut
610 [u8]: Index<T>,
611{
612 type Output = <[u8] as Index<T>>::Output;
613
614 #[inline]
615 fn index(&self, index: T) -> &Self::Output {
616 self.contents.index(index)
617 }
618}
619
620impl<T> IndexMut<T> for PacketMut
621where
622 [u8]: IndexMut<T>,
623{
624 #[inline]
625 fn index_mut(&mut self, index: T) -> &mut Self::Output {
626 self.contents.index_mut(index)
627 }
628}
629
630impl LowerHex for PacketMut {
631 #[inline]
632 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
633 hex_fmt(self.iter(), Case::Lower, f)
634 }
635}
636
637impl UpperHex for PacketMut {
638 #[inline]
639 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
640 hex_fmt(self.iter(), Case::Upper, f)
641 }
642}
643
644#[cfg(test)]
645mod tests {
646 use alloc::string::String;
647 use core::fmt::Write;
648
649 use super::*;
650
651 /// Simple byte sequence for testing hexdumps, etc.
652 const BYTE_SEQUENCE_1: &[u8] = &[
653 0x00u8, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
654 0x0F, 0x10, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
655 ];
656
657 /// Resembles a 5-byte DERP KeepAlive frame; the 4-byte length field doesn't include the type/
658 /// length fields themselves, so is zero.
659 const BYTE_SEQUENCE_2: &[u8] = &[0x06, 0x00, 0x00, 0x00, 0x00];
660
661 #[test]
662 fn test_packet_mut_hexdump() {
663 let pkt = PacketMut::from(BYTE_SEQUENCE_1);
664
665 let mut buf = String::new();
666 write!(
667 buf,
668 "{}",
669 pkt.iter()
670 .hexdump(Case::Lower)
671 .flatten()
672 .collect::<String>()
673 )
674 .unwrap();
675 assert_eq!(
676 buf,
677 "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ................\n10 aa bb cc dd ee ff .......\n"
678 );
679
680 buf.clear();
681 write!(
682 buf,
683 "{}",
684 pkt.iter()
685 .hexdump(Case::Upper)
686 .flatten()
687 .collect::<String>()
688 )
689 .unwrap();
690 assert_eq!(
691 buf,
692 "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ................\n10 AA BB CC DD EE FF .......\n"
693 );
694 }
695
696 #[test]
697 fn test_packet_mut_iter() {
698 let pkt = PacketMut::from(BYTE_SEQUENCE_1);
699 for (idx, byte) in pkt.iter().enumerate() {
700 assert_eq!(
701 *byte, BYTE_SEQUENCE_1[idx],
702 "packet and original bytes should have identical values in same order"
703 );
704 }
705 }
706
707 #[test]
708 fn test_packet_mut_iter_mut() {
709 let mut pkt1 = PacketMut::from(BYTE_SEQUENCE_1);
710 let pkt2 = PacketMut::from(BYTE_SEQUENCE_1);
711 for byte in pkt1.iter_mut() {
712 *byte = byte.wrapping_sub(0xFF);
713 }
714
715 for (idx, byte) in pkt1.iter().enumerate() {
716 assert_eq!(
717 *byte,
718 BYTE_SEQUENCE_1[idx].wrapping_sub(0xFF),
719 "pkt1 and original bytes should have values offset by 0xFF"
720 );
721 assert_eq!(
722 pkt2[idx], BYTE_SEQUENCE_1[idx],
723 "pkt2 and original bytes should have identical values in same order"
724 );
725 assert_eq!(
726 pkt1[idx],
727 pkt2[idx].wrapping_sub(0xFF),
728 "pkt1 and pkt2 should have values offset by 0xFF"
729 );
730 }
731 }
732
733 #[test]
734 fn test_packet_mut_prepend() {
735 let mut pkt = PacketMut::from(BYTE_SEQUENCE_1);
736 pkt.grow_front(5);
737 assert_eq!(pkt.len(), BYTE_SEQUENCE_1.len() + 5);
738 assert_eq!(pkt[..5], [0; 5]);
739 assert_eq!(&pkt[5..], BYTE_SEQUENCE_1);
740
741 let mut pkt = PacketMut::from(BYTE_SEQUENCE_1);
742 pkt.extend_front_from_slice(BYTE_SEQUENCE_2);
743 assert_eq!(pkt.len(), BYTE_SEQUENCE_1.len() + BYTE_SEQUENCE_2.len());
744 assert_eq!(&pkt[..BYTE_SEQUENCE_2.len()], BYTE_SEQUENCE_2);
745 assert_eq!(&pkt[BYTE_SEQUENCE_2.len()..], BYTE_SEQUENCE_1);
746 }
747}