domain/rdata/svcb/
params.rs

1//! Handling of service binding parameters.
2//!
3//! This is a private module. It’s public types are re-exported by the
4//! parent.
5
6// Currently a false positive on SvcParams. We cannot apply it there because
7// the allow attribute doesn't get copied to the code generated by serde.
8#![allow(clippy::needless_maybe_sized)]
9
10use super::value::AllValues;
11use crate::base::cmp::CanonicalOrd;
12use crate::base::iana::SvcParamKey;
13use crate::base::scan::Symbol;
14use crate::base::wire::{Compose, Parse, ParseError};
15use crate::base::zonefile_fmt::{self, Formatter, ZonefileFmt};
16use core::cmp::Ordering;
17use core::marker::PhantomData;
18use core::{cmp, fmt, hash, mem};
19use octseq::builder::{EmptyBuilder, FromBuilder, OctetsBuilder, ShortBuf};
20use octseq::octets::{Octets, OctetsFrom, OctetsInto};
21use octseq::parse::{Parser, ShortInput};
22
23//------------ SvcParams -----------------------------------------------------
24
25/// A sequence of service binding parameters.
26///
27/// These parameters provide information helpful when trying to connect to an
28/// endpoint offering a service. They consist of a sequence of parameter
29/// values. Each value has a type and some data specific to that type. The
30/// type is provided through a `u16` key with values assigned via an IANA
31/// registry. The key and registry are available through
32/// [`SvcParamKey`]. Each key is only allowed to appear at most once in the
33/// parameter sequence. Values need to be ordered by their key’s integer value.
34///
35/// A value of the `SvcParams` type contains a sequence of values in their
36/// wire-format encoded form. It guarantees that this content is correctly
37/// encoded. It does not guarantee that the content of the individual
38/// parameter value is correct. It also does not guarantee any size limit
39/// to the octets sequence.
40///
41/// You can create a value of this type through parsing or manually via
42/// [`from_octets`][Self::from_octets] or [`from_slice`][Self::from_slice].
43/// You can also build a new value from scratch via the [`SvcParamsBuilder`].
44/// The [`from_values`][Self::from_values] function provides a shortcut that
45/// crates the builder, passes it to a closure, and returns the finished
46/// parameter sequence.
47///
48/// Access to the values of the parameter sequence happens through a mechanism
49/// similar to record data: Various types exist that implement either a
50/// specific value type or a group of types. These types need to implement the
51/// [`SvcParamValue`] and [`ParseSvcParamValue`] traits to be used to access
52/// values. They can be used as a type parameter to the [`iter`][Self::iter]
53/// method to acquire an iterator over all the values that they understand.
54/// Since every concrete value can only be present once, the
55/// [`first`][Self::first] method can be used together with a value type
56/// implementing that concrete value to get the value if present. As a
57/// convenience, methods exist for every currently defined value type which
58/// return a value of that type if present.
59///
60/// The type [`UnknownSvcParam`] can be used to represent any value type with
61/// the value as a octets sequence. The [`AllValues`] enum provides typed
62/// access to all known value types.
63///
64/// # Wire Format
65///
66/// The wire format of a parameter sequence consists of a sequence of
67/// values. Each value is encoded as a 16 bit parameter key – represented
68/// by [`SvcParamKey`] in this crate –, followed by an unsigned 16 bit length
69/// value, followed by this many octets. Since the sequence is the last element
70/// in the record data, it is limited by the length of the record data only.
71#[derive(Clone, Default)]
72#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
73#[repr(transparent)]
74pub struct SvcParams<Octs: ?Sized> {
75    #[cfg_attr(
76        feature = "serde",
77        serde(
78            serialize_with = "octseq::serde::SerializeOctets::serialize_octets",
79            deserialize_with = "octseq::serde::DeserializeOctets::deserialize_octets",
80            bound(
81                serialize = "Octs: octseq::serde::SerializeOctets",
82                deserialize = "Octs: octseq::serde::DeserializeOctets<'de> + Sized",
83            )
84        )
85    )]
86    octets: Octs,
87}
88
89impl<Octs> SvcParams<Octs> {
90    /// Creates a parameter sequence from an octets sequence.
91    ///
92    /// The method checks that `octets` contains a parameter sequence that is
93    /// correctly encoded in wire format. It does not check that the
94    /// individual values are correctly encoded. It also does not check for
95    /// any length limit.
96    pub fn from_octets(octets: Octs) -> Result<Self, SvcParamsError>
97    where
98        Octs: AsRef<[u8]>,
99    {
100        SvcParams::check_slice(octets.as_ref())?;
101        Ok(unsafe { Self::from_octets_unchecked(octets) })
102    }
103
104    /// Creates a new value from an octets sequence without checking.
105    ///
106    /// # Safety
107    ///
108    /// The caller has to ensure that `octets` contains a properly formatted
109    /// parameter sequence.
110    pub unsafe fn from_octets_unchecked(octets: Octs) -> Self {
111        SvcParams { octets }
112    }
113}
114
115impl SvcParams<[u8]> {
116    /// Creates a parameter sequence from an octets slice.
117    ///
118    /// The method checks that `slice` contains a parameter sequence that is
119    /// correctly encoded in wire format. It does not check that the
120    /// individual values are correctly encoded. It also does not check for
121    /// any length limit.
122    pub fn from_slice(slice: &[u8]) -> Result<&Self, SvcParamsError> {
123        SvcParams::check_slice(slice)?;
124        Ok(unsafe { Self::from_slice_unchecked(slice) })
125    }
126
127    /// Creates a new value from a slice without checking.
128    ///
129    /// # Safety
130    ///
131    /// The caller has to ensure that `slice` contains a properly formatted
132    /// parameter sequence.
133    #[must_use]
134    pub unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
135        // SAFETY: SvcParams has repr(transparent)
136        mem::transmute(slice)
137    }
138
139    /// Checks that a slice contains a correctly encoded parameters sequence.
140    fn check_slice(slice: &[u8]) -> Result<(), SvcParamsError> {
141        let mut parser = Parser::from_ref(slice);
142        let mut last_key = None;
143        while parser.remaining() > 0 {
144            let key = u16::parse(&mut parser)?;
145            if let Some(last_key) = last_key {
146                if key <= last_key {
147                    Err(ParseError::form_error("unordered SVCB params"))?;
148                }
149            }
150            last_key = Some(key);
151            let len = u16::parse(&mut parser)?;
152            parser.advance(len.into())?;
153        }
154        Ok(())
155    }
156}
157
158impl<Octs> SvcParams<Octs> {
159    /// Creates a parameter sequence by constructing it from values.
160    ///
161    /// The method expects a closure that receives an [`SvcParamsBuilder`]
162    /// which it should push all the required values to. Once it returns,
163    /// this builder is frozen into an `SvcParams` value and returned.
164    pub fn from_values<F>(op: F) -> Result<Self, PushError>
165    where
166        Octs: FromBuilder,
167        <Octs as FromBuilder>::Builder:
168            AsRef<[u8]> + OctetsBuilder + EmptyBuilder,
169        F: FnOnce(
170            &mut SvcParamsBuilder<<Octs as FromBuilder>::Builder>,
171        ) -> Result<(), PushError>,
172    {
173        let mut res = SvcParamsBuilder::empty();
174        op(&mut res)?;
175        res.freeze().map_err(Into::into)
176    }
177}
178
179impl<Octs: AsRef<[u8]>> SvcParams<Octs> {
180    /// Parses a parameter sequence from its wire format.
181    pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized + 'a>(
182        parser: &mut Parser<'a, Src>,
183    ) -> Result<Self, ParseError> {
184        Self::from_octets(parser.parse_octets(parser.remaining())?)
185            .map_err(Into::into)
186    }
187}
188
189impl<Octs: ?Sized> SvcParams<Octs> {
190    /// Returns a reference to the underlying octets sequence.
191    pub fn as_octets(&self) -> &Octs {
192        &self.octets
193    }
194}
195
196impl<Octs: AsRef<[u8]> + ?Sized> SvcParams<Octs> {
197    /// Returns a slice of the underlying octets sequence.
198    pub fn as_slice(&self) -> &[u8] {
199        self.octets.as_ref()
200    }
201
202    /// Returns a parameter sequence atop a slice of this value’s octets.
203    pub fn for_slice(&self) -> &SvcParams<[u8]> {
204        unsafe { SvcParams::from_slice_unchecked(self.octets.as_ref()) }
205    }
206
207    /// Returns the length of the parameter sequence in octets.
208    pub fn len(&self) -> usize {
209        self.octets.as_ref().len()
210    }
211
212    /// Returns whether the parameters sequences is empty.
213    pub fn is_empty(&self) -> bool {
214        self.octets.as_ref().is_empty()
215    }
216
217    /// Returns the first value of type `Value`.
218    ///
219    /// This method is intended to be used with value types implementing a
220    /// specific type. Since only one instance is allowed to be present,
221    /// this method also returns `None` if the first value fails parsing,
222    /// assuming that the value is unusable and should be ignored.
223    ///
224    /// This may not be the correct behaviour in all cases. Please use
225    /// `self.iter::<Value>().next()` to get an optional parsing result.
226    pub fn first<'s, Value>(&'s self) -> Option<Value>
227    where
228        Octs: Octets,
229        Value: ParseSvcParamValue<'s, Octs>,
230    {
231        self.iter::<Value>().next().and_then(Result::ok)
232    }
233
234    /// Returns an iterator over all values accepted by `Value`.
235    pub fn iter<Value>(&self) -> ValueIter<'_, Octs, Value> {
236        ValueIter::new(self.as_octets())
237    }
238
239    /// Returns an iterator over all values.
240    pub fn iter_all(&self) -> ValueIter<'_, Octs, AllValues<Octs>>
241    where
242        Octs: Sized,
243    {
244        self.iter()
245    }
246
247    /// Returns an iterator over all values in their raw form.
248    pub fn iter_raw(
249        &self,
250    ) -> impl Iterator<Item = UnknownSvcParam<Octs::Range<'_>>>
251    where
252        Octs: Octets + Sized,
253    {
254        self.iter()
255            .map(|item| item.expect("parsing cannot have failed"))
256    }
257
258    /// Composes the wire-format of the parameter sequence.
259    pub fn compose<Target: OctetsBuilder + ?Sized>(
260        &self,
261        target: &mut Target,
262    ) -> Result<(), Target::AppendError> {
263        target.append_slice(self.octets.as_ref())
264    }
265}
266
267//--- OctetsFrom
268
269impl<SrcOcts, Octs> OctetsFrom<SvcParams<SrcOcts>> for SvcParams<Octs>
270where
271    Octs: OctetsFrom<SrcOcts>,
272{
273    type Error = Octs::Error;
274
275    fn try_octets_from(src: SvcParams<SrcOcts>) -> Result<Self, Self::Error> {
276        Ok(unsafe {
277            SvcParams::from_octets_unchecked(src.octets.try_octets_into()?)
278        })
279    }
280}
281
282//--- PartialEq and Eq
283
284impl<Octs, OtherOcts> PartialEq<SvcParams<OtherOcts>> for SvcParams<Octs>
285where
286    Octs: AsRef<[u8]> + ?Sized,
287    OtherOcts: AsRef<[u8]> + ?Sized,
288{
289    fn eq(&self, other: &SvcParams<OtherOcts>) -> bool {
290        self.as_slice().eq(other.as_slice())
291    }
292}
293
294impl<Octs: AsRef<[u8]> + ?Sized> Eq for SvcParams<Octs> {}
295
296//--- Hash
297
298impl<Octs: AsRef<[u8]> + ?Sized> hash::Hash for SvcParams<Octs> {
299    fn hash<H: hash::Hasher>(&self, state: &mut H) {
300        self.as_slice().hash(state)
301    }
302}
303
304//--- PartialOrd Ord, and CanonicalOrd
305
306impl<Octs, OtherOcts> PartialOrd<SvcParams<OtherOcts>> for SvcParams<Octs>
307where
308    Octs: AsRef<[u8]> + ?Sized,
309    OtherOcts: AsRef<[u8]> + ?Sized,
310{
311    fn partial_cmp(
312        &self,
313        other: &SvcParams<OtherOcts>,
314    ) -> Option<cmp::Ordering> {
315        self.as_slice().partial_cmp(other.as_slice())
316    }
317}
318
319impl<Octs: AsRef<[u8]> + ?Sized> Ord for SvcParams<Octs> {
320    fn cmp(&self, other: &Self) -> cmp::Ordering {
321        self.as_slice().cmp(other.as_slice())
322    }
323}
324
325impl<Octs, OtherOcts> CanonicalOrd<SvcParams<OtherOcts>> for SvcParams<Octs>
326where
327    Octs: AsRef<[u8]> + ?Sized,
328    OtherOcts: AsRef<[u8]> + ?Sized,
329{
330    fn canonical_cmp(&self, other: &SvcParams<OtherOcts>) -> cmp::Ordering {
331        self.as_slice().cmp(other.as_slice())
332    }
333}
334
335//--- Display and Debug
336
337impl<Octs: Octets + ?Sized> fmt::Display for SvcParams<Octs> {
338    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
339        let mut parser = Parser::from_ref(self.as_slice());
340        let mut first = true;
341        while parser.remaining() > 0 {
342            let key =
343                SvcParamKey::parse(&mut parser).expect("invalid SvcbParam");
344            let len = usize::from(
345                u16::parse(&mut parser).expect("invalid SvcParam"),
346            );
347            let mut parser =
348                parser.parse_parser(len).expect("invalid SvcParam");
349            if first {
350                first = false;
351            } else {
352                f.write_str(" ")?;
353            }
354            write!(
355                f,
356                "{}",
357                super::value::AllValues::parse_any(key, &mut parser)
358            )?;
359        }
360        Ok(())
361    }
362}
363
364impl<Octs: Octets + ?Sized> fmt::Debug for SvcParams<Octs> {
365    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
366        f.debug_tuple("SvcParams")
367            .field(&format_args!("{}", self))
368            .finish()
369    }
370}
371
372//--- ZonefileFmt
373
374impl<Octs: Octets + ?Sized> ZonefileFmt for SvcParams<Octs> {
375    fn fmt(&self, p: &mut impl Formatter) -> zonefile_fmt::Result {
376        p.block(|p| {
377            let mut parser = Parser::from_ref(self.as_slice());
378            while parser.remaining() > 0 {
379                let key = SvcParamKey::parse(&mut parser)
380                    .expect("invalid SvcbParam");
381                let len = usize::from(
382                    u16::parse(&mut parser).expect("invalid SvcParam"),
383                );
384                let mut parser =
385                    parser.parse_parser(len).expect("invalid SvcParam");
386                p.write_token(super::value::AllValues::parse_any(
387                    key,
388                    &mut parser,
389                ))?;
390            }
391            Ok(())
392        })
393    }
394}
395
396//------------ ValueIter -----------------------------------------------------
397
398/// An iterator over the values in a parameter sequence.
399///
400/// The iterator skips over those values that `Value` does not accept. It
401/// returns the result of trying to parse the value into `Value`.
402#[derive(Clone, Debug)]
403pub struct ValueIter<'a, Octs: ?Sized, Value> {
404    parser: Parser<'a, Octs>,
405    marker: PhantomData<Value>,
406}
407
408impl<'a, Octs: AsRef<[u8]> + ?Sized, Value> ValueIter<'a, Octs, Value> {
409    fn new(octets: &'a Octs) -> Self {
410        ValueIter {
411            parser: Parser::from_ref(octets),
412            marker: PhantomData,
413        }
414    }
415
416    fn next_step(&mut self) -> Result<Option<Value>, ParseError>
417    where
418        Octs: Octets,
419        Value: ParseSvcParamValue<'a, Octs>,
420    {
421        let key = SvcParamKey::parse(&mut self.parser)?;
422        let len = usize::from(u16::parse(&mut self.parser)?);
423        let mut parser = self.parser.parse_parser(len)?;
424        let res = Value::parse_value(key, &mut parser)?;
425        if res.is_some() && parser.remaining() > 0 {
426            return Err(ParseError::form_error(
427                "trailing data in SVCB parameter",
428            ));
429        }
430        Ok(res)
431    }
432}
433
434impl<'a, Octs, Value> Iterator for ValueIter<'a, Octs, Value>
435where
436    Octs: Octets + ?Sized,
437    Value: ParseSvcParamValue<'a, Octs>,
438{
439    type Item = Result<Value, ParseError>;
440
441    fn next(&mut self) -> Option<Self::Item> {
442        while self.parser.remaining() > 0 {
443            match self.next_step() {
444                Ok(Some(res)) => return Some(Ok(res)),
445                Ok(None) => {}
446                Err(err) => {
447                    // Advance to end so we’ll return None from now on.
448                    self.parser.advance_to_end();
449                    return Some(Err(err));
450                }
451            }
452        }
453        None
454    }
455}
456
457//------------ SvcParamValue, ParseSvcParamValue, ComposeSvcParamValue -------
458
459/// A type representing a service binding parameter value.
460pub trait SvcParamValue {
461    /// Returns the parameter key of the value.
462    fn key(&self) -> SvcParamKey;
463}
464
465/// A service binding parameter value that can be parse from wire format.
466pub trait ParseSvcParamValue<'a, Octs: ?Sized>:
467    SvcParamValue + Sized
468{
469    /// Parse a parameter value from wire format.
470    ///
471    /// The method should return `Ok(None)` if the type cannot parse values
472    /// with `key`. It should return an error if parsing fails.
473    fn parse_value(
474        key: SvcParamKey,
475        parser: &mut Parser<'a, Octs>,
476    ) -> Result<Option<Self>, ParseError>;
477}
478
479/// A service binding parameter value that can be composed into wire format.
480///
481/// All value types need to be able to calculate the length of their
482/// wire format. This length needs to fit into a `u16`. It is the
483/// responsibility of the value type to ensure that it will not grow too
484/// large.
485pub trait ComposeSvcParamValue: SvcParamValue {
486    /// Returns the length of the composed value.
487    fn compose_len(&self) -> u16;
488
489    /// Appends the wire format of the value to the end of `target`.
490    fn compose_value<Target: OctetsBuilder + ?Sized>(
491        &self,
492        target: &mut Target,
493    ) -> Result<(), Target::AppendError>;
494}
495
496//------------ UnknownSvcParam -----------------------------------------------
497
498/// A service binding parameter value in its raw form.
499///
500/// This type can be used for any value type. It keeps the value’s data in
501/// its raw wire format.
502#[derive(Clone, Debug)]
503pub struct UnknownSvcParam<Octs> {
504    /// The key of the value.
505    key: SvcParamKey,
506
507    /// The octets of the value.
508    value: Octs,
509}
510
511impl<Octs> UnknownSvcParam<Octs> {
512    /// Creates a new parameter value from the given key and data.
513    ///
514    /// The function returns an error if `value` is longer than 65,535 octets.
515    pub fn new(key: SvcParamKey, value: Octs) -> Result<Self, LongSvcParam>
516    where
517        Octs: AsRef<[u8]>,
518    {
519        LongSvcParam::check_len(value.as_ref().len())?;
520        Ok(unsafe { Self::new_unchecked(key, value) })
521    }
522
523    /// Creates a new SVCB parameter value without checking.
524    ///
525    /// # Safety
526    ///
527    /// The caller needs to make sure that `value` is not longer than
528    /// 65,535 octets.
529    pub unsafe fn new_unchecked(key: SvcParamKey, value: Octs) -> Self {
530        Self { key, value }
531    }
532}
533
534impl<Octs: AsRef<[u8]>> UnknownSvcParam<Octs> {
535    /// Parses a parameter value’s data from its wire format.
536    pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
537        key: SvcParamKey,
538        parser: &mut Parser<'a, Src>,
539    ) -> Result<Self, ParseError> {
540        Self::new(key, parser.parse_octets(parser.remaining())?)
541            .map_err(Into::into)
542    }
543
544    /// Parses a full parameter from the wire format.
545    ///
546    /// This function parses the key, length, and data of the parameter.
547    pub fn parse_param<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
548        parser: &mut Parser<'a, Src>,
549    ) -> Result<Self, ParseError> {
550        let key = SvcParamKey::parse(parser)?;
551        let len = usize::from(u16::parse(parser)?);
552        let value = parser.parse_octets(len)?;
553        Ok(unsafe { Self::new_unchecked(key, value) })
554    }
555
556    /// Appends the wire format of the full parameter to the target.
557    ///
558    /// This includes the key and length of the parameter.
559    pub fn compose_param<Target: OctetsBuilder + ?Sized>(
560        &self,
561        target: &mut Target,
562    ) -> Result<(), Target::AppendError> {
563        self.key.compose(target)?;
564        self.compose_len().compose(target)?;
565        self.compose_value(target)
566    }
567}
568
569impl<Octs> UnknownSvcParam<Octs> {
570    /// Returns the key of the value.
571    pub fn key(&self) -> SvcParamKey {
572        self.key
573    }
574
575    /// Returns a reference to the value octets.
576    pub fn value(&self) -> &Octs {
577        &self.value
578    }
579
580    /// Returns a slice of the value.
581    pub fn as_slice(&self) -> &[u8]
582    where
583        Octs: AsRef<[u8]>,
584    {
585        self.value.as_ref()
586    }
587
588    /// Returns a mutable slice of the value.
589    pub fn as_slice_mut(&mut self) -> &mut [u8]
590    where
591        Octs: AsMut<[u8]>,
592    {
593        self.value.as_mut()
594    }
595}
596
597//--- AsRef and AsMut
598
599impl<Octs> AsRef<Octs> for UnknownSvcParam<Octs> {
600    fn as_ref(&self) -> &Octs {
601        self.value()
602    }
603}
604
605impl<Octs: AsRef<[u8]>> AsRef<[u8]> for UnknownSvcParam<Octs> {
606    fn as_ref(&self) -> &[u8] {
607        self.as_slice()
608    }
609}
610
611impl<Octs: AsMut<[u8]>> AsMut<[u8]> for UnknownSvcParam<Octs> {
612    fn as_mut(&mut self) -> &mut [u8] {
613        self.as_slice_mut()
614    }
615}
616
617//--- PartialEq and Eq
618
619impl<Octs, OtherOcts> PartialEq<UnknownSvcParam<OtherOcts>>
620    for UnknownSvcParam<Octs>
621where
622    Octs: AsRef<[u8]>,
623    OtherOcts: AsRef<[u8]>,
624{
625    fn eq(&self, other: &UnknownSvcParam<OtherOcts>) -> bool {
626        self.as_slice().eq(other.as_slice())
627    }
628}
629
630impl<Octs: AsRef<[u8]>> Eq for UnknownSvcParam<Octs> {}
631
632//--- Hash
633
634impl<Octs: AsRef<[u8]>> hash::Hash for UnknownSvcParam<Octs> {
635    fn hash<H: hash::Hasher>(&self, state: &mut H) {
636        self.as_slice().hash(state)
637    }
638}
639
640//--- SvcParamValue et al.
641
642impl<Octs> SvcParamValue for UnknownSvcParam<Octs> {
643    fn key(&self) -> SvcParamKey {
644        self.key
645    }
646}
647
648impl<'a, Octs: Octets + ?Sized> ParseSvcParamValue<'a, Octs>
649    for UnknownSvcParam<Octs::Range<'a>>
650{
651    fn parse_value(
652        key: SvcParamKey,
653        parser: &mut Parser<'a, Octs>,
654    ) -> Result<Option<Self>, ParseError> {
655        Self::new(key, parser.parse_octets(parser.remaining())?)
656            .map(Some)
657            .map_err(Into::into)
658    }
659}
660
661impl<Octs: AsRef<[u8]>> ComposeSvcParamValue for UnknownSvcParam<Octs> {
662    fn compose_len(&self) -> u16 {
663        u16::try_from(self.as_slice().len()).expect("long value")
664    }
665
666    fn compose_value<Target: OctetsBuilder + ?Sized>(
667        &self,
668        target: &mut Target,
669    ) -> Result<(), Target::AppendError> {
670        target.append_slice(self.as_slice())
671    }
672}
673
674//--- Display and Debug
675
676impl<Octs: AsRef<[u8]>> fmt::Display for UnknownSvcParam<Octs> {
677    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
678        write!(f, "{}", self.key)?;
679        let slice = self.value.as_ref();
680        if !slice.is_empty() {
681            f.write_str("=")?;
682            for &ch in slice {
683                Symbol::from_octet(ch).fmt(f)?;
684            }
685        }
686        Ok(())
687    }
688}
689
690//------------ SvcParamsBuilder ----------------------------------------------
691
692/// A builder for a service parameter sequence.
693///
694/// This type wraps an octets builder and allows appending parameter values.
695/// You can create a new empty builder using the [`empty`][Self::empty]
696/// function or copy an existing value through
697/// [`from_params`][Self::from_params].
698///
699/// You can add additional values using the [`push`][Self::push] method.
700/// There are also dedicated methods for all known value types. The builder
701/// will make sure that each parameter key can only appear once. Thus,
702/// pushing values may fail if a value is already present.
703///
704/// The builder also takes care of sorting the values into their correct
705/// order. So you can push them in any order.
706///
707/// It only sorts the items when producing a frozen value via the
708/// [`freeze`][Self::freeze] method.
709#[derive(Clone, Debug)]
710pub struct SvcParamsBuilder<Octs> {
711    /// The octets builder.
712    octets: Octs,
713}
714
715impl<Octs> SvcParamsBuilder<Octs> {
716    /// Creates an empty parameter builder.
717    #[must_use]
718    pub fn empty() -> Self
719    where
720        Octs: EmptyBuilder,
721    {
722        Self {
723            octets: Octs::empty(),
724        }
725    }
726
727    /// Creates a parameter builder from an existing parameter sequence.
728    ///
729    /// The function creates a new empty builder and copies over the content
730    /// of `params`. It can fail if the octets builder is not capable of
731    /// providing enough space to hold the content of `params`.
732    pub fn from_params<Src: Octets + ?Sized>(
733        params: &SvcParams<Src>,
734    ) -> Result<Self, ShortBuf>
735    where
736        Octs: AsRef<[u8]> + OctetsBuilder + EmptyBuilder,
737    {
738        let mut octets = Octs::empty();
739        for item in params.iter::<UnknownSvcParam<_>>() {
740            let item = item.expect("invalid SvcParams");
741            let start = u32::try_from(octets.as_ref().len())
742                .map_err(|_| ShortBuf)?
743                .checked_add(u32::from(u32::COMPOSE_LEN))
744                .ok_or(ShortBuf)?;
745            octets
746                .append_slice(start.to_ne_bytes().as_ref())
747                .map_err(Into::into)?;
748            item.compose_param(&mut octets).map_err(Into::into)?;
749        }
750        octets
751            .append_slice(u32::MAX.to_be_bytes().as_ref())
752            .map_err(Into::into)?;
753        Ok(Self { octets })
754    }
755
756    /// Adds a new value to the builder.
757    ///
758    /// The method will return an error if a value with this key is already
759    /// present or if there isn’t enough space left in the builder’s buffer.
760    pub fn push<Value: ComposeSvcParamValue + ?Sized>(
761        &mut self,
762        value: &Value,
763    ) -> Result<(), PushError>
764    where
765        Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>,
766    {
767        self.push_raw(value.key(), value.compose_len(), |octs| {
768            value.compose_value(octs)
769        })
770    }
771
772    pub(super) fn push_raw(
773        &mut self,
774        key: SvcParamKey,
775        value_len: u16,
776        value: impl FnOnce(&mut Octs) -> Result<(), Octs::AppendError>,
777    ) -> Result<(), PushError>
778    where
779        Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>,
780    {
781        // If octets is emtpy, we can just append ourselves and be done.
782        if self.octets.as_ref().is_empty() {
783            self.octets
784                .append_slice(&u32::from(u32::COMPOSE_LEN).to_ne_bytes())?;
785            key.compose(&mut self.octets)?;
786            value_len.compose(&mut self.octets)?;
787            (value)(&mut self.octets)?;
788            u32::MAX.compose(&mut self.octets)?;
789            return Ok(());
790        }
791
792        // Where will this value start? This also serves as a check whether
793        // we have become too long.
794        let start = u32::try_from(self.octets.as_ref().len())
795            .map_err(|_| PushError::ShortBuf)?;
796
797        // Go over the values and find the predecessor and successor.
798        let mut pre = None;
799        let mut next = None;
800        let mut parser = Parser::from_ref(self.octets.as_ref());
801
802        // Skip the first pointer.
803        parser.advance(u32::COMPOSE_LEN.into()).unwrap();
804
805        while parser.remaining() > 0 {
806            let tmp_start = u32::try_from(parser.pos()).unwrap();
807            let tmp = UnknownSvcParam::parse_param(&mut parser).unwrap();
808            let tmp_end = u32::try_from(parser.pos()).unwrap();
809            let tmp_key = tmp.key();
810            match tmp_key.cmp(&key) {
811                Ordering::Equal => return Err(PushError::DuplicateKey),
812                Ordering::Less => match pre {
813                    Some((key, _)) => {
814                        if tmp_key > key {
815                            pre = Some((tmp_key, tmp_end));
816                        }
817                    }
818                    None => pre = Some((tmp_key, tmp_end)),
819                },
820                Ordering::Greater => match next {
821                    Some((key, _)) => {
822                        if tmp_key < key {
823                            next = Some((tmp_key, tmp_start));
824                        }
825                    }
826                    None => next = Some((tmp_key, tmp_start)),
827                },
828            }
829            parser.advance(u32::COMPOSE_LEN.into()).unwrap();
830        }
831
832        // Append the value.
833        key.compose(&mut self.octets)?;
834        value_len.compose(&mut self.octets)?;
835        (value)(&mut self.octets)?;
836
837        // Append the pointer to the next value. MAX means none.
838        self.octets.append_slice(
839            &next.map(|(_, pos)| pos).unwrap_or(u32::MAX).to_ne_bytes(),
840        )?;
841
842        // Replace the predecessor’s point with our start. If there is no
843        // predecessor, we are the first item.
844        let pos = pre
845            .map(|(_, pos)| {
846                // The u32 here was made from a usize so converting it back has to
847                // work.
848                usize::try_from(pos).unwrap()
849            })
850            .unwrap_or(0);
851        self.octets.as_mut()[pos..pos + usize::from(u32::COMPOSE_LEN)]
852            .copy_from_slice(&start.to_ne_bytes());
853
854        Ok(())
855    }
856
857    /// Freezes the builder to a parameter sequence.
858    ///
859    /// Because the values may need to be resorted, this method actually
860    /// produces a new octets sequence. This is why it doesn’t consume the
861    /// builder and may fail if the target octet’s builder can’t provide
862    /// enough space.
863    pub fn freeze<Target>(
864        &self,
865    ) -> Result<
866        SvcParams<Target>,
867        <<Target as FromBuilder>::Builder as OctetsBuilder>::AppendError,
868    >
869    where
870        Octs: AsRef<[u8]>,
871        Target: FromBuilder,
872        <Target as FromBuilder>::Builder: OctetsBuilder + EmptyBuilder,
873    {
874        let mut target = <Target as FromBuilder>::Builder::empty();
875        if !self.octets.as_ref().is_empty() {
876            let mut parser = Parser::from_ref(self.octets.as_ref());
877            loop {
878                let pos =
879                    u32::from_ne_bytes(Parse::parse(&mut parser).unwrap());
880                if pos == u32::MAX {
881                    break;
882                }
883                let pos = usize::try_from(pos).unwrap();
884                parser.seek(pos).unwrap();
885                let param =
886                    UnknownSvcParam::parse_param(&mut parser).unwrap();
887                param.compose_param(&mut target)?;
888            }
889        }
890        Ok(unsafe {
891            SvcParams::from_octets_unchecked(Target::from_builder(target))
892        })
893    }
894}
895
896//============ Error Types ===================================================
897
898//------------ SvcParamsError -----------------------------------------------
899
900/// An octets sequence was not a valid service bindings parameter sequence.
901pub struct SvcParamsError(ParseError);
902
903impl From<ShortInput> for SvcParamsError {
904    fn from(err: ShortInput) -> Self {
905        ParseError::from(err).into()
906    }
907}
908
909impl From<ParseError> for SvcParamsError {
910    fn from(err: ParseError) -> Self {
911        SvcParamsError(err)
912    }
913}
914
915impl From<SvcParamsError> for ParseError {
916    fn from(err: SvcParamsError) -> Self {
917        err.0
918    }
919}
920
921//------------ LongSvcParam --------------------------------------------------
922
923/// The octets sequence to be used for record data is too long.
924#[derive(Clone, Copy, Debug)]
925pub struct LongSvcParam(());
926
927impl LongSvcParam {
928    #[must_use]
929    pub fn as_str(self) -> &'static str {
930        "service parameter too long"
931    }
932
933    pub fn check_len(len: usize) -> Result<(), Self> {
934        if len > usize::from(u16::MAX) {
935            Err(LongSvcParam(()))
936        } else {
937            Ok(())
938        }
939    }
940}
941
942impl From<LongSvcParam> for ParseError {
943    fn from(src: LongSvcParam) -> Self {
944        ParseError::form_error(src.as_str())
945    }
946}
947
948impl fmt::Display for LongSvcParam {
949    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
950        f.write_str(self.as_str())
951    }
952}
953
954#[cfg(feature = "std")]
955impl std::error::Error for LongSvcParam {}
956
957//------------ PushError -----------------------------------------------------
958
959/// An error happened when pushing values to a parameters builder.
960#[derive(Clone, Copy, Debug)]
961#[non_exhaustive]
962pub enum PushError {
963    /// A value with this key is already present.
964    DuplicateKey,
965
966    /// The octets builder does not have enough space to append the value.
967    ShortBuf,
968}
969
970impl<T: Into<ShortBuf>> From<T> for PushError {
971    fn from(_: T) -> Self {
972        PushError::ShortBuf
973    }
974}
975
976impl fmt::Display for PushError {
977    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
978        match self {
979            PushError::DuplicateKey => f.write_str("duplicate key"),
980            PushError::ShortBuf => ShortBuf.fmt(f),
981        }
982    }
983}
984
985#[cfg(feature = "std")]
986impl std::error::Error for PushError {}
987
988//============ Tests =========================================================
989
990#[cfg(test)]
991mod test {
992    use super::super::value;
993    use super::*;
994    use octseq::array::Array;
995
996    type Octets512 = Array<512>;
997    type Params512 = SvcParams<Array<512>>;
998    type Builder512 = SvcParamsBuilder<Array<512>>;
999
1000    fn octets512(slice: impl AsRef<[u8]>) -> Octets512 {
1001        Octets512::try_from(slice.as_ref()).unwrap()
1002    }
1003
1004    //--- Test vectors from the draft.
1005    //
1006    // We’re only testing the parameter portion here.
1007
1008    macro_rules! parse_compose {
1009        ( $rdata:expr, [ $( $value:expr )* ] ) => {
1010            // parse test
1011            let mut parser = Parser::from_ref($rdata.as_ref());
1012            let params = SvcParams::parse(&mut parser).unwrap();
1013
1014            let mut param_iter = params.iter_all();
1015            $(
1016                assert_eq!(
1017                    param_iter.next().unwrap().unwrap(),
1018                    AllValues::<Octets512>::from($value)
1019                );
1020            )*
1021            assert_eq!(None, param_iter.next());
1022
1023            // compose test
1024            let built = Params512::from_values(|_builder| {
1025                $(
1026                    _builder.push(&$value).unwrap();
1027                )*
1028                Ok(())
1029            }).unwrap();
1030            let mut buf = Octets512::new();
1031            built.compose(&mut buf).unwrap();
1032            assert_eq!($rdata.as_ref(), buf.as_ref());
1033        }
1034    }
1035
1036    #[test]
1037    fn test_vectors_alias() {
1038        parse_compose!(b"", []);
1039    }
1040
1041    #[test]
1042    fn test_vectors_port_only() {
1043        parse_compose!(
1044            b"\x00\x03\
1045              \x00\x02\
1046              \x00\x35",
1047            [value::Port::new(53)]
1048        );
1049    }
1050
1051    #[test]
1052    fn test_vectors_unknown_param() {
1053        parse_compose!(
1054            b"\x02\x9b\
1055              \x00\x05\
1056              \x68\x65\x6c\x6c\x6f",
1057            [UnknownSvcParam::new(0x029b.into(), octets512(b"hello"))
1058                .unwrap()]
1059        );
1060    }
1061
1062    #[test]
1063    fn test_vectors_unknown_param_quote() {
1064        parse_compose!(
1065            b"\x02\x9b\
1066              \x00\x09\
1067              \x68\x65\x6c\x6c\x6f\xd2\x71\x6f\x6f",
1068            [UnknownSvcParam::new(
1069                0x029b.into(),
1070                octets512(b"\x68\x65\x6c\x6c\x6f\xd2\x71\x6f\x6f"),
1071            )
1072            .unwrap()]
1073        );
1074    }
1075
1076    #[test]
1077    fn test_vectors_ipv6hint() {
1078        use crate::base::net::Ipv6Addr;
1079        use core::str::FromStr;
1080
1081        parse_compose!(
1082            b"\x00\x06\
1083              \x00\x20\
1084              \x20\x01\x0d\xb8\x00\x00\x00\x00\
1085              \x00\x00\x00\x00\x00\x00\x00\x01\
1086              \x20\x01\x0d\xb8\x00\x00\x00\x00\
1087              \x00\x00\x00\x00\x00\x53\x00\x01",
1088            [value::Ipv6Hint::<Octets512>::from_addrs([
1089                Ipv6Addr::from_str("2001:db8::1").unwrap(),
1090                Ipv6Addr::from_str("2001:db8::53:1").unwrap(),
1091            ])
1092            .unwrap()]
1093        );
1094    }
1095
1096    #[test]
1097    fn test_vectors_ipv6hint_v4mapped() {
1098        use crate::base::net::Ipv6Addr;
1099        use core::str::FromStr;
1100
1101        parse_compose!(
1102            b"\x00\x06\
1103              \x00\x10\
1104              \x00\x00\x00\x00\x00\x00\x00\x00\
1105              \x00\x00\xff\xff\xc6\x33\x64\x64",
1106            [
1107                value::Ipv6Hint::<Octets512>::from_addrs([
1108                    Ipv6Addr::from_str("::ffff:198.51.100.100").unwrap(),
1109                ])
1110                .unwrap()
1111            ]
1112        );
1113    }
1114
1115    // test vector key_sorting: see builder tests below
1116    // test vector alpn_escape: see super::value::test
1117
1118    #[cfg(feature = "std")]
1119    #[test]
1120    fn test_representation() {
1121        let mandatory = value::Mandatory::<Octets512>::from_keys(
1122            [
1123                SvcParamKey::ALPN,
1124                SvcParamKey::IPV4HINT,
1125                SvcParamKey::PRIVATE_RANGE_BEGIN.into(),
1126            ]
1127            .into_iter(),
1128        )
1129        .unwrap();
1130        assert_eq!(
1131            "mandatory=alpn,ipv4hint,key65280",
1132            format!("{}", mandatory)
1133        );
1134
1135        let mut alpn_builder = value::AlpnBuilder::<Octets512>::empty();
1136        alpn_builder.push("h2").unwrap();
1137        alpn_builder.push("h3-19").unwrap();
1138        assert_eq!("alpn=h2,h3-19", format!("{}", alpn_builder.freeze()));
1139
1140        assert_eq!("nodefaultalpn", format!("{}", value::NoDefaultAlpn));
1141
1142        assert_eq!(
1143            "ech",
1144            format!("{}", value::Ech::from_octets(Octets512::new()).unwrap())
1145        );
1146
1147        assert_eq!(
1148            "ipv4hint=192.0.2.1,192.0.2.2",
1149            format!(
1150                "{}",
1151                value::Ipv4Hint::<Octets512>::from_addrs([
1152                    [192, 0, 2, 1].into(),
1153                    [192, 0, 2, 2].into()
1154                ])
1155                .unwrap()
1156            )
1157        );
1158    }
1159
1160    //--- Builder
1161
1162    #[test]
1163    fn empty_builder() {
1164        assert_eq!(
1165            Builder512::empty()
1166                .freeze::<Octets512>()
1167                .unwrap()
1168                .as_slice(),
1169            b""
1170        );
1171    }
1172
1173    #[test]
1174    fn one_value() {
1175        let mut builder = Builder512::empty();
1176        builder.push(&value::Port::new(53)).unwrap();
1177        assert_eq!(
1178            builder.freeze::<Octets512>().unwrap().as_slice(),
1179            b"\x00\x03\x00\x02\x00\x35"
1180        );
1181    }
1182
1183    #[test]
1184    fn three_values_in_order() {
1185        let mut builder = Builder512::empty();
1186        builder
1187            .push(&UnknownSvcParam::new(1.into(), b"223").unwrap())
1188            .unwrap();
1189        builder
1190            .push(&UnknownSvcParam::new(2.into(), b"224").unwrap())
1191            .unwrap();
1192        builder
1193            .push(&UnknownSvcParam::new(8.into(), b"225").unwrap())
1194            .unwrap();
1195        assert_eq!(
1196            builder.freeze::<Octets512>().unwrap().as_slice(),
1197            b"\x00\x01\x00\x03223\
1198              \x00\x02\x00\x03224\
1199              \x00\x08\x00\x03225"
1200        );
1201    }
1202
1203    #[test]
1204    fn three_values_out_of_order() {
1205        let mut builder = Builder512::empty();
1206        builder
1207            .push(&UnknownSvcParam::new(1.into(), b"223").unwrap())
1208            .unwrap();
1209        builder
1210            .push(&UnknownSvcParam::new(8.into(), b"225").unwrap())
1211            .unwrap();
1212        builder
1213            .push(&UnknownSvcParam::new(2.into(), b"224").unwrap())
1214            .unwrap();
1215        assert_eq!(
1216            builder.freeze::<Octets512>().unwrap().as_slice(),
1217            b"\x00\x01\x00\x03223\
1218              \x00\x02\x00\x03224\
1219              \x00\x08\x00\x03225"
1220        );
1221    }
1222
1223    #[test]
1224    fn three_values_with_collision() {
1225        let mut builder = Builder512::empty();
1226        builder
1227            .push(&UnknownSvcParam::new(1.into(), b"223").unwrap())
1228            .unwrap();
1229        builder
1230            .push(&UnknownSvcParam::new(8.into(), b"225").unwrap())
1231            .unwrap();
1232        assert!(builder
1233            .push(&UnknownSvcParam::new(8.into(), b"224").unwrap())
1234            .is_err());
1235    }
1236}