1 use crate::err::Layer; 2 3 /// Error when not enough space is available in a slice 4 /// to write a packet or header to it. 5 #[derive(Clone, Debug, Eq, PartialEq, Hash)] 6 pub struct SliceWriteSpaceError { 7 /// Expected minimum length conflicting with the 8 /// `actual_len` value. 9 pub required_len: usize, 10 11 /// Length limiting or exceeding the required length. 12 pub len: usize, 13 14 /// Layer in which could not be written to the slice. 15 pub layer: Layer, 16 17 /// Offset from the start of the parsed data to the layer where the 18 /// length error occurred. 19 pub layer_start_offset: usize, 20 } 21 22 impl core::fmt::Display for SliceWriteSpaceError { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result23 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 24 if self.layer_start_offset > 0 { 25 write!( 26 f, 27 "Not enough space to write {} to slice. Needed {} byte(s), but only {} byte(s) were available (start offset of {} write was {} byte(s)).", 28 self.layer, 29 self.required_len, 30 self.len, 31 self.layer, 32 self.layer_start_offset 33 ) 34 } else { 35 write!( 36 f, 37 "Not enough space to write {} to slice. Needed {} byte(s), but only {} byte(s) were available.", 38 self.layer, 39 self.required_len, 40 self.len, 41 ) 42 } 43 } 44 } 45 46 #[cfg(feature = "std")] 47 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 48 impl std::error::Error for SliceWriteSpaceError { source(&self) -> Option<&(dyn std::error::Error + 'static)>49 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 50 None 51 } 52 } 53 54 #[cfg(test)] 55 mod test { 56 use super::*; 57 use alloc::format; 58 use std::{ 59 collections::hash_map::DefaultHasher, 60 error::Error, 61 hash::{Hash, Hasher}, 62 }; 63 64 #[test] debug()65 fn debug() { 66 assert_eq!( 67 format!( 68 "{:?}", 69 SliceWriteSpaceError { 70 required_len: 2, 71 layer: Layer::Ipv4Header, 72 len: 1, 73 layer_start_offset: 0 74 } 75 ), 76 format!( 77 "SliceWriteSpaceError {{ required_len: {:?}, len: {:?}, layer: {:?}, layer_start_offset: {:?} }}", 78 2, 1, Layer::Ipv4Header, 0 79 ), 80 ); 81 } 82 83 #[test] clone_eq_hash()84 fn clone_eq_hash() { 85 let err = SliceWriteSpaceError { 86 required_len: 2, 87 layer: Layer::Icmpv4, 88 len: 1, 89 layer_start_offset: 20, 90 }; 91 assert_eq!(err, err.clone()); 92 let hash_a = { 93 let mut hasher = DefaultHasher::new(); 94 err.hash(&mut hasher); 95 hasher.finish() 96 }; 97 let hash_b = { 98 let mut hasher = DefaultHasher::new(); 99 err.clone().hash(&mut hasher); 100 hasher.finish() 101 }; 102 assert_eq!(hash_a, hash_b); 103 } 104 105 #[test] fmt()106 fn fmt() { 107 // layer_start_offset set 108 assert_eq!( 109 "Not enough space to write IPv4 header to slice. Needed 2 byte(s), but only 1 byte(s) were available (start offset of IPv4 header write was 4 byte(s)).", 110 format!( 111 "{}", 112 SliceWriteSpaceError{ 113 required_len: 2, 114 len: 1, 115 layer: Layer::Ipv4Header, 116 layer_start_offset: 4 117 } 118 ) 119 ); 120 121 // layer_start_offset zero 122 assert_eq!( 123 "Not enough space to write IPv4 header to slice. Needed 4 byte(s), but only 3 byte(s) were available.", 124 format!( 125 "{}", 126 SliceWriteSpaceError{ 127 required_len: 4, 128 len: 3, 129 layer: Layer::Ipv4Header, 130 layer_start_offset: 0 131 } 132 ) 133 ); 134 } 135 136 #[cfg(feature = "std")] 137 #[test] source()138 fn source() { 139 assert!(SliceWriteSpaceError { 140 required_len: 0, 141 len: 0, 142 layer: Layer::Ipv4Header, 143 layer_start_offset: 0 144 } 145 .source() 146 .is_none()); 147 } 148 } 149