1 use crate::err::ValueTooBigError; 2 3 /// 3 bit unsigned integer containing the "Priority Code Point" 4 /// (present in the [`crate::SingleVlanHeader`]). 5 /// 6 /// Refers to the IEEE 802.1p class of service and maps to the 7 /// frame priority level. 8 #[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] 9 pub struct VlanPcp(u8); 10 11 impl VlanPcp { 12 /// VlanPcp with value 0. 13 pub const ZERO: VlanPcp = VlanPcp(0); 14 15 /// Maximum value of an vlan header PCP. 16 pub const MAX_U8: u8 = 0b0000_0111; 17 18 /// Tries to create an [`VlanPcp`] and checks that the passed value 19 /// is smaller or equal than [`VlanPcp::MAX_U8`] (3 bit unsigned integer). 20 /// 21 /// In case the passed value is bigger then what can be represented in an 3 bit 22 /// integer an error is returned. Otherwise an `Ok` containing the [`VlanPcp`]. 23 /// 24 /// ``` 25 /// use etherparse::VlanPcp; 26 /// 27 /// let pcp = VlanPcp::try_new(2).unwrap(); 28 /// assert_eq!(pcp.value(), 2); 29 /// 30 /// // if a number that can not be represented in an 3 bit integer 31 /// // gets passed in an error is returned 32 /// use etherparse::err::{ValueTooBigError, ValueType}; 33 /// assert_eq!( 34 /// VlanPcp::try_new(VlanPcp::MAX_U8 + 1), 35 /// Err(ValueTooBigError{ 36 /// actual: VlanPcp::MAX_U8 + 1, 37 /// max_allowed: VlanPcp::MAX_U8, 38 /// value_type: ValueType::VlanPcp, 39 /// }) 40 /// ); 41 /// ``` 42 #[inline] try_new(value: u8) -> Result<VlanPcp, ValueTooBigError<u8>>43 pub const fn try_new(value: u8) -> Result<VlanPcp, ValueTooBigError<u8>> { 44 use crate::err::ValueType; 45 if value <= VlanPcp::MAX_U8 { 46 Ok(VlanPcp(value)) 47 } else { 48 Err(ValueTooBigError { 49 actual: value, 50 max_allowed: VlanPcp::MAX_U8, 51 value_type: ValueType::VlanPcp, 52 }) 53 } 54 } 55 56 /// Creates an [`VlanPcp`] without checking that the value 57 /// is smaller or equal than [`VlanPcp::MAX_U8`] (3 bit unsigned integer). 58 /// The caller must guarantee that `value <= VlanPcp::MAX_U8`. 59 /// 60 /// # Safety 61 /// 62 /// `value` must be smaller or equal than [`VlanPcp::MAX_U8`] 63 /// otherwise the behavior of functions or data structures relying 64 /// on this pre-requirement is undefined. 65 #[inline] new_unchecked(value: u8) -> VlanPcp66 pub const unsafe fn new_unchecked(value: u8) -> VlanPcp { 67 debug_assert!(value <= VlanPcp::MAX_U8); 68 VlanPcp(value) 69 } 70 71 /// Returns the underlying unsigned 3 bit value as an `u8` value. 72 #[inline] value(self) -> u873 pub const fn value(self) -> u8 { 74 self.0 75 } 76 } 77 78 impl core::fmt::Display for VlanPcp { 79 #[inline] fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result80 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 81 self.0.fmt(f) 82 } 83 } 84 85 impl From<VlanPcp> for u8 { 86 #[inline] from(value: VlanPcp) -> Self87 fn from(value: VlanPcp) -> Self { 88 value.0 89 } 90 } 91 92 impl TryFrom<u8> for VlanPcp { 93 type Error = ValueTooBigError<u8>; 94 95 #[inline] try_from(value: u8) -> Result<Self, Self::Error>96 fn try_from(value: u8) -> Result<Self, Self::Error> { 97 use crate::err::ValueType; 98 if value <= VlanPcp::MAX_U8 { 99 Ok(VlanPcp(value)) 100 } else { 101 Err(Self::Error { 102 actual: value, 103 max_allowed: VlanPcp::MAX_U8, 104 value_type: ValueType::VlanPcp, 105 }) 106 } 107 } 108 } 109 110 #[cfg(test)] 111 mod test { 112 use super::*; 113 use core::hash::{Hash, Hasher}; 114 use proptest::prelude::*; 115 use std::format; 116 117 #[test] derived_traits()118 fn derived_traits() { 119 // copy & clone 120 { 121 let a = VlanPcp(2); 122 let b = a; 123 assert_eq!(a, b); 124 assert_eq!(a.clone(), a); 125 } 126 127 // default 128 { 129 let actual: VlanPcp = Default::default(); 130 assert_eq!(actual.value(), 0); 131 } 132 133 // debug 134 { 135 let a = VlanPcp(2); 136 assert_eq!(format!("{:?}", a), format!("VlanPcp(2)")); 137 } 138 139 // ord & partial ord 140 { 141 use core::cmp::Ordering; 142 let a = VlanPcp(2); 143 let b = a; 144 assert_eq!(a.cmp(&b), Ordering::Equal); 145 assert_eq!(a.partial_cmp(&b), Some(Ordering::Equal)); 146 } 147 148 // hash 149 { 150 use std::collections::hash_map::DefaultHasher; 151 let a = { 152 let mut hasher = DefaultHasher::new(); 153 VlanPcp(2).hash(&mut hasher); 154 hasher.finish() 155 }; 156 let b = { 157 let mut hasher = DefaultHasher::new(); 158 VlanPcp(2).hash(&mut hasher); 159 hasher.finish() 160 }; 161 assert_eq!(a, b); 162 } 163 } 164 165 proptest! { 166 #[test] 167 fn try_new( 168 valid_value in 0..=0b0000_0111u8, 169 invalid_value in 0b0000_1000u8..=u8::MAX 170 ) { 171 use crate::err::{ValueType, ValueTooBigError}; 172 assert_eq!( 173 valid_value, 174 VlanPcp::try_new(valid_value).unwrap().value() 175 ); 176 assert_eq!( 177 VlanPcp::try_new(invalid_value).unwrap_err(), 178 ValueTooBigError{ 179 actual: invalid_value, 180 max_allowed: 0b0000_0111, 181 value_type: ValueType::VlanPcp 182 } 183 ); 184 } 185 } 186 187 proptest! { 188 #[test] 189 fn try_from( 190 valid_value in 0..=0b0000_0111u8, 191 invalid_value in 0b0000_1000u8..=u8::MAX 192 ) { 193 use crate::err::{ValueType, ValueTooBigError}; 194 // try_into 195 { 196 let actual: VlanPcp = valid_value.try_into().unwrap(); 197 assert_eq!(actual.value(), valid_value); 198 199 let err: Result<VlanPcp, ValueTooBigError<u8>> = invalid_value.try_into(); 200 assert_eq!( 201 err.unwrap_err(), 202 ValueTooBigError{ 203 actual: invalid_value, 204 max_allowed: 0b0000_0111, 205 value_type: ValueType::VlanPcp 206 } 207 ); 208 } 209 // try_from 210 { 211 assert_eq!( 212 VlanPcp::try_from(valid_value).unwrap().value(), 213 valid_value 214 ); 215 216 assert_eq!( 217 VlanPcp::try_from(invalid_value).unwrap_err(), 218 ValueTooBigError{ 219 actual: invalid_value, 220 max_allowed: 0b0000_0111, 221 value_type: ValueType::VlanPcp 222 } 223 ); 224 } 225 } 226 } 227 228 proptest! { 229 #[test] 230 fn new_unchecked(valid_value in 0..=0b0000_0111u8) { 231 assert_eq!( 232 valid_value, 233 unsafe { 234 VlanPcp::new_unchecked(valid_value).value() 235 } 236 ); 237 } 238 } 239 240 proptest! { 241 #[test] 242 fn fmt(valid_value in 0..=0b0000_0111u8) { 243 assert_eq!(format!("{}", VlanPcp(valid_value)), format!("{}", valid_value)); 244 } 245 } 246 247 proptest! { 248 #[test] 249 fn from(valid_value in 0..=0b0000_0111u8,) { 250 let pcp = VlanPcp::try_new(valid_value).unwrap(); 251 let actual: u8 = pcp.into(); 252 assert_eq!(actual, valid_value); 253 } 254 } 255 } 256