| use crate::*; | |
| /// Laxly parsed payload together with an identifier the type of content & the | |
| /// information if the payload is incomplete. | |
| #[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] | |
| pub enum LaxPayloadSlice<'a> { | |
| /// Payload with it's type identified by an ether type number | |
| /// (e.g. after an ethernet II or vlan header). | |
| Ether(EtherPayloadSlice<'a>), | |
| /// Payload with is's type identified by an ip number (e.g. | |
| /// after an IP header or after an) | |
| Ip(LaxIpPayloadSlice<'a>), | |
| /// UDP payload. | |
| Udp { payload: &'a [u8], incomplete: bool }, | |
| /// TCP payload. | |
| Tcp { | |
| payload: &'a [u8], | |
| /// True if the payload has been cut off. | |
| incomplete: bool, | |
| }, | |
| /// Payload part of an ICMP V4 message. Check [`crate::Icmpv4Type`] | |
| /// for a description what will be part of the payload. | |
| Icmpv4 { | |
| payload: &'a [u8], | |
| /// True if the payload has been cut off. | |
| incomplete: bool, | |
| }, | |
| /// Payload part of an ICMP V4 message. Check [`crate::Icmpv6Type`] | |
| /// for a description what will be part of the payload. | |
| Icmpv6 { | |
| payload: &'a [u8], | |
| /// True if the payload has been cut off. | |
| incomplete: bool, | |
| }, | |
| } | |
| impl<'a> LaxPayloadSlice<'a> { | |
| pub fn slice(&self) -> &'a [u8] { | |
| match self { | |
| LaxPayloadSlice::Ether(e) => e.payload, | |
| LaxPayloadSlice::Ip(i) => i.payload, | |
| LaxPayloadSlice::Udp { | |
| payload, | |
| incomplete: _, | |
| } => payload, | |
| LaxPayloadSlice::Tcp { | |
| payload, | |
| incomplete: _, | |
| } => payload, | |
| LaxPayloadSlice::Icmpv4 { | |
| payload, | |
| incomplete: _, | |
| } => payload, | |
| LaxPayloadSlice::Icmpv6 { | |
| payload, | |
| incomplete: _, | |
| } => payload, | |
| } | |
| } | |
| } | |
| #[cfg(test)] | |
| mod test { | |
| use super::*; | |
| use alloc::format; | |
| #[test] | |
| fn debug() { | |
| assert_eq!( | |
| format!("Udp {{ payload: {:?}, incomplete: {} }}", &[0u8; 0], false), | |
| format!( | |
| "{:?}", | |
| LaxPayloadSlice::Udp { | |
| payload: &[], | |
| incomplete: false | |
| } | |
| ) | |
| ); | |
| } | |
| #[test] | |
| fn clone_eq_hash_ord() { | |
| let s = LaxPayloadSlice::Udp { | |
| payload: &[], | |
| incomplete: false, | |
| }; | |
| assert_eq!(s.clone(), s); | |
| use std::collections::hash_map::DefaultHasher; | |
| use std::hash::{Hash, Hasher}; | |
| let a_hash = { | |
| let mut hasher = DefaultHasher::new(); | |
| s.hash(&mut hasher); | |
| hasher.finish() | |
| }; | |
| let b_hash = { | |
| let mut hasher = DefaultHasher::new(); | |
| s.clone().hash(&mut hasher); | |
| hasher.finish() | |
| }; | |
| assert_eq!(a_hash, b_hash); | |
| use std::cmp::Ordering; | |
| assert_eq!(s.clone().cmp(&s), Ordering::Equal); | |
| assert_eq!(s.clone().partial_cmp(&s), Some(Ordering::Equal)); | |
| } | |
| #[test] | |
| fn slice() { | |
| let payload = [1, 2, 3, 4]; | |
| use LaxPayloadSlice::*; | |
| assert_eq!( | |
| Ether(EtherPayloadSlice { | |
| ether_type: EtherType::IPV4, | |
| payload: &payload | |
| }) | |
| .slice(), | |
| &payload | |
| ); | |
| assert_eq!( | |
| Ip(LaxIpPayloadSlice { | |
| ip_number: IpNumber::IPV4, | |
| fragmented: false, | |
| len_source: LenSource::Slice, | |
| payload: &payload, | |
| incomplete: true, | |
| }) | |
| .slice(), | |
| &payload | |
| ); | |
| assert_eq!( | |
| Udp { | |
| payload: &payload, | |
| incomplete: false | |
| } | |
| .slice(), | |
| &payload | |
| ); | |
| assert_eq!( | |
| Tcp { | |
| payload: &payload, | |
| incomplete: false | |
| } | |
| .slice(), | |
| &payload | |
| ); | |
| assert_eq!( | |
| Icmpv4 { | |
| payload: &payload, | |
| incomplete: false | |
| } | |
| .slice(), | |
| &payload | |
| ); | |
| assert_eq!( | |
| Icmpv6 { | |
| payload: &payload, | |
| incomplete: false | |
| } | |
| .slice(), | |
| &payload | |
| ); | |
| } | |
| } |