domain/base/opt/
padding.rs1use core::{borrow, fmt, str};
12use super::super::iana::OptionCode;
13use super::super::message_builder::OptBuilder;
14use super::super::wire::{Compose, Composer, ParseError};
15use super::{LongOptData, OptData, ComposeOptData, ParseOptData};
16use octseq::builder::OctetsBuilder;
17use octseq::octets::{Octets, OctetsFrom};
18use octseq::parse::Parser;
19
20
21#[derive(Clone, Copy)]
34pub struct Padding<Octs: ?Sized> {
35 octets: Octs,
37}
38
39impl Padding<()> {
40 pub const CODE: OptionCode = OptionCode::PADDING;
42}
43
44impl<Octs> Padding<Octs> {
45 pub fn from_octets(octets: Octs) -> Result<Self, LongOptData>
49 where Octs: AsRef<[u8]> {
50 LongOptData::check_len(octets.as_ref().len())?;
51 Ok(unsafe { Self::from_octets_unchecked(octets) })
52 }
53
54 pub unsafe fn from_octets_unchecked(octets: Octs) -> Self {
61 Self { octets }
62 }
63
64 pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
66 parser: &mut Parser<'a, Src>
67 ) -> Result<Self, ParseError> {
68 let len = parser.remaining();
69 LongOptData::check_len(len)?;
70 Ok(unsafe { Self::from_octets_unchecked(
71 parser.parse_octets(len)?
72 )})
73 }
74}
75
76impl<Octs: ?Sized> Padding<Octs> {
77 pub fn as_octets(&self) -> &Octs {
79 &self.octets
80 }
81
82 pub fn into_octets(self) -> Octs
84 where
85 Octs: Sized,
86 {
87 self.octets
88 }
89
90 pub fn as_slice(&self) -> &[u8]
92 where
93 Octs: AsRef<[u8]>,
94 {
95 self.octets.as_ref()
96 }
97}
98
99impl<Octs, SrcOcts> OctetsFrom<Padding<SrcOcts>> for Padding<Octs>
102where Octs: OctetsFrom<SrcOcts> {
103 type Error = Octs::Error;
104
105 fn try_octets_from(src: Padding<SrcOcts>) -> Result<Self, Self::Error> {
106 Octs::try_octets_from(src.octets).map(|octets| unsafe {
107 Self::from_octets_unchecked(octets)
108 })
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 }
142 else {
143 Ok(None)
144 }
145 }
146}
147
148impl<Octs: AsRef<[u8]>> ComposeOptData for Padding<Octs> {
149 fn compose_len(&self) -> u16 {
150 self.octets.as_ref().len().try_into().expect("long option data")
151 }
152
153 fn compose_option<Target: OctetsBuilder + ?Sized>(
154 &self, target: &mut Target
155 ) -> Result<(), Target::AppendError> {
156 target.append_slice(self.octets.as_ref())
157 }
158}
159
160impl<Octs: AsRef<[u8]> + ?Sized> fmt::Display for Padding<Octs> {
163 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164 for v in self.octets.as_ref() {
165 write!(f, "{:X} ", *v)?;
166 }
167 if let Ok(s) = str::from_utf8(self.octets.as_ref()) {
168 write!(f, "({})", s)?;
169 }
170 Ok(())
171 }
172}
173
174impl<Octs: AsRef<[u8]> + ?Sized> fmt::Debug for Padding<Octs> {
175 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
176 write!(f, "Padding({})", self)
177 }
178}
179
180impl<Target: Composer> OptBuilder<'_, Target> {
183 pub fn padding( &mut self, len: u16) -> Result<(), Target::AppendError> {
184 self.push_raw_option(
185 OptionCode::PADDING,
186 len,
187 |target| {
188 for _ in 0..len {
189 0u8.compose(target)?
190 }
191 Ok(())
192 }
193 )
194 }
195
196 #[cfg(feature = "rand")]
197 pub fn random_padding(
198 &mut self, len: u16
199 ) -> Result<(), Target::AppendError> {
200 self.push_raw_option(
201 OptionCode::PADDING,
202 len,
203 |target| {
204 for _ in 0..len {
205 rand::random::<u8>().compose(target)?
206 }
207 Ok(())
208 }
209 )
210 }
211}
212
213
214#[cfg(feature = "serde")]
217impl<Octs: AsRef<[u8]>> serde::Serialize for Padding<Octs> {
218 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
219 where
220 S: serde::Serializer {
221 use octseq::serde::SerializeOctets;
222 self.octets.as_ref().serialize_octets(serializer)
223 }
224}