domain/base/opt/
padding.rs1use super::super::iana::OptionCode;
12use super::super::message_builder::OptBuilder;
13use super::super::wire::{Compose, Composer, ParseError};
14use super::{ComposeOptData, LongOptData, OptData, ParseOptData};
15use core::{borrow, fmt, str};
16use octseq::builder::OctetsBuilder;
17use octseq::octets::{Octets, OctetsFrom};
18use octseq::parse::Parser;
19
20#[derive(Clone, Copy)]
33pub struct Padding<Octs: ?Sized> {
34 octets: Octs,
36}
37
38impl Padding<()> {
39 pub const CODE: OptionCode = OptionCode::PADDING;
41}
42
43impl<Octs> Padding<Octs> {
44 pub fn from_octets(octets: Octs) -> Result<Self, LongOptData>
48 where
49 Octs: AsRef<[u8]>,
50 {
51 LongOptData::check_len(octets.as_ref().len())?;
52 Ok(unsafe { Self::from_octets_unchecked(octets) })
53 }
54
55 pub unsafe fn from_octets_unchecked(octets: Octs) -> Self {
62 Self { octets }
63 }
64
65 pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
67 parser: &mut Parser<'a, Src>,
68 ) -> Result<Self, ParseError> {
69 let len = parser.remaining();
70 LongOptData::check_len(len)?;
71 Ok(unsafe { Self::from_octets_unchecked(parser.parse_octets(len)?) })
72 }
73}
74
75impl<Octs: ?Sized> Padding<Octs> {
76 pub fn as_octets(&self) -> &Octs {
78 &self.octets
79 }
80
81 pub fn into_octets(self) -> Octs
83 where
84 Octs: Sized,
85 {
86 self.octets
87 }
88
89 pub fn as_slice(&self) -> &[u8]
91 where
92 Octs: AsRef<[u8]>,
93 {
94 self.octets.as_ref()
95 }
96}
97
98impl<Octs, SrcOcts> OctetsFrom<Padding<SrcOcts>> for Padding<Octs>
101where
102 Octs: OctetsFrom<SrcOcts>,
103{
104 type Error = Octs::Error;
105
106 fn try_octets_from(src: Padding<SrcOcts>) -> Result<Self, Self::Error> {
107 Octs::try_octets_from(src.octets)
108 .map(|octets| unsafe { Self::from_octets_unchecked(octets) })
109 }
110}
111
112impl<Octs: AsRef<[u8]> + ?Sized> AsRef<[u8]> for Padding<Octs> {
115 fn as_ref(&self) -> &[u8] {
116 self.as_slice()
117 }
118}
119
120impl<Octs: AsRef<[u8]> + ?Sized> borrow::Borrow<[u8]> for Padding<Octs> {
121 fn borrow(&self) -> &[u8] {
122 self.as_slice()
123 }
124}
125
126impl<Octs> OptData for Padding<Octs> {
129 fn code(&self) -> OptionCode {
130 OptionCode::PADDING
131 }
132}
133
134impl<'a, Octs: Octets> ParseOptData<'a, Octs> for Padding<Octs::Range<'a>> {
135 fn parse_option(
136 code: OptionCode,
137 parser: &mut Parser<'a, Octs>,
138 ) -> Result<Option<Self>, ParseError> {
139 if code == OptionCode::PADDING {
140 Self::parse(parser).map(Some)
141 } else {
142 Ok(None)
143 }
144 }
145}
146
147impl<Octs: AsRef<[u8]>> ComposeOptData for Padding<Octs> {
148 fn compose_len(&self) -> u16 {
149 self.octets
150 .as_ref()
151 .len()
152 .try_into()
153 .expect("long option data")
154 }
155
156 fn compose_option<Target: OctetsBuilder + ?Sized>(
157 &self,
158 target: &mut Target,
159 ) -> Result<(), Target::AppendError> {
160 target.append_slice(self.octets.as_ref())
161 }
162}
163
164impl<Octs: AsRef<[u8]> + ?Sized> fmt::Display for Padding<Octs> {
167 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 for v in self.octets.as_ref() {
169 write!(f, "{:X} ", *v)?;
170 }
171 if let Ok(s) = str::from_utf8(self.octets.as_ref()) {
172 write!(f, "({})", s)?;
173 }
174 Ok(())
175 }
176}
177
178impl<Octs: AsRef<[u8]> + ?Sized> fmt::Debug for Padding<Octs> {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 write!(f, "Padding({})", self)
181 }
182}
183
184impl<Target: Composer> OptBuilder<'_, Target> {
187 pub fn padding(&mut self, len: u16) -> Result<(), Target::AppendError> {
188 self.push_raw_option(OptionCode::PADDING, len, |target| {
189 for _ in 0..len {
190 0u8.compose(target)?
191 }
192 Ok(())
193 })
194 }
195
196 #[cfg(feature = "rand")]
197 pub fn random_padding(
198 &mut self,
199 len: u16,
200 ) -> Result<(), Target::AppendError> {
201 self.push_raw_option(OptionCode::PADDING, len, |target| {
202 for _ in 0..len {
203 rand::random::<u8>().compose(target)?
204 }
205 Ok(())
206 })
207 }
208}
209
210#[cfg(feature = "serde")]
213impl<Octs: AsRef<[u8]>> serde::Serialize for Padding<Octs> {
214 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
215 where
216 S: serde::Serializer,
217 {
218 use octseq::serde::SerializeOctets;
219 self.octets.as_ref().serialize_octets(serializer)
220 }
221}