1#![allow(clippy::needless_maybe_sized)]
9
10use super::value::AllValues;
11use crate::base::cmp::CanonicalOrd;
12use crate::base::iana::SvcParamKey;
13use crate::base::scan::Symbol;
14use crate::base::wire::{Compose, Parse, ParseError};
15use crate::base::zonefile_fmt::{self, Formatter, ZonefileFmt};
16use core::cmp::Ordering;
17use core::marker::PhantomData;
18use core::{cmp, fmt, hash, mem};
19use octseq::builder::{EmptyBuilder, FromBuilder, OctetsBuilder, ShortBuf};
20use octseq::octets::{Octets, OctetsFrom, OctetsInto};
21use octseq::parse::{Parser, ShortInput};
22
23#[derive(Clone, Default)]
72#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
73#[repr(transparent)]
74pub struct SvcParams<Octs: ?Sized> {
75 #[cfg_attr(
76 feature = "serde",
77 serde(
78 serialize_with = "octseq::serde::SerializeOctets::serialize_octets",
79 deserialize_with = "octseq::serde::DeserializeOctets::deserialize_octets",
80 bound(
81 serialize = "Octs: octseq::serde::SerializeOctets",
82 deserialize = "Octs: octseq::serde::DeserializeOctets<'de> + Sized",
83 )
84 )
85 )]
86 octets: Octs,
87}
88
89impl<Octs> SvcParams<Octs> {
90 pub fn from_octets(octets: Octs) -> Result<Self, SvcParamsError>
97 where
98 Octs: AsRef<[u8]>,
99 {
100 SvcParams::check_slice(octets.as_ref())?;
101 Ok(unsafe { Self::from_octets_unchecked(octets) })
102 }
103
104 pub unsafe fn from_octets_unchecked(octets: Octs) -> Self {
111 SvcParams { octets }
112 }
113}
114
115impl SvcParams<[u8]> {
116 pub fn from_slice(slice: &[u8]) -> Result<&Self, SvcParamsError> {
123 SvcParams::check_slice(slice)?;
124 Ok(unsafe { Self::from_slice_unchecked(slice) })
125 }
126
127 #[must_use]
134 pub unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
135 mem::transmute(slice)
137 }
138
139 fn check_slice(slice: &[u8]) -> Result<(), SvcParamsError> {
141 let mut parser = Parser::from_ref(slice);
142 let mut last_key = None;
143 while parser.remaining() > 0 {
144 let key = u16::parse(&mut parser)?;
145 if let Some(last_key) = last_key {
146 if key <= last_key {
147 Err(ParseError::form_error("unordered SVCB params"))?;
148 }
149 }
150 last_key = Some(key);
151 let len = u16::parse(&mut parser)?;
152 parser.advance(len.into())?;
153 }
154 Ok(())
155 }
156}
157
158impl<Octs> SvcParams<Octs> {
159 pub fn from_values<F>(op: F) -> Result<Self, PushError>
165 where
166 Octs: FromBuilder,
167 <Octs as FromBuilder>::Builder:
168 AsRef<[u8]> + OctetsBuilder + EmptyBuilder,
169 F: FnOnce(
170 &mut SvcParamsBuilder<<Octs as FromBuilder>::Builder>,
171 ) -> Result<(), PushError>,
172 {
173 let mut res = SvcParamsBuilder::empty();
174 op(&mut res)?;
175 res.freeze().map_err(Into::into)
176 }
177}
178
179impl<Octs: AsRef<[u8]>> SvcParams<Octs> {
180 pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized + 'a>(
182 parser: &mut Parser<'a, Src>,
183 ) -> Result<Self, ParseError> {
184 Self::from_octets(parser.parse_octets(parser.remaining())?)
185 .map_err(Into::into)
186 }
187}
188
189impl<Octs: ?Sized> SvcParams<Octs> {
190 pub fn as_octets(&self) -> &Octs {
192 &self.octets
193 }
194}
195
196impl<Octs: AsRef<[u8]> + ?Sized> SvcParams<Octs> {
197 pub fn as_slice(&self) -> &[u8] {
199 self.octets.as_ref()
200 }
201
202 pub fn for_slice(&self) -> &SvcParams<[u8]> {
204 unsafe { SvcParams::from_slice_unchecked(self.octets.as_ref()) }
205 }
206
207 pub fn len(&self) -> usize {
209 self.octets.as_ref().len()
210 }
211
212 pub fn is_empty(&self) -> bool {
214 self.octets.as_ref().is_empty()
215 }
216
217 pub fn first<'s, Value>(&'s self) -> Option<Value>
227 where
228 Octs: Octets,
229 Value: ParseSvcParamValue<'s, Octs>,
230 {
231 self.iter::<Value>().next().and_then(Result::ok)
232 }
233
234 pub fn iter<Value>(&self) -> ValueIter<'_, Octs, Value> {
236 ValueIter::new(self.as_octets())
237 }
238
239 pub fn iter_all(&self) -> ValueIter<'_, Octs, AllValues<Octs>>
241 where
242 Octs: Sized,
243 {
244 self.iter()
245 }
246
247 pub fn iter_raw(
249 &self,
250 ) -> impl Iterator<Item = UnknownSvcParam<Octs::Range<'_>>>
251 where
252 Octs: Octets + Sized,
253 {
254 self.iter()
255 .map(|item| item.expect("parsing cannot have failed"))
256 }
257
258 pub fn compose<Target: OctetsBuilder + ?Sized>(
260 &self,
261 target: &mut Target,
262 ) -> Result<(), Target::AppendError> {
263 target.append_slice(self.octets.as_ref())
264 }
265}
266
267impl<SrcOcts, Octs> OctetsFrom<SvcParams<SrcOcts>> for SvcParams<Octs>
270where
271 Octs: OctetsFrom<SrcOcts>,
272{
273 type Error = Octs::Error;
274
275 fn try_octets_from(src: SvcParams<SrcOcts>) -> Result<Self, Self::Error> {
276 Ok(unsafe {
277 SvcParams::from_octets_unchecked(src.octets.try_octets_into()?)
278 })
279 }
280}
281
282impl<Octs, OtherOcts> PartialEq<SvcParams<OtherOcts>> for SvcParams<Octs>
285where
286 Octs: AsRef<[u8]> + ?Sized,
287 OtherOcts: AsRef<[u8]> + ?Sized,
288{
289 fn eq(&self, other: &SvcParams<OtherOcts>) -> bool {
290 self.as_slice().eq(other.as_slice())
291 }
292}
293
294impl<Octs: AsRef<[u8]> + ?Sized> Eq for SvcParams<Octs> {}
295
296impl<Octs: AsRef<[u8]> + ?Sized> hash::Hash for SvcParams<Octs> {
299 fn hash<H: hash::Hasher>(&self, state: &mut H) {
300 self.as_slice().hash(state)
301 }
302}
303
304impl<Octs, OtherOcts> PartialOrd<SvcParams<OtherOcts>> for SvcParams<Octs>
307where
308 Octs: AsRef<[u8]> + ?Sized,
309 OtherOcts: AsRef<[u8]> + ?Sized,
310{
311 fn partial_cmp(
312 &self,
313 other: &SvcParams<OtherOcts>,
314 ) -> Option<cmp::Ordering> {
315 self.as_slice().partial_cmp(other.as_slice())
316 }
317}
318
319impl<Octs: AsRef<[u8]> + ?Sized> Ord for SvcParams<Octs> {
320 fn cmp(&self, other: &Self) -> cmp::Ordering {
321 self.as_slice().cmp(other.as_slice())
322 }
323}
324
325impl<Octs, OtherOcts> CanonicalOrd<SvcParams<OtherOcts>> for SvcParams<Octs>
326where
327 Octs: AsRef<[u8]> + ?Sized,
328 OtherOcts: AsRef<[u8]> + ?Sized,
329{
330 fn canonical_cmp(&self, other: &SvcParams<OtherOcts>) -> cmp::Ordering {
331 self.as_slice().cmp(other.as_slice())
332 }
333}
334
335impl<Octs: Octets + ?Sized> fmt::Display for SvcParams<Octs> {
338 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
339 let mut parser = Parser::from_ref(self.as_slice());
340 let mut first = true;
341 while parser.remaining() > 0 {
342 let key =
343 SvcParamKey::parse(&mut parser).expect("invalid SvcbParam");
344 let len = usize::from(
345 u16::parse(&mut parser).expect("invalid SvcParam"),
346 );
347 let mut parser =
348 parser.parse_parser(len).expect("invalid SvcParam");
349 if first {
350 first = false;
351 } else {
352 f.write_str(" ")?;
353 }
354 write!(
355 f,
356 "{}",
357 super::value::AllValues::parse_any(key, &mut parser)
358 )?;
359 }
360 Ok(())
361 }
362}
363
364impl<Octs: Octets + ?Sized> fmt::Debug for SvcParams<Octs> {
365 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
366 f.debug_tuple("SvcParams")
367 .field(&format_args!("{}", self))
368 .finish()
369 }
370}
371
372impl<Octs: Octets + ?Sized> ZonefileFmt for SvcParams<Octs> {
375 fn fmt(&self, p: &mut impl Formatter) -> zonefile_fmt::Result {
376 p.block(|p| {
377 let mut parser = Parser::from_ref(self.as_slice());
378 while parser.remaining() > 0 {
379 let key = SvcParamKey::parse(&mut parser)
380 .expect("invalid SvcbParam");
381 let len = usize::from(
382 u16::parse(&mut parser).expect("invalid SvcParam"),
383 );
384 let mut parser =
385 parser.parse_parser(len).expect("invalid SvcParam");
386 p.write_token(super::value::AllValues::parse_any(
387 key,
388 &mut parser,
389 ))?;
390 }
391 Ok(())
392 })
393 }
394}
395
396#[derive(Clone, Debug)]
403pub struct ValueIter<'a, Octs: ?Sized, Value> {
404 parser: Parser<'a, Octs>,
405 marker: PhantomData<Value>,
406}
407
408impl<'a, Octs: AsRef<[u8]> + ?Sized, Value> ValueIter<'a, Octs, Value> {
409 fn new(octets: &'a Octs) -> Self {
410 ValueIter {
411 parser: Parser::from_ref(octets),
412 marker: PhantomData,
413 }
414 }
415
416 fn next_step(&mut self) -> Result<Option<Value>, ParseError>
417 where
418 Octs: Octets,
419 Value: ParseSvcParamValue<'a, Octs>,
420 {
421 let key = SvcParamKey::parse(&mut self.parser)?;
422 let len = usize::from(u16::parse(&mut self.parser)?);
423 let mut parser = self.parser.parse_parser(len)?;
424 let res = Value::parse_value(key, &mut parser)?;
425 if res.is_some() && parser.remaining() > 0 {
426 return Err(ParseError::form_error(
427 "trailing data in SVCB parameter",
428 ));
429 }
430 Ok(res)
431 }
432}
433
434impl<'a, Octs, Value> Iterator for ValueIter<'a, Octs, Value>
435where
436 Octs: Octets + ?Sized,
437 Value: ParseSvcParamValue<'a, Octs>,
438{
439 type Item = Result<Value, ParseError>;
440
441 fn next(&mut self) -> Option<Self::Item> {
442 while self.parser.remaining() > 0 {
443 match self.next_step() {
444 Ok(Some(res)) => return Some(Ok(res)),
445 Ok(None) => {}
446 Err(err) => {
447 self.parser.advance_to_end();
449 return Some(Err(err));
450 }
451 }
452 }
453 None
454 }
455}
456
457pub trait SvcParamValue {
461 fn key(&self) -> SvcParamKey;
463}
464
465pub trait ParseSvcParamValue<'a, Octs: ?Sized>:
467 SvcParamValue + Sized
468{
469 fn parse_value(
474 key: SvcParamKey,
475 parser: &mut Parser<'a, Octs>,
476 ) -> Result<Option<Self>, ParseError>;
477}
478
479pub trait ComposeSvcParamValue: SvcParamValue {
486 fn compose_len(&self) -> u16;
488
489 fn compose_value<Target: OctetsBuilder + ?Sized>(
491 &self,
492 target: &mut Target,
493 ) -> Result<(), Target::AppendError>;
494}
495
496#[derive(Clone, Debug)]
503pub struct UnknownSvcParam<Octs> {
504 key: SvcParamKey,
506
507 value: Octs,
509}
510
511impl<Octs> UnknownSvcParam<Octs> {
512 pub fn new(key: SvcParamKey, value: Octs) -> Result<Self, LongSvcParam>
516 where
517 Octs: AsRef<[u8]>,
518 {
519 LongSvcParam::check_len(value.as_ref().len())?;
520 Ok(unsafe { Self::new_unchecked(key, value) })
521 }
522
523 pub unsafe fn new_unchecked(key: SvcParamKey, value: Octs) -> Self {
530 Self { key, value }
531 }
532}
533
534impl<Octs: AsRef<[u8]>> UnknownSvcParam<Octs> {
535 pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
537 key: SvcParamKey,
538 parser: &mut Parser<'a, Src>,
539 ) -> Result<Self, ParseError> {
540 Self::new(key, parser.parse_octets(parser.remaining())?)
541 .map_err(Into::into)
542 }
543
544 pub fn parse_param<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
548 parser: &mut Parser<'a, Src>,
549 ) -> Result<Self, ParseError> {
550 let key = SvcParamKey::parse(parser)?;
551 let len = usize::from(u16::parse(parser)?);
552 let value = parser.parse_octets(len)?;
553 Ok(unsafe { Self::new_unchecked(key, value) })
554 }
555
556 pub fn compose_param<Target: OctetsBuilder + ?Sized>(
560 &self,
561 target: &mut Target,
562 ) -> Result<(), Target::AppendError> {
563 self.key.compose(target)?;
564 self.compose_len().compose(target)?;
565 self.compose_value(target)
566 }
567}
568
569impl<Octs> UnknownSvcParam<Octs> {
570 pub fn key(&self) -> SvcParamKey {
572 self.key
573 }
574
575 pub fn value(&self) -> &Octs {
577 &self.value
578 }
579
580 pub fn as_slice(&self) -> &[u8]
582 where
583 Octs: AsRef<[u8]>,
584 {
585 self.value.as_ref()
586 }
587
588 pub fn as_slice_mut(&mut self) -> &mut [u8]
590 where
591 Octs: AsMut<[u8]>,
592 {
593 self.value.as_mut()
594 }
595}
596
597impl<Octs> AsRef<Octs> for UnknownSvcParam<Octs> {
600 fn as_ref(&self) -> &Octs {
601 self.value()
602 }
603}
604
605impl<Octs: AsRef<[u8]>> AsRef<[u8]> for UnknownSvcParam<Octs> {
606 fn as_ref(&self) -> &[u8] {
607 self.as_slice()
608 }
609}
610
611impl<Octs: AsMut<[u8]>> AsMut<[u8]> for UnknownSvcParam<Octs> {
612 fn as_mut(&mut self) -> &mut [u8] {
613 self.as_slice_mut()
614 }
615}
616
617impl<Octs, OtherOcts> PartialEq<UnknownSvcParam<OtherOcts>>
620 for UnknownSvcParam<Octs>
621where
622 Octs: AsRef<[u8]>,
623 OtherOcts: AsRef<[u8]>,
624{
625 fn eq(&self, other: &UnknownSvcParam<OtherOcts>) -> bool {
626 self.as_slice().eq(other.as_slice())
627 }
628}
629
630impl<Octs: AsRef<[u8]>> Eq for UnknownSvcParam<Octs> {}
631
632impl<Octs: AsRef<[u8]>> hash::Hash for UnknownSvcParam<Octs> {
635 fn hash<H: hash::Hasher>(&self, state: &mut H) {
636 self.as_slice().hash(state)
637 }
638}
639
640impl<Octs> SvcParamValue for UnknownSvcParam<Octs> {
643 fn key(&self) -> SvcParamKey {
644 self.key
645 }
646}
647
648impl<'a, Octs: Octets + ?Sized> ParseSvcParamValue<'a, Octs>
649 for UnknownSvcParam<Octs::Range<'a>>
650{
651 fn parse_value(
652 key: SvcParamKey,
653 parser: &mut Parser<'a, Octs>,
654 ) -> Result<Option<Self>, ParseError> {
655 Self::new(key, parser.parse_octets(parser.remaining())?)
656 .map(Some)
657 .map_err(Into::into)
658 }
659}
660
661impl<Octs: AsRef<[u8]>> ComposeSvcParamValue for UnknownSvcParam<Octs> {
662 fn compose_len(&self) -> u16 {
663 u16::try_from(self.as_slice().len()).expect("long value")
664 }
665
666 fn compose_value<Target: OctetsBuilder + ?Sized>(
667 &self,
668 target: &mut Target,
669 ) -> Result<(), Target::AppendError> {
670 target.append_slice(self.as_slice())
671 }
672}
673
674impl<Octs: AsRef<[u8]>> fmt::Display for UnknownSvcParam<Octs> {
677 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
678 write!(f, "{}", self.key)?;
679 let slice = self.value.as_ref();
680 if !slice.is_empty() {
681 f.write_str("=")?;
682 for &ch in slice {
683 Symbol::from_octet(ch).fmt(f)?;
684 }
685 }
686 Ok(())
687 }
688}
689
690#[derive(Clone, Debug)]
710pub struct SvcParamsBuilder<Octs> {
711 octets: Octs,
713}
714
715impl<Octs> SvcParamsBuilder<Octs> {
716 #[must_use]
718 pub fn empty() -> Self
719 where
720 Octs: EmptyBuilder,
721 {
722 Self {
723 octets: Octs::empty(),
724 }
725 }
726
727 pub fn from_params<Src: Octets + ?Sized>(
733 params: &SvcParams<Src>,
734 ) -> Result<Self, ShortBuf>
735 where
736 Octs: AsRef<[u8]> + OctetsBuilder + EmptyBuilder,
737 {
738 let mut octets = Octs::empty();
739 for item in params.iter::<UnknownSvcParam<_>>() {
740 let item = item.expect("invalid SvcParams");
741 let start = u32::try_from(octets.as_ref().len())
742 .map_err(|_| ShortBuf)?
743 .checked_add(u32::from(u32::COMPOSE_LEN))
744 .ok_or(ShortBuf)?;
745 octets
746 .append_slice(start.to_ne_bytes().as_ref())
747 .map_err(Into::into)?;
748 item.compose_param(&mut octets).map_err(Into::into)?;
749 }
750 octets
751 .append_slice(u32::MAX.to_be_bytes().as_ref())
752 .map_err(Into::into)?;
753 Ok(Self { octets })
754 }
755
756 pub fn push<Value: ComposeSvcParamValue + ?Sized>(
761 &mut self,
762 value: &Value,
763 ) -> Result<(), PushError>
764 where
765 Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>,
766 {
767 self.push_raw(value.key(), value.compose_len(), |octs| {
768 value.compose_value(octs)
769 })
770 }
771
772 pub(super) fn push_raw(
773 &mut self,
774 key: SvcParamKey,
775 value_len: u16,
776 value: impl FnOnce(&mut Octs) -> Result<(), Octs::AppendError>,
777 ) -> Result<(), PushError>
778 where
779 Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>,
780 {
781 if self.octets.as_ref().is_empty() {
783 self.octets
784 .append_slice(&u32::from(u32::COMPOSE_LEN).to_ne_bytes())?;
785 key.compose(&mut self.octets)?;
786 value_len.compose(&mut self.octets)?;
787 (value)(&mut self.octets)?;
788 u32::MAX.compose(&mut self.octets)?;
789 return Ok(());
790 }
791
792 let start = u32::try_from(self.octets.as_ref().len())
795 .map_err(|_| PushError::ShortBuf)?;
796
797 let mut pre = None;
799 let mut next = None;
800 let mut parser = Parser::from_ref(self.octets.as_ref());
801
802 parser.advance(u32::COMPOSE_LEN.into()).unwrap();
804
805 while parser.remaining() > 0 {
806 let tmp_start = u32::try_from(parser.pos()).unwrap();
807 let tmp = UnknownSvcParam::parse_param(&mut parser).unwrap();
808 let tmp_end = u32::try_from(parser.pos()).unwrap();
809 let tmp_key = tmp.key();
810 match tmp_key.cmp(&key) {
811 Ordering::Equal => return Err(PushError::DuplicateKey),
812 Ordering::Less => match pre {
813 Some((key, _)) => {
814 if tmp_key > key {
815 pre = Some((tmp_key, tmp_end));
816 }
817 }
818 None => pre = Some((tmp_key, tmp_end)),
819 },
820 Ordering::Greater => match next {
821 Some((key, _)) => {
822 if tmp_key < key {
823 next = Some((tmp_key, tmp_start));
824 }
825 }
826 None => next = Some((tmp_key, tmp_start)),
827 },
828 }
829 parser.advance(u32::COMPOSE_LEN.into()).unwrap();
830 }
831
832 key.compose(&mut self.octets)?;
834 value_len.compose(&mut self.octets)?;
835 (value)(&mut self.octets)?;
836
837 self.octets.append_slice(
839 &next.map(|(_, pos)| pos).unwrap_or(u32::MAX).to_ne_bytes(),
840 )?;
841
842 let pos = pre
845 .map(|(_, pos)| {
846 usize::try_from(pos).unwrap()
849 })
850 .unwrap_or(0);
851 self.octets.as_mut()[pos..pos + usize::from(u32::COMPOSE_LEN)]
852 .copy_from_slice(&start.to_ne_bytes());
853
854 Ok(())
855 }
856
857 pub fn freeze<Target>(
864 &self,
865 ) -> Result<
866 SvcParams<Target>,
867 <<Target as FromBuilder>::Builder as OctetsBuilder>::AppendError,
868 >
869 where
870 Octs: AsRef<[u8]>,
871 Target: FromBuilder,
872 <Target as FromBuilder>::Builder: OctetsBuilder + EmptyBuilder,
873 {
874 let mut target = <Target as FromBuilder>::Builder::empty();
875 if !self.octets.as_ref().is_empty() {
876 let mut parser = Parser::from_ref(self.octets.as_ref());
877 loop {
878 let pos =
879 u32::from_ne_bytes(Parse::parse(&mut parser).unwrap());
880 if pos == u32::MAX {
881 break;
882 }
883 let pos = usize::try_from(pos).unwrap();
884 parser.seek(pos).unwrap();
885 let param =
886 UnknownSvcParam::parse_param(&mut parser).unwrap();
887 param.compose_param(&mut target)?;
888 }
889 }
890 Ok(unsafe {
891 SvcParams::from_octets_unchecked(Target::from_builder(target))
892 })
893 }
894}
895
896pub struct SvcParamsError(ParseError);
902
903impl From<ShortInput> for SvcParamsError {
904 fn from(err: ShortInput) -> Self {
905 ParseError::from(err).into()
906 }
907}
908
909impl From<ParseError> for SvcParamsError {
910 fn from(err: ParseError) -> Self {
911 SvcParamsError(err)
912 }
913}
914
915impl From<SvcParamsError> for ParseError {
916 fn from(err: SvcParamsError) -> Self {
917 err.0
918 }
919}
920
921#[derive(Clone, Copy, Debug)]
925pub struct LongSvcParam(());
926
927impl LongSvcParam {
928 #[must_use]
929 pub fn as_str(self) -> &'static str {
930 "service parameter too long"
931 }
932
933 pub fn check_len(len: usize) -> Result<(), Self> {
934 if len > usize::from(u16::MAX) {
935 Err(LongSvcParam(()))
936 } else {
937 Ok(())
938 }
939 }
940}
941
942impl From<LongSvcParam> for ParseError {
943 fn from(src: LongSvcParam) -> Self {
944 ParseError::form_error(src.as_str())
945 }
946}
947
948impl fmt::Display for LongSvcParam {
949 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
950 f.write_str(self.as_str())
951 }
952}
953
954#[cfg(feature = "std")]
955impl std::error::Error for LongSvcParam {}
956
957#[derive(Clone, Copy, Debug)]
961#[non_exhaustive]
962pub enum PushError {
963 DuplicateKey,
965
966 ShortBuf,
968}
969
970impl<T: Into<ShortBuf>> From<T> for PushError {
971 fn from(_: T) -> Self {
972 PushError::ShortBuf
973 }
974}
975
976impl fmt::Display for PushError {
977 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
978 match self {
979 PushError::DuplicateKey => f.write_str("duplicate key"),
980 PushError::ShortBuf => ShortBuf.fmt(f),
981 }
982 }
983}
984
985#[cfg(feature = "std")]
986impl std::error::Error for PushError {}
987
988#[cfg(test)]
991mod test {
992 use super::super::value;
993 use super::*;
994 use octseq::array::Array;
995
996 type Octets512 = Array<512>;
997 type Params512 = SvcParams<Array<512>>;
998 type Builder512 = SvcParamsBuilder<Array<512>>;
999
1000 fn octets512(slice: impl AsRef<[u8]>) -> Octets512 {
1001 Octets512::try_from(slice.as_ref()).unwrap()
1002 }
1003
1004 macro_rules! parse_compose {
1009 ( $rdata:expr, [ $( $value:expr )* ] ) => {
1010 let mut parser = Parser::from_ref($rdata.as_ref());
1012 let params = SvcParams::parse(&mut parser).unwrap();
1013
1014 let mut param_iter = params.iter_all();
1015 $(
1016 assert_eq!(
1017 param_iter.next().unwrap().unwrap(),
1018 AllValues::<Octets512>::from($value)
1019 );
1020 )*
1021 assert_eq!(None, param_iter.next());
1022
1023 let built = Params512::from_values(|_builder| {
1025 $(
1026 _builder.push(&$value).unwrap();
1027 )*
1028 Ok(())
1029 }).unwrap();
1030 let mut buf = Octets512::new();
1031 built.compose(&mut buf).unwrap();
1032 assert_eq!($rdata.as_ref(), buf.as_ref());
1033 }
1034 }
1035
1036 #[test]
1037 fn test_vectors_alias() {
1038 parse_compose!(b"", []);
1039 }
1040
1041 #[test]
1042 fn test_vectors_port_only() {
1043 parse_compose!(
1044 b"\x00\x03\
1045 \x00\x02\
1046 \x00\x35",
1047 [value::Port::new(53)]
1048 );
1049 }
1050
1051 #[test]
1052 fn test_vectors_unknown_param() {
1053 parse_compose!(
1054 b"\x02\x9b\
1055 \x00\x05\
1056 \x68\x65\x6c\x6c\x6f",
1057 [UnknownSvcParam::new(0x029b.into(), octets512(b"hello"))
1058 .unwrap()]
1059 );
1060 }
1061
1062 #[test]
1063 fn test_vectors_unknown_param_quote() {
1064 parse_compose!(
1065 b"\x02\x9b\
1066 \x00\x09\
1067 \x68\x65\x6c\x6c\x6f\xd2\x71\x6f\x6f",
1068 [UnknownSvcParam::new(
1069 0x029b.into(),
1070 octets512(b"\x68\x65\x6c\x6c\x6f\xd2\x71\x6f\x6f"),
1071 )
1072 .unwrap()]
1073 );
1074 }
1075
1076 #[test]
1077 fn test_vectors_ipv6hint() {
1078 use crate::base::net::Ipv6Addr;
1079 use core::str::FromStr;
1080
1081 parse_compose!(
1082 b"\x00\x06\
1083 \x00\x20\
1084 \x20\x01\x0d\xb8\x00\x00\x00\x00\
1085 \x00\x00\x00\x00\x00\x00\x00\x01\
1086 \x20\x01\x0d\xb8\x00\x00\x00\x00\
1087 \x00\x00\x00\x00\x00\x53\x00\x01",
1088 [value::Ipv6Hint::<Octets512>::from_addrs([
1089 Ipv6Addr::from_str("2001:db8::1").unwrap(),
1090 Ipv6Addr::from_str("2001:db8::53:1").unwrap(),
1091 ])
1092 .unwrap()]
1093 );
1094 }
1095
1096 #[test]
1097 fn test_vectors_ipv6hint_v4mapped() {
1098 use crate::base::net::Ipv6Addr;
1099 use core::str::FromStr;
1100
1101 parse_compose!(
1102 b"\x00\x06\
1103 \x00\x10\
1104 \x00\x00\x00\x00\x00\x00\x00\x00\
1105 \x00\x00\xff\xff\xc6\x33\x64\x64",
1106 [
1107 value::Ipv6Hint::<Octets512>::from_addrs([
1108 Ipv6Addr::from_str("::ffff:198.51.100.100").unwrap(),
1109 ])
1110 .unwrap()
1111 ]
1112 );
1113 }
1114
1115 #[cfg(feature = "std")]
1119 #[test]
1120 fn test_representation() {
1121 let mandatory = value::Mandatory::<Octets512>::from_keys(
1122 [
1123 SvcParamKey::ALPN,
1124 SvcParamKey::IPV4HINT,
1125 SvcParamKey::PRIVATE_RANGE_BEGIN.into(),
1126 ]
1127 .into_iter(),
1128 )
1129 .unwrap();
1130 assert_eq!(
1131 "mandatory=alpn,ipv4hint,key65280",
1132 format!("{}", mandatory)
1133 );
1134
1135 let mut alpn_builder = value::AlpnBuilder::<Octets512>::empty();
1136 alpn_builder.push("h2").unwrap();
1137 alpn_builder.push("h3-19").unwrap();
1138 assert_eq!("alpn=h2,h3-19", format!("{}", alpn_builder.freeze()));
1139
1140 assert_eq!("nodefaultalpn", format!("{}", value::NoDefaultAlpn));
1141
1142 assert_eq!(
1143 "ech",
1144 format!("{}", value::Ech::from_octets(Octets512::new()).unwrap())
1145 );
1146
1147 assert_eq!(
1148 "ipv4hint=192.0.2.1,192.0.2.2",
1149 format!(
1150 "{}",
1151 value::Ipv4Hint::<Octets512>::from_addrs([
1152 [192, 0, 2, 1].into(),
1153 [192, 0, 2, 2].into()
1154 ])
1155 .unwrap()
1156 )
1157 );
1158 }
1159
1160 #[test]
1163 fn empty_builder() {
1164 assert_eq!(
1165 Builder512::empty()
1166 .freeze::<Octets512>()
1167 .unwrap()
1168 .as_slice(),
1169 b""
1170 );
1171 }
1172
1173 #[test]
1174 fn one_value() {
1175 let mut builder = Builder512::empty();
1176 builder.push(&value::Port::new(53)).unwrap();
1177 assert_eq!(
1178 builder.freeze::<Octets512>().unwrap().as_slice(),
1179 b"\x00\x03\x00\x02\x00\x35"
1180 );
1181 }
1182
1183 #[test]
1184 fn three_values_in_order() {
1185 let mut builder = Builder512::empty();
1186 builder
1187 .push(&UnknownSvcParam::new(1.into(), b"223").unwrap())
1188 .unwrap();
1189 builder
1190 .push(&UnknownSvcParam::new(2.into(), b"224").unwrap())
1191 .unwrap();
1192 builder
1193 .push(&UnknownSvcParam::new(8.into(), b"225").unwrap())
1194 .unwrap();
1195 assert_eq!(
1196 builder.freeze::<Octets512>().unwrap().as_slice(),
1197 b"\x00\x01\x00\x03223\
1198 \x00\x02\x00\x03224\
1199 \x00\x08\x00\x03225"
1200 );
1201 }
1202
1203 #[test]
1204 fn three_values_out_of_order() {
1205 let mut builder = Builder512::empty();
1206 builder
1207 .push(&UnknownSvcParam::new(1.into(), b"223").unwrap())
1208 .unwrap();
1209 builder
1210 .push(&UnknownSvcParam::new(8.into(), b"225").unwrap())
1211 .unwrap();
1212 builder
1213 .push(&UnknownSvcParam::new(2.into(), b"224").unwrap())
1214 .unwrap();
1215 assert_eq!(
1216 builder.freeze::<Octets512>().unwrap().as_slice(),
1217 b"\x00\x01\x00\x03223\
1218 \x00\x02\x00\x03224\
1219 \x00\x08\x00\x03225"
1220 );
1221 }
1222
1223 #[test]
1224 fn three_values_with_collision() {
1225 let mut builder = Builder512::empty();
1226 builder
1227 .push(&UnknownSvcParam::new(1.into(), b"223").unwrap())
1228 .unwrap();
1229 builder
1230 .push(&UnknownSvcParam::new(8.into(), b"225").unwrap())
1231 .unwrap();
1232 assert!(builder
1233 .push(&UnknownSvcParam::new(8.into(), b"224").unwrap())
1234 .is_err());
1235 }
1236}