domain/base/opt/
padding.rs
1use 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;
18use octseq::parse::Parser;
19
20
21#[derive(Clone, Copy)]
34pub struct Padding<Octs: ?Sized> {
35 octets: Octs,
37}
38
39impl<Octs> Padding<Octs> {
40 pub fn from_octets(octets: Octs) -> Result<Self, LongOptData>
44 where Octs: AsRef<[u8]> {
45 LongOptData::check_len(octets.as_ref().len())?;
46 Ok(unsafe { Self::from_octets_unchecked(octets) })
47 }
48
49 pub unsafe fn from_octets_unchecked(octets: Octs) -> Self {
56 Self { octets }
57 }
58
59 pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
61 parser: &mut Parser<'a, Src>
62 ) -> Result<Self, ParseError> {
63 let len = parser.remaining();
64 LongOptData::check_len(len)?;
65 Ok(unsafe { Self::from_octets_unchecked(
66 parser.parse_octets(len)?
67 )})
68 }
69}
70
71impl<Octs: ?Sized> Padding<Octs> {
72 pub fn as_octets(&self) -> &Octs {
74 &self.octets
75 }
76
77 pub fn into_octets(self) -> Octs
79 where
80 Octs: Sized,
81 {
82 self.octets
83 }
84
85 pub fn as_slice(&self) -> &[u8]
87 where
88 Octs: AsRef<[u8]>,
89 {
90 self.octets.as_ref()
91 }
92}
93
94impl<Octs: AsRef<[u8]> + ?Sized> AsRef<[u8]> for Padding<Octs> {
97 fn as_ref(&self) -> &[u8] {
98 self.as_slice()
99 }
100}
101
102impl<Octs: AsRef<[u8]> + ?Sized> borrow::Borrow<[u8]> for Padding<Octs> {
103 fn borrow(&self) -> &[u8] {
104 self.as_slice()
105 }
106}
107
108impl<Octs> OptData for Padding<Octs> {
111 fn code(&self) -> OptionCode {
112 OptionCode::Padding
113 }
114}
115
116impl<'a, Octs: Octets> ParseOptData<'a, Octs> for Padding<Octs::Range<'a>> {
117 fn parse_option(
118 code: OptionCode,
119 parser: &mut Parser<'a, Octs>,
120 ) -> Result<Option<Self>, ParseError> {
121 if code == OptionCode::Padding {
122 Self::parse(parser).map(Some)
123 }
124 else {
125 Ok(None)
126 }
127 }
128}
129
130impl<Octs: AsRef<[u8]>> ComposeOptData for Padding<Octs> {
131 fn compose_len(&self) -> u16 {
132 self.octets.as_ref().len().try_into().expect("long option data")
133 }
134
135 fn compose_option<Target: OctetsBuilder + ?Sized>(
136 &self, target: &mut Target
137 ) -> Result<(), Target::AppendError> {
138 target.append_slice(self.octets.as_ref())
139 }
140}
141
142impl<Octs: AsRef<[u8]> + ?Sized> fmt::Display for Padding<Octs> {
145 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146 for v in self.octets.as_ref() {
147 write!(f, "{:X} ", *v)?;
148 }
149 if let Ok(s) = str::from_utf8(self.octets.as_ref()) {
150 write!(f, "({})", s)?;
151 }
152 Ok(())
153 }
154}
155
156impl<Octs: AsRef<[u8]> + ?Sized> fmt::Debug for Padding<Octs> {
157 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
158 write!(f, "Padding({})", self)
159 }
160}
161
162impl<'a, Target: Composer> OptBuilder<'a, Target> {
165 pub fn padding( &mut self, len: u16) -> Result<(), Target::AppendError> {
166 self.push_raw_option(
167 OptionCode::Padding,
168 len,
169 |target| {
170 for _ in 0..len {
171 0u8.compose(target)?
172 }
173 Ok(())
174 }
175 )
176 }
177
178 #[cfg(feature = "rand")]
179 pub fn random_padding(
180 &mut self, len: u16
181 ) -> Result<(), Target::AppendError> {
182 self.push_raw_option(
183 OptionCode::Padding,
184 len,
185 |target| {
186 for _ in 0..len {
187 rand::random::<u8>().compose(target)?
188 }
189 Ok(())
190 }
191 )
192 }
193}
194