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