net_wire/icmpv6/
builder.rs1use core::fmt;
4
5use super::message::{HEADER_LENGTH, Icmpv6MessageMut};
6use super::types::Icmpv6Type;
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub enum Icmpv6MessageBuildError {
11 MissingType,
13 MissingCode,
15 MessageLengthTooLarge,
17 BufferTooShort {
19 required: usize,
21 available: usize,
23 },
24}
25
26impl fmt::Display for Icmpv6MessageBuildError {
27 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
28 match self {
29 Self::MissingType => formatter.write_str("missing ICMPv6 type"),
30 Self::MissingCode => formatter.write_str("missing ICMPv6 code"),
31 Self::MessageLengthTooLarge => {
32 formatter.write_str("ICMPv6 message length exceeds the platform limit")
33 }
34 Self::BufferTooShort {
35 required,
36 available,
37 } => write!(
38 formatter,
39 "ICMPv6 buffer is too short: need {required} bytes, have {available}"
40 ),
41 }
42 }
43}
44
45pub struct Icmpv6MessageBuilder<'a> {
47 buffer: &'a mut [u8],
48 body_length: usize,
49 message_type: Option<Icmpv6Type>,
50 code: Option<u8>,
51 checksum: u16,
52}
53
54impl<'a> Icmpv6MessageBuilder<'a> {
55 #[inline]
57 pub fn new(buffer: &'a mut [u8], body_length: usize) -> Self {
58 Self {
59 buffer,
60 body_length,
61 message_type: None,
62 code: None,
63 checksum: 0,
64 }
65 }
66
67 #[inline]
69 pub fn message_type(mut self, value: Icmpv6Type) -> Self {
70 self.message_type = Some(value);
71 self
72 }
73
74 #[inline]
76 pub fn code(mut self, value: u8) -> Self {
77 self.code = Some(value);
78 self
79 }
80
81 #[inline]
83 pub fn checksum(mut self, value: u16) -> Self {
84 self.checksum = value;
85 self
86 }
87
88 #[inline]
93 pub fn build(self) -> Result<Icmpv6MessageMut<'a>, Icmpv6MessageBuildError> {
94 let message_type = self
95 .message_type
96 .ok_or(Icmpv6MessageBuildError::MissingType)?;
97 let code = self.code.ok_or(Icmpv6MessageBuildError::MissingCode)?;
98 let length = HEADER_LENGTH
99 .checked_add(self.body_length)
100 .ok_or(Icmpv6MessageBuildError::MessageLengthTooLarge)?;
101 if self.buffer.len() < length {
102 return Err(Icmpv6MessageBuildError::BufferTooShort {
103 required: length,
104 available: self.buffer.len(),
105 });
106 }
107
108 let bytes = &mut self.buffer[..length];
109 bytes[0] = message_type.raw();
110 bytes[1] = code;
111 bytes[2..4].copy_from_slice(&self.checksum.to_be_bytes());
112 Ok(Icmpv6MessageMut::from_validated(bytes))
113 }
114}