domain/rdata/svcb/
value.rs

1use super::{
2    ComposeSvcParamValue, LongSvcParam, PushError, ParseSvcParamValue,
3    SvcParamsBuilder, SvcParams, SvcParamValue, UnknownSvcParam,
4};
5use crate::base::iana::SvcParamKey;
6use crate::base::net::{Ipv4Addr, Ipv6Addr};
7use crate::base::wire::{Compose, Parse, ParseError};
8use crate::utils::base64;
9use octseq::builder::{
10    EmptyBuilder, FreezeBuilder, FromBuilder, OctetsBuilder, ShortBuf
11};
12use octseq::octets::{Octets, OctetsFrom};
13use octseq::parse::Parser;
14use octseq::str::Str;
15use core::{fmt, hash, mem, str};
16use core::fmt::Write as _;
17use core::str::FromStr;
18
19//============ AllValues =====================================================
20
21macro_rules! values_enum {
22    (
23        $( $type:ident $( < $( $type_arg:ident ),* > )?, )+
24    ) => {
25        /// All known service bindings parameter values.
26        ///
27        /// This type allows parsing all known parameter values into their
28        /// dedicated type and all unknown values into their raw form.
29        #[derive(Debug, Clone)]
30        pub enum AllValues<Octs> {
31            $(
32                $type($type $( < $( $type_arg ),* > )? ),
33            )+
34            Unknown(UnknownSvcParam<Octs>),
35        }
36
37        impl<Octs: AsRef<[u8]>> AllValues<Octs> {
38            /// Parses any service bindings parameter value.
39            ///
40            /// If a known variant fails to parse, returns it as the unknown
41            /// variant instead.
42            ///
43            /// # Panics
44            ///
45            /// Panics if taking the remaining octets from the parser fails.
46            pub(super) fn parse_any<'a, Src>(
47                key: SvcParamKey,
48                parser: &mut Parser<'a, Src>,
49            ) -> Self
50            where Src: Octets<Range<'a> = Octs> + ?Sized {
51                let pos = parser.pos();
52                let res = match key {
53                    $(
54                        $type::KEY => {
55                            $type::parse(
56                                parser
57                            ).map(Self::$type)
58                        }
59                    )+
60                    _ => {
61                        UnknownSvcParam::parse(
62                            key, parser
63                        ).map(Self::Unknown)
64                    }
65                };
66                if let Ok(res) = res {
67                    return res
68                }
69                parser.seek(pos).expect("invalid SvcParams");
70                let octets = parser.parse_octets(
71                    parser.remaining()
72                ).expect("invalid SvcParams");
73
74                Self::Unknown(unsafe { 
75                    UnknownSvcParam::new_unchecked(key, octets)
76                })
77            }
78        }
79
80        //--- From
81
82        $(
83            impl<Octs> From<$type $( < $( $type_arg ),* > )*>
84            for AllValues<Octs> {
85                fn from(p: $type $( < $( $type_arg ),* > )*) -> Self {
86                    Self::$type(p)
87                }
88            }
89        )+
90
91        impl<Octs> From<UnknownSvcParam<Octs>> for AllValues<Octs> {
92            fn from(p: UnknownSvcParam<Octs>) -> Self {
93                Self::Unknown(p)
94            }
95        }
96
97        //--- SvcParamValue et al.
98
99        impl<Octs> SvcParamValue for AllValues<Octs> {
100            fn key(&self) -> SvcParamKey {
101                match self {
102                    $(
103                        Self::$type(v) => v.key(),
104                    )+
105                    Self::Unknown(v) => v.key(),
106                }
107            }
108        }
109
110        impl<'a, Octs> ParseSvcParamValue<'a, Octs>
111        for AllValues<Octs::Range<'a>>
112        where Octs: Octets + ?Sized {
113            fn parse_value(
114                key: SvcParamKey,
115                parser: &mut Parser<'a, Octs>,
116            ) -> Result<Option<Self>, ParseError> {
117                match key {
118                    $(
119                        $type::KEY => {
120                            $type::parse(
121                                parser
122                            ).map(|res| Some(Self::$type(res)))
123                        }
124                    )+
125                    _ => {
126                        UnknownSvcParam::parse_value(
127                            key, parser
128                        ).map(|res| res.map(Self::Unknown))
129                    }
130                }
131            }
132        }
133
134        impl<Octs: AsRef<[u8]>> ComposeSvcParamValue for AllValues<Octs> {
135            fn compose_len(&self) -> u16 {
136                match self {
137                    $(
138                        Self::$type(v) => v.compose_len(),
139                    )*
140                    Self::Unknown(v) => v.compose_len(),
141                }
142            }
143
144            fn compose_value<Target: OctetsBuilder + ?Sized>(
145                &self, target: &mut Target,
146            ) -> Result<(), Target::AppendError> {
147                match self {
148                    $(
149                        Self::$type(v) => v.compose_value(target),
150                    )*
151                    Self::Unknown(v) => v.compose_value(target),
152                }
153            }
154        }
155
156        //--- PartialEq and Eq
157        
158        impl<Octs, OtherOcts> PartialEq<AllValues<OtherOcts>>
159        for AllValues<Octs>
160        where
161            Octs: AsRef<[u8]>,
162            OtherOcts: AsRef<[u8]>,
163        {
164            fn eq(&self, other: &AllValues<OtherOcts>) -> bool {
165                match (self, other) {
166                    $(
167                        (AllValues::$type(left), AllValues::$type(right)) => {
168                            left.eq(right)
169                        }
170                    )*
171                    (AllValues::Unknown(left), AllValues::Unknown(right)) => {
172                        left.eq(right)
173                    }
174                    _ => false
175                }
176            }
177        }
178
179        impl<Octs: AsRef<[u8]>> Eq for AllValues<Octs> { }
180
181        //--- Hash
182
183        impl<Octs: AsRef<[u8]>> hash::Hash for AllValues<Octs> {
184            fn hash<H: hash::Hasher>(&self, state: &mut H) {
185                match self {
186                    $(
187                        Self::$type(value) => value.hash(state),
188                    )*
189                    Self::Unknown(value) => value.hash(state)
190                }
191            }
192        }
193
194        //--- Display and Debug
195
196        impl<Octs: Octets> fmt::Display for AllValues<Octs> {
197            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
198                match self {
199                    $(
200                        Self::$type(v) => v.fmt(f),
201                    )*
202                    Self::Unknown(v) => v.fmt(f),
203                }
204            }
205        }
206    }
207}
208
209values_enum! {
210    Mandatory<Octs>,
211    Alpn<Octs>,
212    NoDefaultAlpn,
213    Port,
214    Ech<Octs>,
215    Ipv4Hint<Octs>,
216    Ipv6Hint<Octs>,
217    DohPath<Octs>,
218}
219
220//============ Individual Value Types ========================================
221
222//------------ octets_wrapper ------------------------------------------------
223
224/// Defines the standard methods for a parameter type wrapping octets.
225macro_rules! octets_wrapper {
226    ( $(#[$attr:meta])* $name:ident => $key:ident) => {
227        $(#[$attr])*
228        #[derive(Debug, Clone)]
229        #[repr(transparent)]
230        pub struct $name<Octs: ?Sized>(Octs);
231
232        impl $name<()> {
233            /// The key for this type.
234            const KEY: SvcParamKey = SvcParamKey::$key;
235        }
236
237        impl<Octs> $name<Octs> {
238            /// Creates a new value from octets without checking.
239            ///
240            /// # Safety
241            ///
242            /// The caller has to ensure that `octets` contains a properly
243            /// formated value of at most 65,535 octets.
244            pub unsafe fn from_octets_unchecked(octets: Octs) -> Self {
245                $name(octets)
246            }
247        }
248
249        impl $name<[u8]> {
250            /// Creates a new value for a slice without checking.
251            ///
252            /// # Safety
253            ///
254            /// The caller has to ensure that `slice` contains a properly
255            /// formated value of at most 65,535 octets.
256            #[must_use]
257            pub unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
258                // SAFETY: Self has repr(transparent)
259                mem::transmute(slice)
260            }
261        }
262
263        impl<Octs: ?Sized> $name<Octs> {
264            /// Returns a reference to the underlying octets sequence.
265            pub fn as_octets(&self) -> &Octs {
266                &self.0
267            }
268
269            /// Returns a slice of the underlying octets sequence.
270            pub fn as_slice(&self) -> &[u8]
271            where Octs: AsRef<[u8]> {
272                self.0.as_ref()
273            }
274        }
275
276        //--- OctetsFrom
277
278        impl<O, OO> OctetsFrom<$name<O>> for $name<OO>
279        where
280            OO: OctetsFrom<O>,
281        {
282            type Error = OO::Error;
283
284            fn try_octets_from(
285                source: $name<O>,
286            ) -> Result<Self, Self::Error> {
287                Ok(unsafe {
288                    $name::from_octets_unchecked(
289                        OO::try_octets_from(source.0)?
290                    )
291                })
292            }
293        }
294
295        //--- AsRef
296
297        impl<Octs> AsRef<Octs> for $name<Octs> {
298            fn as_ref(&self) -> &Octs {
299                self.as_octets()
300            }
301        }
302
303        impl<Octs: AsRef<[u8]> + ?Sized> AsRef<[u8]> for $name<Octs> {
304            fn as_ref(&self) -> &[u8] {
305                self.as_slice()
306            }
307        }
308
309        //--- PartialEq and Eq
310
311        impl<Octs, OtherOcts> PartialEq<$name<OtherOcts>> for $name<Octs>
312        where
313            Octs: AsRef<[u8]>,
314            OtherOcts: AsRef<[u8]>,
315        {
316            fn eq(&self, other: &$name<OtherOcts>) -> bool {
317                self.as_slice().eq(other.as_slice())
318            }
319        }
320
321        impl<Octs: AsRef<[u8]>> Eq for $name<Octs> { }
322
323        //--- Hash
324
325        impl<Octs: AsRef<[u8]>> hash::Hash for $name<Octs> {
326            fn hash<H: hash::Hasher>(&self, state: &mut H) {
327                self.as_slice().hash(state)
328            }
329        }
330
331        //--- SvcParamValue et al.
332
333        impl<Octs: ?Sized> SvcParamValue for $name<Octs> {
334            fn key(&self) -> SvcParamKey {
335                $name::KEY
336            }
337        }
338
339        impl<'a, Octs> ParseSvcParamValue<'a, Octs> for $name<Octs::Range<'a>>
340        where Octs: Octets + ?Sized {
341            fn parse_value(
342                key: SvcParamKey,
343                parser: &mut Parser<'a, Octs>,
344            ) -> Result<Option<Self>, ParseError> {
345                if key == $name::KEY {
346                    Self::parse(parser).map(Some)
347                }
348                else {
349                    Ok(None)
350                }
351            }
352        }
353
354        impl<Octs: AsRef<[u8]> + ?Sized> ComposeSvcParamValue for $name<Octs> {
355            fn compose_len(&self) -> u16 {
356                u16::try_from(self.as_slice().len()).expect("long value")
357            }
358
359            fn compose_value<Target: OctetsBuilder + ?Sized>(
360                &self, target: &mut Target,
361            ) -> Result<(), Target::AppendError> {
362                target.append_slice(self.as_slice())
363            }
364        }
365    };
366
367    ($(#[$attr:meta])* $name:ident => $key:ident, $iter:ident) => {
368        octets_wrapper!( $(#[$attr])* $name => $key);
369
370        impl<Octs: AsRef<[u8]> + ?Sized> $name<Octs> {
371            /// Returns an iterator over the elements of the value.
372            pub fn iter(&self) -> $iter<'_, Octs> {
373                $iter {
374                    parser: Parser::from_ref(&self.0),
375                }
376            }
377        }
378
379        /// An iterator over the elements of the value.
380        pub struct $iter<'a, Octs: ?Sized> {
381            parser: Parser<'a, Octs>,
382        }
383    };
384}
385
386//------------ Mandatory -----------------------------------------------------
387
388octets_wrapper!(
389    /// The “mandatory” service parameter value.
390    ///
391    /// This value type lists the keys of the values that are considered
392    /// essential for interpretation of the service binding. A client must
393    /// understand all these keys in order be able to use a service bindings
394    /// record.
395    ///
396    /// A value of this type wraps an octets sequence that contains the
397    /// integer values of the keys in network byte order. You can create a
398    /// value of this type by providing an iterator over the keys to be
399    /// included to the [`from_keys`][Self::from_keys] function. You can
400    /// get an iterator over the keys in an existing value through the
401    /// [`iter`][Self::iter] method.
402    Mandatory => MANDATORY,
403    MandatoryIter
404);
405
406impl<Octs: AsRef<[u8]>> Mandatory<Octs> {
407    /// Creates a new mandatory value from an octets sequence.
408    ///
409    /// The function checks that the octets sequence contains a properly
410    /// encoded value of at most 65,535 octets. It does not check whether
411    /// there are any duplicates in the data.
412    pub fn from_octets(octets: Octs) -> Result<Self, ParseError> {
413        Mandatory::check_slice(octets.as_ref())?;
414        Ok(unsafe { Self::from_octets_unchecked(octets) })
415    }
416}
417
418impl Mandatory<[u8]> {
419    /// Creates a new mandatory value from an octets slice.
420    ///
421    /// The function checks that the octets slice contains a properly
422    /// encoded value of at most 65,535 octets. It does not check whether
423    /// there are any duplicates in the data.
424    pub fn from_slice(slice: &[u8]) -> Result<&Self, ParseError> {
425        Self::check_slice(slice)?;
426        Ok(unsafe { Self::from_slice_unchecked(slice) })
427    }
428
429    /// Checks that a slice contains a properly encoded mandatory value.
430    fn check_slice(slice: &[u8]) -> Result<(), ParseError> {
431        LongSvcParam::check_len(slice.len())?;
432        if slice.len() % usize::from(SvcParamKey::COMPOSE_LEN) != 0 {
433            return Err(ParseError::form_error("invalid mandatory parameter"))
434        }
435        Ok(())
436    }
437}
438
439impl<Octs: AsRef<[u8]>> Mandatory<Octs> {
440    /// Creates a new value from a list of keys.
441    ///
442    /// The created value will contain all the keys returned by the iterator
443    /// in the order provided. The function does not check for duplicates.
444    ///
445    /// Returns an error if the octets builder runs out of space or the
446    /// resulting value would be longer than 65,535 octets.
447    pub fn from_keys(
448        keys: impl Iterator<Item = SvcParamKey>
449    ) -> Result<Self, BuildValueError>
450    where
451        Octs: FromBuilder,
452        <Octs as FromBuilder>::Builder: EmptyBuilder
453    {
454        let mut octets = EmptyBuilder::empty();
455        for item in keys {
456            item.compose(&mut octets)?;
457        }
458        let octets = Octs::from_builder(octets);
459        if LongSvcParam::check_len(octets.as_ref().len()).is_err() {
460            return Err(BuildValueError::LongSvcParam)
461        }
462        Ok(unsafe { Self::from_octets_unchecked(octets) })
463    }
464}
465
466impl<Octs: AsRef<[u8]>> Mandatory<Octs> {
467    /// Parses a mandatory value from its wire format.
468    pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
469        parser: &mut Parser<'a, Src>,
470    ) -> Result<Self, ParseError> {
471        Self::from_octets(parser.parse_octets(parser.remaining())?)
472    }
473}
474
475//--- Iterator
476
477impl<Octs: Octets + ?Sized> Iterator for MandatoryIter<'_, Octs> {
478    type Item = SvcParamKey;
479
480    fn next(&mut self) -> Option<Self::Item> {
481        if self.parser.remaining() == 0 {
482            return None;
483        }
484        Some(
485            SvcParamKey::parse(
486                &mut self.parser
487            ).expect("invalid mandatory parameter")
488        )
489    }
490}
491
492//--- Display
493
494impl<Octs: Octets + ?Sized> fmt::Display for Mandatory<Octs> {
495    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
496        for (i, v) in self.iter().enumerate() {
497            if i == 0 {
498                write!(f, "mandatory={}", v)?;
499            } else {
500                write!(f, ",{}", v)?;
501            }
502        }
503        Ok(())
504    }
505}
506
507//--- Extend SvcParams and SvcParamsBuilder
508
509impl<Octs: Octets + ?Sized> SvcParams<Octs> {
510    /// Returns the content of the ‘mandatory’ value if present.
511    pub fn mandatory(&self) -> Option<Mandatory<Octs::Range<'_>>> {
512        self.first()
513    }
514}
515
516impl<Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>> SvcParamsBuilder<Octs> {
517    /// Adds a ‘mandatory’ value with the given keys.
518    ///
519    /// Returns an error if there already is a ‘mandatory’ value, `keys`
520    /// contains more values than fit into a service binding parameter value,
521    /// or the underlying octets builder runs out of space.
522    pub fn mandatory(
523        &mut self, keys: impl AsRef<[SvcParamKey]>,
524    ) -> Result<(), PushValueError> {
525        self.push_raw(
526            Mandatory::KEY,
527            u16::try_from(
528                keys.as_ref().len() * usize::from(SvcParamKey::COMPOSE_LEN)
529            ).map_err(|_| PushValueError::LongSvcParam)?,
530            |octs| {
531                keys.as_ref().iter().try_for_each(|item| item.compose(octs))
532            },
533        ).map_err(Into::into)
534    }
535}
536
537
538//------------ Alpn ----------------------------------------------------------
539
540octets_wrapper!(
541    /// The application layer protocols supported by the service endpoint.
542    ///
543    /// This value lists the protocol names supported by the service endpoint
544    /// described by the service binding’s target name and, if present, port.
545    /// The names are the same as used by Application Layer Protocol
546    /// Negotiation (ALPN) described in [RFC 7301]. Each scheme that uses
547    /// service bindings defines a set of default protocols that are quietly
548    /// added to this list unless the [`NoDefaultAlpn`] value is present as
549    /// well. For HTTPS, this default set consists of the `"http/1.1"`
550    /// protocol.
551    ///
552    /// The wire format of this value consists of those protocol names each
553    /// preceeded by a `u8` giving their length.
554    ///
555    /// The `iter` method produces an iterator over the individual protocol
556    /// names in the value.
557    Alpn => ALPN,
558    AlpnIter
559);
560
561impl<Octs: AsRef<[u8]>> Alpn<Octs> {
562    /// Creates an ALPN value from the underlying octets.
563    ///
564    /// The function ensures that `octets` is a correctly encoded ALPN
565    /// value. It does not, however, check that the protocol identifiers
566    /// are valid.
567    pub fn from_octets(octets: Octs) -> Result<Self, ParseError> {
568        Alpn::check_slice(octets.as_ref())?;
569        Ok(unsafe { Self::from_octets_unchecked(octets) })
570    }
571}
572
573impl Alpn<[u8]> {
574    /// Creates an ALPN value from an octets slice.
575    ///
576    /// The function ensures that `slice` is a correctly encoded ALPN
577    /// value. It does not, however, check that the protocol identifiers
578    /// are valid.
579    pub fn from_slice(slice: &[u8]) -> Result<&Self, ParseError> {
580        Self::check_slice(slice)?;
581        Ok(unsafe { Self::from_slice_unchecked(slice) })
582    }
583
584    /// Checks that a slice is a correctly encoded ALPN value.
585    ///
586    /// Checks for the length and that there is a sequence of elements each
587    /// preceeded by its length.
588    fn check_slice(slice: &[u8]) -> Result<(), ParseError> {
589        LongSvcParam::check_len(slice.len())?;
590        let mut parser = Parser::from_ref(slice);
591        while parser.remaining() > 0 {
592            let len = usize::from(u8::parse(&mut parser)?);
593            parser.advance(len)?;
594        }
595        Ok(())
596    }
597}
598
599impl<Octs: AsRef<[u8]>> Alpn<Octs> {
600    /// Parses an ALPN value from its wire format.
601    pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
602        parser: &mut Parser<'a, Src>,
603    ) -> Result<Self, ParseError> {
604        Self::from_octets(parser.parse_octets(parser.remaining())?)
605    }
606}
607
608//--- Iterator
609
610impl<'a, Octs: Octets + ?Sized> Iterator for AlpnIter<'a, Octs> {
611    type Item = Octs::Range<'a>;
612
613    fn next(&mut self) -> Option<Self::Item> {
614        if self.parser.remaining() == 0 {
615            return None
616        }
617        let len = usize::from(
618            u8::parse(&mut self.parser).expect("invalid alpn parameter")
619        );
620        Some(self.parser.parse_octets(len).expect("invalid alpn parameter"))
621    }
622}
623
624//--- Display
625
626impl<Octs: Octets + ?Sized> fmt::Display for Alpn<Octs> {
627    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
628        for (i, v) in self.iter().enumerate() {
629            if i == 0 {
630                f.write_str("alpn=")?;
631            } else {
632                f.write_str(",")?;
633            }
634            for ch in v.as_ref() {
635                f.write_char(*ch as char)?;
636            }
637        }
638        Ok(())
639    }
640}
641
642//--- Extend SvcParams and SvcParamsBuilder
643
644impl<Octs: Octets + ?Sized> SvcParams<Octs> {
645    /// Returns the content of the ‘mandatory’ value if present.
646    pub fn alpn(&self) -> Option<Alpn<Octs::Range<'_>>> {
647        self.first()
648    }
649}
650
651impl<Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>> SvcParamsBuilder<Octs> {
652    /// Adds an ALPN value to the parameters.
653    ///
654    /// The ALPN protocol names to be included in the value must be provided
655    /// as a slice of those names in order to be able to calculate
656    /// the length of the value up front.
657    ///
658    /// Returns an error if there already is an ALPN value, or if `protocols`
659    /// contains more values than fit into a service binding parameter value,
660    /// or the underlying octets builder runs out of space.
661    pub fn alpn(
662        &mut self, protocols: &[&[u8]],
663    ) -> Result<(), PushAlpnError> {
664        // Check that everything is a-okay.
665        let mut len = 0u16;
666        for proto in protocols.iter() {
667            let proto_len = u8::try_from(
668                proto.len()
669            ).map_err(|_| PushAlpnError::InvalidProtocol)?;
670            len = len.checked_add(
671                u16::from(proto_len) + u8::COMPOSE_LEN
672            ).ok_or(PushAlpnError::LongSvcParam)?;
673        }
674        self.push_raw(
675            Alpn::KEY,
676            len,
677            |octs| {
678                protocols.iter().try_for_each(|proto| {
679                    u8::try_from(
680                        proto.len()
681                    ).expect("long protocol").compose(octs)?;
682                    octs.append_slice(proto)
683                })
684            }
685        ).map_err(Into::into)
686    }
687}
688
689//------------ AlpnBuilder ---------------------------------------------------
690
691/// A builder for [`Alpn`] value content.
692#[derive(Clone, Debug)]
693pub struct AlpnBuilder<Target> {
694    /// The octets builder to append to.
695    target: Target,
696}
697
698impl<Target> AlpnBuilder<Target> {
699    /// Creates a new, empty ALPN value builder.
700    #[must_use]
701    pub fn empty() -> Self
702    where
703        Target: EmptyBuilder,
704    {
705        AlpnBuilder { target: Target::empty() }
706    }
707
708    /// Appends the given protocol name to the builder.
709    ///
710    /// Returns an error if the name is too long or the ALPN value would
711    /// become too long or the underlying octets builder runs out of space.
712    pub fn push(
713        &mut self, protocol: impl AsRef<[u8]>
714    ) -> Result<(), BuildAlpnError>
715    where Target: OctetsBuilder + AsRef<[u8]> {
716        let protocol = protocol.as_ref();
717        if protocol.is_empty() {
718            return Err(BuildAlpnError::InvalidProtocol)
719        }
720        let len = u8::try_from(
721            protocol.len()
722        ).map_err(|_| BuildAlpnError::InvalidProtocol)?;
723        LongSvcParam::check_len(
724            self.target.as_ref().len().checked_add(
725                protocol.len() + 1
726            ).expect("long Alpn value")
727        ).map_err(|_| BuildAlpnError::LongSvcParam)?;
728        len.compose(&mut self.target)?;
729        self.target.append_slice(
730            protocol
731        ).map_err(|_| BuildAlpnError::ShortBuf)
732    }
733
734    /// Converts the builder into an imutable ALPN value.
735    pub fn freeze(self) -> Alpn<Target::Octets>
736    where
737        Target: FreezeBuilder
738    {
739        unsafe { Alpn::from_octets_unchecked(self.target.freeze()) }
740    }
741}
742
743//------------ NoDefaultAlpn -------------------------------------------------
744
745/// A signal to not include the service’s default ALPNs in the ALPN set.
746///
747/// For each service that uses SVCB, a set of default [`Alpn`] protocols
748/// is defined. This set will be included even if they are not explicitely
749/// provided via the ALPN value. The no-default-alpn value can be used to
750/// signal that they should not be included.
751///
752/// This value is always empty.
753#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
754pub struct NoDefaultAlpn;
755
756impl NoDefaultAlpn {
757    /// The key for this type.
758    const KEY: SvcParamKey = SvcParamKey::NO_DEFAULT_ALPN;
759}
760
761impl NoDefaultAlpn {
762    /// Parses a no-default-alpn value from its wire-format.
763    pub fn parse<Src: Octets + ?Sized>(
764        _parser: &mut Parser<Src>,
765    ) -> Result<Self, ParseError> {
766        Ok(Self)
767    }
768}
769
770//--- SvcParamValue et al.
771
772impl SvcParamValue for NoDefaultAlpn {
773    fn key(&self) -> SvcParamKey {
774        Self::KEY
775    }
776}
777
778impl<'a, Octs: Octets + ?Sized> ParseSvcParamValue<'a, Octs> for NoDefaultAlpn {
779    fn parse_value(
780        key: SvcParamKey,
781        parser: &mut Parser<'a, Octs>,
782    ) -> Result<Option<Self>, ParseError> {
783        if key == Self::KEY {
784            Self::parse(parser).map(Some)
785        }
786        else {
787            Ok(None)
788        }
789    }
790}
791
792impl ComposeSvcParamValue for NoDefaultAlpn {
793    fn compose_len(&self) -> u16 {
794        0
795    }
796
797    fn compose_value<Target: OctetsBuilder + ?Sized>(
798        &self, _target: &mut Target,
799    ) -> Result<(), Target::AppendError> {
800        Ok(())
801    }
802}
803
804//--- Display
805
806impl fmt::Display for NoDefaultAlpn {
807    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
808        f.write_str("nodefaultalpn")
809    }
810}
811
812//--- Extend SvcParams and SvcParamsBuilder
813
814impl<Octs: Octets + ?Sized> SvcParams<Octs> {
815    /// Returns whether the [`NoDefaultAlpn`] value is present.
816    pub fn no_default_alpn(&self) -> bool {
817        self.first::<NoDefaultAlpn>().is_some()
818    }
819}
820
821impl<Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>> SvcParamsBuilder<Octs> {
822    /// Adds the [`NoDefaultAlpn`] value.
823    pub fn no_default_alpn(&mut self) -> Result<(), PushError> {
824        self.push(&NoDefaultAlpn)
825    }
826}
827
828//------------ Port ----------------------------------------------------------
829
830/// The TCP or UDP port to connect to when using an endpoint.
831///
832/// If this value is missing, the default port for the service should be used.
833#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
834pub struct Port(u16);
835
836impl Port {
837    /// The key for this type.
838    const KEY: SvcParamKey = SvcParamKey::PORT;
839}
840
841impl Port {
842    /// Creates a new port value with the given port.
843    #[must_use]
844    pub fn new(port: u16) -> Self {
845        Port(port)
846    }
847
848    /// Parses a port value from its wire-format.
849    pub fn parse<Src: Octets + ?Sized>(
850        parser: &mut Parser<Src>,
851    ) -> Result<Self, ParseError> {
852        u16::parse(parser).map(Port::new)
853    }
854
855    /// Returns the port of this value.
856    #[must_use]
857    pub fn port(self) -> u16 {
858        self.0
859    }
860}
861
862//--- SvcParamValue et al.
863
864impl SvcParamValue for Port {
865    fn key(&self) -> SvcParamKey {
866        Self::KEY
867    }
868}
869
870impl<'a, Octs: Octets + ?Sized> ParseSvcParamValue<'a, Octs> for Port {
871    fn parse_value(
872        key: SvcParamKey,
873        parser: &mut Parser<'a, Octs>,
874    ) -> Result<Option<Self>, ParseError> {
875        if key == Self::KEY {
876            Self::parse(parser).map(Some)
877        }
878        else {
879            Ok(None)
880        }
881    }
882}
883
884impl ComposeSvcParamValue for Port {
885    fn compose_len(&self) -> u16 {
886        u16::COMPOSE_LEN 
887    }
888
889    fn compose_value<Target: OctetsBuilder + ?Sized>(
890        &self, target: &mut Target,
891    ) -> Result<(), Target::AppendError> {
892        self.0.compose(target)
893    }
894}
895
896//--- Display
897
898impl fmt::Display for Port {
899    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
900        write!(f, "port={}", self.0)
901    }
902}
903
904//--- Extend SvcParams and SvcParamsBuilder
905
906impl<Octs: Octets + ?Sized> SvcParams<Octs> {
907    /// Returns the content of the port value if present.
908    pub fn port(&self) -> Option<Port> {
909        self.first()
910    }
911}
912
913impl<Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>> SvcParamsBuilder<Octs> {
914    /// Adds a port value with the given port number.
915    pub fn port(&mut self, port: u16) -> Result<(), PushError> {
916        self.push(&Port::new(port))
917    }
918}
919
920//------------ Ech -----------------------------------------------------------
921
922octets_wrapper!(
923    /// The Encrypted Client Hello (ECH) service parameter value.
924    ///
925    /// This value holds the information necessary to connect to the service
926    /// with Encrypted Client Hello. It contains all this information in
927    /// wire-format to be used with the TLS ECH extension currently in
928    /// development as Internet draft [draft-ietf-tls-esni].
929    ///
930    /// [draft-ietf-tls-esni]: https://datatracker.ietf.org/doc/draft-ietf-tls-esni/
931    Ech => ECH
932);
933
934impl<Octs: AsRef<[u8]>> Ech<Octs> {
935    /// Creates a new ECH value from the given content.
936    ///
937    /// Returns an error if the content is too long to fit into an SVCB
938    /// parameter value.
939    pub fn from_octets(octets: Octs) -> Result<Self, LongSvcParam> {
940        Ech::check_slice(octets.as_ref())?;
941        Ok(unsafe { Self::from_octets_unchecked(octets) })
942    }
943}
944
945impl Ech<[u8]> {
946    /// Creates a new ECH value from a slice of the content.
947    ///
948    /// Returns an error if the slice is too long to fit into an SVCB
949    /// parameter value.
950    pub fn from_slice(slice: &[u8]) -> Result<&Self, LongSvcParam> {
951        Self::check_slice(slice)?;
952        Ok(unsafe { Self::from_slice_unchecked(slice) })
953    }
954
955    /// Checks that a slice holds correct ECH content.
956    ///
957    /// This only checks the length.
958    fn check_slice(slice: &[u8]) -> Result<(), LongSvcParam> {
959        LongSvcParam::check_len(slice.len())?;
960        Ok(())
961    }
962}
963
964impl<Octs: AsRef<[u8]>> Ech<Octs> {
965    /// Parses an ECH value from its wire-format.
966    pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
967        parser: &mut Parser<'a, Src>,
968    ) -> Result<Self, ParseError> {
969        Self::from_octets(
970            parser.parse_octets(parser.remaining())?
971        ).map_err(Into::into)
972    }
973}
974
975//--- Display
976
977impl<Octs: AsRef<[u8]> + ?Sized> fmt::Display for Ech<Octs> {
978    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
979        if self.as_slice().is_empty() {
980            f.write_str("ech")
981        }
982        else {
983            f.write_str("ech=")?;
984            base64::display(self.as_slice(), f)
985        }
986    }
987}
988
989//--- Extend SvcParams and SvcParamsBuilder
990
991impl<Octs: Octets + ?Sized> SvcParams<Octs> {
992    /// Returns the content of the ECH value if present.
993    pub fn ech(&self) -> Option<Ech<Octs::Range<'_>>> {
994        self.first()
995    }
996}
997
998impl<Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>> SvcParamsBuilder<Octs> {
999    /// Adds a port value with the given port number.
1000    pub fn ech<Source: AsRef<[u8]> + ?Sized>(
1001        &mut self, ech: &Source
1002    ) -> Result<(), PushValueError> {
1003        self.push(Ech::from_slice(ech.as_ref())?).map_err(Into::into)
1004    }
1005}
1006
1007//------------ Ipv4Hint ------------------------------------------------------
1008
1009octets_wrapper!(
1010    /// The ‘ipv4hint’ service parameter value.
1011    ///
1012    /// This values provides a list of IPv4 addresses that the client may use
1013    /// to connect to the endpoint. The value is intended to speed up
1014    /// connecting but not to replace the A query to get the actual IPv4
1015    /// addresses of the endpoint. That is, the client can start an A query
1016    /// and at the same time connect to an IP address from the value. If the
1017    /// A query doesn’t return this IP address, it may want to start again
1018    /// with an address from the response.
1019    ///
1020    /// The type contains the value in its wire format which consists of the
1021    /// sequence of IPv4 addresses.
1022    Ipv4Hint => IPV4HINT,
1023    Ipv4HintIter
1024);
1025
1026impl<Octs: AsRef<[u8]>> Ipv4Hint<Octs> {
1027    /// Creates a new ipv4hint value from its content.
1028    ///
1029    /// The function returns an error if `octets` doesn’t contain a
1030    /// correctly encoded value or if it is longer than 65,535 octets.
1031    pub fn from_octets(octets: Octs) -> Result<Self, ParseError> {
1032        Ipv4Hint::check_slice(octets.as_ref())?;
1033        Ok(unsafe { Self::from_octets_unchecked(octets) })
1034    }
1035
1036    /// Creates a new value from a list of IPv4 addresses.
1037    ///
1038    /// The function will fail if the iterator returns more than 16,383
1039    /// addresses or if the octets builder to be used for building runs out
1040    /// of space.
1041    pub fn from_addrs(
1042        addrs: impl IntoIterator<Item = Ipv4Addr>
1043    ) -> Result<Self, BuildValueError>
1044    where
1045        Octs: FromBuilder,
1046        <Octs as FromBuilder>::Builder: EmptyBuilder
1047    {
1048        let mut octets = EmptyBuilder::empty();
1049        for item in addrs {
1050            item.compose(&mut octets)?;
1051        }
1052        let octets = Octs::from_builder(octets);
1053        if LongSvcParam::check_len(octets.as_ref().len()).is_err() {
1054            return Err(BuildValueError::LongSvcParam)
1055        }
1056        Ok(unsafe { Self::from_octets_unchecked(octets) })
1057    }
1058}
1059
1060impl Ipv4Hint<[u8]> {
1061    /// Creates a new ipv4hint value from a slice of its content.
1062    ///
1063    /// The function returns an error if `slice` doesn’t contain a
1064    /// correctly encoded value or if it is longer than 65,535 octets.
1065    pub fn from_slice(slice: &[u8]) -> Result<&Self, ParseError> {
1066        Self::check_slice(slice)?;
1067        Ok(unsafe { Self::from_slice_unchecked(slice) })
1068    }
1069
1070    /// Checks that a slice contains a correctly encoded ipv4hint value.
1071    ///
1072    /// It checks that the length is divisible by 4 and not longer than
1073    /// 65,535 octets.
1074    fn check_slice(slice: &[u8]) -> Result<(), ParseError> {
1075        LongSvcParam::check_len(slice.len())?;
1076        if slice.len() % usize::from(Ipv4Addr::COMPOSE_LEN) != 0 {
1077            return Err(ParseError::form_error("invalid ipv4hint parameter"))
1078        }
1079        Ok(())
1080    }
1081}
1082
1083impl<Octs: AsRef<[u8]>> Ipv4Hint<Octs> {
1084    /// Parses an ipv4hint value from its wire format.
1085    pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
1086        parser: &mut Parser<'a, Src>,
1087    ) -> Result<Self, ParseError> {
1088        Self::from_octets(parser.parse_octets(parser.remaining())?)
1089    }
1090}
1091
1092impl<Octs: Octets + ?Sized> Iterator for Ipv4HintIter<'_, Octs> {
1093    type Item = Ipv4Addr;
1094
1095    fn next(&mut self) -> Option<Self::Item> {
1096        if self.parser.remaining() == 0 {
1097            return None;
1098        }
1099        Some(
1100            Ipv4Addr::parse(
1101                &mut self.parser
1102            ).expect("invalid ipv4hint parameter")
1103        )
1104    }
1105}
1106
1107impl<Octs: Octets + ?Sized> fmt::Display for Ipv4Hint<Octs> {
1108    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1109        for (i, v) in self.iter().enumerate() {
1110            if i == 0 {
1111                write!(f, "ipv4hint={}", v)?;
1112            } else {
1113                write!(f, ",{}", v)?;
1114            }
1115        }
1116        Ok(())
1117    }
1118}
1119
1120//--- Extend SvcParams and SvcParamsBuilder
1121
1122impl<Octs: Octets + ?Sized> SvcParams<Octs> {
1123    /// Returns the content of the ‘ipv4hint’ value if present.
1124    pub fn ipv4hint(&self) -> Option<Ipv4Hint<Octs::Range<'_>>> {
1125        self.first()
1126    }
1127}
1128
1129impl<Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>> SvcParamsBuilder<Octs> {
1130    /// Adds an ‘ipv4hint’ value with the given addresses.
1131    ///
1132    /// Returns an error if there already is an ‘ipv4hint’ value, `addrs`
1133    /// contains more values than fit into a service binding parameter value,
1134    /// or the underlying octets builder runs out of space.
1135    pub fn ipv4hint(
1136        &mut self, addrs: impl AsRef<[Ipv4Addr]>,
1137    ) -> Result<(), PushValueError> {
1138        self.push_raw(
1139            Ipv4Hint::KEY,
1140            u16::try_from(
1141                addrs.as_ref().len() * usize::from(Ipv4Addr::COMPOSE_LEN)
1142            ).map_err(|_| PushValueError::LongSvcParam)?,
1143            |octs| {
1144                addrs.as_ref().iter().try_for_each(|item| item.compose(octs))
1145            },
1146        ).map_err(Into::into)
1147    }
1148}
1149
1150//------------ Ipv6Hint ------------------------------------------------------
1151
1152octets_wrapper!(
1153    /// The ‘ipv6hint’ service parameter value.
1154    ///
1155    /// This values provides a list of IPv6 addresses that the client may use
1156    /// to connect to the endpoint. The value is intended to speed up
1157    /// connecting but not to replace the AAAA query to get the actual IPv6
1158    /// addresses of the endpoint. That is, the client can start an AAAA query
1159    /// and at the same time connect to an IP address from the value. If the
1160    /// AAAA query doesn’t return this IP address, it may want to start again
1161    /// with an address from the response.
1162    ///
1163    /// The type contains the value in its wire format which consists of the
1164    /// sequence of IPv6 addresses.
1165    Ipv6Hint => IPV6HINT,
1166    Ipv6HintIter
1167);
1168
1169impl<Octs: AsRef<[u8]>> Ipv6Hint<Octs> {
1170    /// Creates a new ipv6hint value from its content.
1171    ///
1172    /// The function returns an error if `octets` doesn’t contain a
1173    /// correctly encoded value or if it is longer than 65,535 octets.
1174    pub fn from_octets(octets: Octs) -> Result<Self, ParseError> {
1175        Ipv6Hint::check_slice(octets.as_ref())?;
1176        Ok(unsafe { Self::from_octets_unchecked(octets) })
1177    }
1178
1179    /// Creates a new value from a list of IPv6 addresses.
1180    ///
1181    /// The function will fail if the iterator returns more than 16,383
1182    /// addresses or if the octets builder to be used for building runs out
1183    /// of space.
1184    pub fn from_addrs(
1185        addrs: impl IntoIterator<Item = Ipv6Addr>
1186    ) -> Result<Self, BuildValueError>
1187    where
1188        Octs: FromBuilder,
1189        <Octs as FromBuilder>::Builder: EmptyBuilder
1190    {
1191        let mut octets = EmptyBuilder::empty();
1192        for item in addrs {
1193            item.compose(&mut octets)?;
1194        }
1195        let octets = Octs::from_builder(octets);
1196        if LongSvcParam::check_len(octets.as_ref().len()).is_err() {
1197            return Err(BuildValueError::LongSvcParam)
1198        }
1199        Ok(unsafe { Self::from_octets_unchecked(octets) })
1200    }
1201}
1202
1203impl Ipv6Hint<[u8]> {
1204    /// Creates a new ‘ipv6hint’ value from a slice of its content.
1205    ///
1206    /// The function returns an error if `slice` doesn’t contain a
1207    /// correctly encoded value or if it is longer than 65,535 octets.
1208    pub fn from_slice(slice: &[u8]) -> Result<&Self, ParseError> {
1209        Self::check_slice(slice)?;
1210        Ok(unsafe { Self::from_slice_unchecked(slice) })
1211    }
1212
1213    /// Checks that a slice contains a correctly encoded ipv6hint value.
1214    ///
1215    /// It checks that the length is divisible by16 and not longer than
1216    /// 65,535 octets.
1217    fn check_slice(slice: &[u8]) -> Result<(), ParseError> {
1218        LongSvcParam::check_len(slice.len())?;
1219        if slice.len() % usize::from(Ipv6Addr::COMPOSE_LEN) != 0 {
1220            return Err(ParseError::form_error("invalid ipv6hint parameter"))
1221        }
1222        Ok(())
1223    }
1224}
1225
1226impl<Octs: AsRef<[u8]>> Ipv6Hint<Octs> {
1227    /// Parses an ‘ipv6hint’ value from its wire format.
1228    pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
1229        parser: &mut Parser<'a, Src>,
1230    ) -> Result<Self, ParseError> {
1231        Self::from_octets(parser.parse_octets(parser.remaining())?)
1232    }
1233}
1234
1235//--- Iterator
1236
1237impl<Octs: Octets + ?Sized> Iterator for Ipv6HintIter<'_, Octs> {
1238    type Item = Ipv6Addr;
1239
1240    fn next(&mut self) -> Option<Self::Item> {
1241        if self.parser.remaining() == 0 {
1242            return None;
1243        }
1244        Some(
1245            Ipv6Addr::parse(
1246                &mut self.parser
1247            ).expect("invalid ipv6hint parameter")
1248        )
1249    }
1250}
1251
1252//--- Display
1253
1254impl<Octs: Octets + ?Sized> fmt::Display for Ipv6Hint<Octs> {
1255    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1256        for (i, v) in self.iter().enumerate() {
1257            if i == 0 {
1258                write!(f, "ipv6hint={}", v)?;
1259            } else {
1260                write!(f, ",{}", v)?;
1261            }
1262        }
1263        Ok(())
1264    }
1265}
1266
1267//--- Extend SvcParams and SvcParamsBuilder
1268
1269impl<Octs: Octets + ?Sized> SvcParams<Octs> {
1270    /// Returns the content of the ‘ipv6hint’ value if present.
1271    pub fn ipv6hint(&self) -> Option<Ipv6Hint<Octs::Range<'_>>> {
1272        self.first()
1273    }
1274}
1275
1276impl<Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>> SvcParamsBuilder<Octs> {
1277    /// Adds an ‘ipv6hint’ value with the given addresses.
1278    ///
1279    /// Returns an error if there already is an ‘ipv6hint’ value, `addrs`
1280    /// contains more values than fit into a service binding parameter value,
1281    /// or the underlying octets builder runs out of space.
1282    pub fn ipv6hint(
1283        &mut self, addrs: impl AsRef<[Ipv6Addr]>,
1284    ) -> Result<(), PushValueError> {
1285        self.push_raw(
1286            Ipv6Hint::KEY,
1287            u16::try_from(
1288                addrs.as_ref().len() * usize::from(Ipv6Addr::COMPOSE_LEN)
1289            ).map_err(|_| PushValueError::LongSvcParam)?,
1290            |octs| {
1291                addrs.as_ref().iter().try_for_each(|item| item.compose(octs))
1292            },
1293        ).map_err(Into::into)
1294    }
1295}
1296
1297//------------ DohPath -------------------------------------------------------
1298
1299octets_wrapper!(
1300    /// The ‘dohpath’ service parameter value.
1301    ///
1302    /// This value includes the URI template to be used when directing
1303    /// DNS-over-HTTPS (DoH) queries to a service. This template is encoded
1304    /// as UTF-8. URI templates are described in
1305    /// [RFC 6570](https://www.rfc-editor.org/rfc/rfc6570)
1306    ///
1307    /// This value type is described as part of the specification for
1308    /// using service bindings with DNS-over-HTTPS, currently
1309    /// [draft-ietf-add-svcb-dns](https://datatracker.ietf.org/doc/html/draft-ietf-add-svcb-dns).
1310    DohPath => DOHPATH
1311);
1312
1313impl<Octs: AsRef<[u8]>> DohPath<Octs> {
1314    /// Creates a ‘dohpath’ value from its content.
1315    ///
1316    /// Returns an error if `octets` is longer than 65,535 bytes.
1317    pub fn from_octets(octets: Octs) -> Result<Self, LongSvcParam> {
1318        DohPath::check_slice(octets.as_ref())?;
1319        Ok(unsafe { Self::from_octets_unchecked(octets) })
1320    }
1321}
1322
1323impl DohPath<[u8]> {
1324    /// Creates a ‘dohpath’ value from a slice of its content.
1325    ///
1326    /// Returns an error if `slice` is longer than 65,535 bytes.
1327    pub fn from_slice(slice: &[u8]) -> Result<&Self, LongSvcParam> {
1328        Self::check_slice(slice)?;
1329        Ok(unsafe { Self::from_slice_unchecked(slice) })
1330    }
1331
1332    /// Checkes that a slice is acceptable as ‘dohpath’ content.
1333    ///
1334    /// Only checks that the slice isn’t too long.
1335    fn check_slice(slice: &[u8]) -> Result<(), LongSvcParam> {
1336        LongSvcParam::check_len(slice.len())?;
1337        Ok(())
1338    }
1339}
1340
1341impl<Octs: AsRef<[u8]>> DohPath<Octs> {
1342    /// Parses a ‘dohpath’ value from its wire format.
1343    pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
1344        parser: &mut Parser<'a, Src>,
1345    ) -> Result<Self, ParseError> {
1346        Self::from_octets(
1347            parser.parse_octets(parser.remaining())?
1348        ).map_err(Into::into)
1349    }
1350}
1351
1352//--- TryFrom and FromStr
1353
1354impl<Octs: AsRef<[u8]>> TryFrom<Str<Octs>> for DohPath<Octs> {
1355    type Error = LongSvcParam;
1356
1357    fn try_from(src: Str<Octs>) -> Result<Self, Self::Error> {
1358        Self::from_octets(src.into_octets())
1359    }
1360}
1361
1362impl<Octs> FromStr for DohPath<Octs>
1363where
1364    Octs: FromBuilder,
1365    <Octs as FromBuilder>::Builder:
1366        EmptyBuilder
1367        + FreezeBuilder<Octets = Octs>
1368{
1369    type Err = BuildValueError;
1370
1371    fn from_str(s: &str) -> Result<Self, Self::Err> {
1372        DohPath::check_slice(s.as_bytes())?;
1373        let mut res: <Octs as FromBuilder>::Builder = EmptyBuilder::empty();
1374        res.append_slice(s.as_bytes()).map_err(Into::into)?;
1375        Ok(unsafe { Self::from_octets_unchecked(res.freeze()) })
1376    }
1377}
1378
1379//--- Display
1380
1381impl<Octs: AsRef<[u8]> + ?Sized> fmt::Display for DohPath<Octs> {
1382    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1383        if self.as_slice().is_empty() {
1384            f.write_str("dohpath")
1385        }
1386        else {
1387            f.write_str("dohpath=")?;
1388            let mut s = self.as_slice();
1389
1390            // XXX Should this be moved to base::utils?
1391            while !s.is_empty() {
1392                match str::from_utf8(s) {
1393                    Ok(s) => return f.write_str(s),
1394                    Err(err) => {
1395                        let end = err.valid_up_to();
1396                        if end > 0 {
1397                            f.write_str(unsafe {
1398                                str::from_utf8_unchecked(&s[..end])
1399                            })?;
1400                        }
1401                        f.write_str("\u{FFFD}")?;
1402                        match err.error_len() {
1403                            Some(len) => {
1404                                s = &s[end + len..];
1405                            }
1406                            None => break,
1407                        }
1408                    }
1409                }
1410            }
1411            Ok(())
1412        }
1413    }
1414}
1415
1416//--- Extend SvcParams and SvcParamsBuilder
1417
1418impl<Octs: Octets + ?Sized> SvcParams<Octs> {
1419    /// Returns the content of the ‘dohpath’ value if present.
1420    pub fn dohpath(&self) -> Option<DohPath<Octs::Range<'_>>> {
1421        self.first()
1422    }
1423}
1424
1425impl<Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>> SvcParamsBuilder<Octs> {
1426    /// Adds a ‘dohpath’ value with the URI template.
1427    ///
1428    /// Returns an error if there already is a ‘dohpath’ value, `template`
1429    /// is too long to fit in a service binding parameter value,
1430    /// or the underlying octets builder runs out of space.
1431    pub fn dohpath(
1432        &mut self, template: &str
1433    ) -> Result<(), PushValueError> {
1434        self.push_raw(
1435            DohPath::KEY,
1436            u16::try_from(
1437                template.len()
1438            ).map_err(|_| PushValueError::LongSvcParam)?,
1439            |octs| {
1440                octs.append_slice(template.as_bytes())
1441            },
1442        ).map_err(Into::into)
1443    }
1444}
1445
1446//============ BuildValueError ===============================================
1447
1448//------------ BuildValueError -----------------------------------------------
1449
1450/// An error happened while constructing an SVCB value.
1451#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1452pub enum BuildValueError {
1453    /// The value would exceed the allow length of a value.
1454    LongSvcParam,
1455
1456    /// The underlying octets builder ran out of buffer space.
1457    ShortBuf,
1458}
1459
1460impl From<LongSvcParam> for BuildValueError {
1461    fn from(_: LongSvcParam) -> Self {
1462        Self::LongSvcParam
1463    }
1464}
1465
1466impl<T: Into<ShortBuf>> From<T> for BuildValueError {
1467    fn from(_: T) -> Self {
1468        Self::ShortBuf
1469    }
1470}
1471
1472//--- Display and Error
1473
1474impl fmt::Display for BuildValueError {
1475    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1476        match self {
1477            Self::LongSvcParam => f.write_str("long SVCB value"),
1478            Self::ShortBuf => ShortBuf.fmt(f)
1479        }
1480    }
1481}
1482
1483#[cfg(feature = "std")]
1484impl std::error::Error for BuildValueError {}
1485
1486//------------ PushValueError ------------------------------------------------
1487
1488/// An error happened while constructing an SVCB value.
1489#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1490pub enum PushValueError {
1491    /// A value with this key is already present.
1492    DuplicateKey,
1493
1494    /// The value would exceed the allow length of a value.
1495    LongSvcParam,
1496
1497    /// The underlying octets builder ran out of buffer space.
1498    ShortBuf,
1499}
1500
1501impl From<LongSvcParam> for PushValueError {
1502    fn from(_: LongSvcParam) -> Self {
1503            Self::LongSvcParam
1504    }
1505}
1506
1507impl From<PushError> for PushValueError {
1508    fn from(src: PushError) -> Self {
1509        match src {
1510            PushError::DuplicateKey => Self::DuplicateKey,
1511            PushError::ShortBuf => Self::ShortBuf,
1512        }
1513    }
1514}
1515
1516impl From<BuildValueError> for PushValueError {
1517    fn from(src: BuildValueError) -> Self {
1518        match src {
1519            BuildValueError::LongSvcParam => Self::LongSvcParam,
1520            BuildValueError::ShortBuf => Self::ShortBuf,
1521        }
1522    }
1523}
1524
1525impl<T: Into<ShortBuf>> From<T> for PushValueError {
1526    fn from(_: T) -> Self {
1527        Self::ShortBuf
1528    }
1529}
1530
1531//--- Display and Error
1532
1533impl fmt::Display for PushValueError {
1534    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1535        match self {
1536            Self::DuplicateKey => f.write_str("duplicate key"),
1537            Self::LongSvcParam => f.write_str("long SVCB value"),
1538            Self::ShortBuf => ShortBuf.fmt(f)
1539        }
1540    }
1541}
1542
1543#[cfg(feature = "std")]
1544impl std::error::Error for PushValueError {}
1545
1546//------------ BuildAlpnError ------------------------------------------------
1547
1548/// An error happened while constructing an SVCB value.
1549#[derive(Clone, Copy, Debug)]
1550pub enum BuildAlpnError {
1551    /// The protocol value is not valid.
1552    ///
1553    /// It was either empty or longer than 255 octets.
1554    InvalidProtocol,
1555
1556    /// The value would exceed the allow length of a value.
1557    LongSvcParam,
1558
1559    /// The underlying octets builder ran out of buffer space.
1560    ShortBuf,
1561}
1562
1563impl<T: Into<ShortBuf>> From<T> for BuildAlpnError {
1564    fn from(_: T) -> Self {
1565        Self::ShortBuf
1566    }
1567}
1568
1569//--- Display and Error
1570
1571impl fmt::Display for BuildAlpnError {
1572    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1573        match self {
1574            Self::InvalidProtocol => f.write_str("invalid ALPN protocol"),
1575            Self::LongSvcParam => f.write_str("long SVCB value"),
1576            Self::ShortBuf => ShortBuf.fmt(f)
1577        }
1578    }
1579}
1580
1581#[cfg(feature = "std")]
1582impl std::error::Error for BuildAlpnError {}
1583
1584//------------ PushAlpnError -------------------------------------------------
1585
1586/// An error happened while constructing an SVCB value.
1587#[derive(Clone, Copy, Debug)]
1588pub enum PushAlpnError {
1589    /// A value with this key is already present.
1590    DuplicateKey,
1591
1592    /// The protocol value is not valid.
1593    ///
1594    /// It was either empty or longer than 255 octets.
1595    InvalidProtocol,
1596
1597    /// The value would exceed the allow length of a value.
1598    LongSvcParam,
1599
1600    /// The underlying octets builder ran out of buffer space.
1601    ShortBuf,
1602}
1603
1604impl From<PushError> for PushAlpnError {
1605    fn from(src: PushError) -> Self {
1606        match src {
1607            PushError::DuplicateKey => Self::DuplicateKey,
1608            PushError::ShortBuf => Self::ShortBuf,
1609        }
1610    }
1611}
1612
1613impl From<BuildValueError> for PushAlpnError {
1614    fn from(src: BuildValueError) -> Self {
1615        match src {
1616            BuildValueError::LongSvcParam => Self::LongSvcParam,
1617            BuildValueError::ShortBuf => Self::ShortBuf,
1618        }
1619    }
1620}
1621
1622impl<T: Into<ShortBuf>> From<T> for PushAlpnError {
1623    fn from(_: T) -> Self {
1624        Self::ShortBuf
1625    }
1626}
1627
1628//--- Display and Error
1629
1630impl fmt::Display for PushAlpnError {
1631    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1632        match self {
1633            Self::DuplicateKey => f.write_str("duplicate key"),
1634            Self::InvalidProtocol => f.write_str("invalid ALPN protocol"),
1635            Self::LongSvcParam => f.write_str("long SVCB value"),
1636            Self::ShortBuf => ShortBuf.fmt(f)
1637        }
1638    }
1639}
1640
1641#[cfg(feature = "std")]
1642impl std::error::Error for PushAlpnError {}
1643
1644//============ Tests =========================================================
1645
1646#[cfg(test)]
1647mod test {
1648    use super::*;
1649
1650    #[test]
1651    fn test_vectors_alpn_escape() {
1652        let mut parser = Parser::from_ref(b"\
1653            \x08\
1654            \x66\x5c\x6f\x6f\x2c\x62\x61\x72\
1655            \x02\
1656            \x68\x32\
1657        ".as_ref());
1658        let alpn = Alpn::parse(&mut parser).unwrap();
1659        assert_eq!(parser.remaining(), 0);
1660        assert!(
1661            alpn.iter().eq(
1662                [
1663                    br"f\oo,bar".as_ref(),
1664                    b"h2".as_ref(),
1665                ]
1666            )
1667        );
1668    }
1669
1670}
1671