1 use super::{chunk_header::*, chunk_type::*, *}; 2 use crate::error_cause::*; 3 4 use bytes::{Bytes, BytesMut}; 5 use std::fmt; 6 7 ///Operation Error (ERROR) (9) 8 /// 9 ///An endpoint sends this chunk to its peer endpoint to notify it of 10 ///certain error conditions. It contains one or more error causes. An 11 ///Operation Error is not considered fatal in and of itself, but may be 12 ///used with an ERROR chunk to report a fatal condition. It has the 13 ///following parameters: 14 /// 0 1 2 3 15 /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 16 ///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 17 ///| Type = 9 | Chunk Flags | Length | 18 ///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 19 ///| | 20 ///| one or more Error Causes | 21 ///| | 22 ///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 23 ///Chunk Flags: 8 bits 24 /// Set to 0 on transmit and ignored on receipt. 25 ///Length: 16 bits (unsigned integer) 26 /// Set to the size of the chunk in bytes, including the chunk header 27 /// and all the Error Cause fields present. 28 #[derive(Default, Debug, Clone)] 29 pub(crate) struct ChunkError { 30 pub(crate) error_causes: Vec<ErrorCause>, 31 } 32 33 /// makes ChunkError printable 34 impl fmt::Display for ChunkError { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 36 let mut res = vec![self.header().to_string()]; 37 38 for cause in &self.error_causes { 39 res.push(format!(" - {cause}")); 40 } 41 42 write!(f, "{}", res.join("\n")) 43 } 44 } 45 46 impl Chunk for ChunkError { header(&self) -> ChunkHeader47 fn header(&self) -> ChunkHeader { 48 ChunkHeader { 49 typ: CT_ERROR, 50 flags: 0, 51 value_length: self.value_length() as u16, 52 } 53 } 54 unmarshal(raw: &Bytes) -> Result<Self>55 fn unmarshal(raw: &Bytes) -> Result<Self> { 56 let header = ChunkHeader::unmarshal(raw)?; 57 58 if header.typ != CT_ERROR { 59 return Err(Error::ErrChunkTypeNotCtError); 60 } 61 62 let mut error_causes = vec![]; 63 let mut offset = CHUNK_HEADER_SIZE; 64 while offset + 4 <= raw.len() { 65 let e = ErrorCause::unmarshal( 66 &raw.slice(offset..CHUNK_HEADER_SIZE + header.value_length()), 67 )?; 68 offset += e.length(); 69 error_causes.push(e); 70 } 71 72 Ok(ChunkError { error_causes }) 73 } 74 marshal_to(&self, buf: &mut BytesMut) -> Result<usize>75 fn marshal_to(&self, buf: &mut BytesMut) -> Result<usize> { 76 self.header().marshal_to(buf)?; 77 for ec in &self.error_causes { 78 buf.extend(ec.marshal()); 79 } 80 Ok(buf.len()) 81 } 82 check(&self) -> Result<()>83 fn check(&self) -> Result<()> { 84 Ok(()) 85 } 86 value_length(&self) -> usize87 fn value_length(&self) -> usize { 88 self.error_causes 89 .iter() 90 .fold(0, |length, ec| length + ec.length()) 91 } 92 as_any(&self) -> &(dyn Any + Send + Sync)93 fn as_any(&self) -> &(dyn Any + Send + Sync) { 94 self 95 } 96 } 97