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