net_wire/icmpv4/
builder.rs1use core::fmt;
4
5use super::message::{HEADER_LENGTH, Icmpv4MessageMut};
6use super::types::Icmpv4Type;
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub enum Icmpv4MessageBuildError {
11 MissingType,
13 MissingCode,
15 MessageLengthTooLarge,
17 BufferTooShort {
19 required: usize,
21 available: usize,
23 },
24}
25
26impl fmt::Display for Icmpv4MessageBuildError {
27 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
28 match self {
29 Self::MissingType => formatter.write_str("missing ICMPv4 type"),
30 Self::MissingCode => formatter.write_str("missing ICMPv4 code"),
31 Self::MessageLengthTooLarge => {
32 formatter.write_str("ICMPv4 message length exceeds the platform limit")
33 }
34 Self::BufferTooShort {
35 required,
36 available,
37 } => write!(
38 formatter,
39 "ICMPv4 buffer is too short: need {required} bytes, have {available}"
40 ),
41 }
42 }
43}
44
45pub struct Icmpv4MessageBuilder<'a> {
47 buffer: &'a mut [u8],
48 body_length: usize,
49 message_type: Option<Icmpv4Type>,
50 code: Option<u8>,
51}
52
53impl<'a> Icmpv4MessageBuilder<'a> {
54 pub fn new(buffer: &'a mut [u8], body_length: usize) -> Self {
56 Self {
57 buffer,
58 body_length,
59 message_type: None,
60 code: None,
61 }
62 }
63 pub fn message_type(mut self, value: Icmpv4Type) -> Self {
65 self.message_type = Some(value);
66 self
67 }
68 pub fn code(mut self, value: u8) -> Self {
70 self.code = Some(value);
71 self
72 }
73 pub fn build(self) -> Result<Icmpv4MessageMut<'a>, Icmpv4MessageBuildError> {
78 let message_type = self
79 .message_type
80 .ok_or(Icmpv4MessageBuildError::MissingType)?;
81 let code = self.code.ok_or(Icmpv4MessageBuildError::MissingCode)?;
82 let length = HEADER_LENGTH
83 .checked_add(self.body_length)
84 .ok_or(Icmpv4MessageBuildError::MessageLengthTooLarge)?;
85 if self.buffer.len() < length {
86 return Err(Icmpv4MessageBuildError::BufferTooShort {
87 required: length,
88 available: self.buffer.len(),
89 });
90 }
91 let bytes = &mut self.buffer[..length];
92 bytes[0] = message_type.raw();
93 bytes[1] = code;
94 bytes[2] = 0;
95 bytes[3] = 0;
96 let mut result = Icmpv4MessageMut::from_validated(bytes);
97 result.update_checksum();
98 Ok(result)
99 }
100}