domain/rdata/svcb/
value.rs

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