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::{
16 self, Formatter, ZonefileFmt,
17};
18use core::cmp::Ordering;
19use core::marker::PhantomData;
20use core::{cmp, fmt, hash, mem};
21use octseq::builder::{EmptyBuilder, FromBuilder, OctetsBuilder, ShortBuf};
22use octseq::octets::{Octets, OctetsFrom, OctetsInto};
23use octseq::parse::{Parser, ShortInput};
24
25#[derive(Clone, Default)]
74#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
75#[repr(transparent)]
76pub struct SvcParams<Octs: ?Sized> {
77 #[cfg_attr(
78 feature = "serde",
79 serde(
80 serialize_with =
81 "octseq::serde::SerializeOctets::serialize_octets",
82 deserialize_with =
83 "octseq::serde::DeserializeOctets::deserialize_octets",
84 bound(
85 serialize = "Octs: octseq::serde::SerializeOctets",
86 deserialize =
87 "Octs: octseq::serde::DeserializeOctets<'de> + Sized",
88 )
89 )
90 )]
91 octets: Octs,
92}
93
94impl<Octs> SvcParams<Octs> {
95 pub fn from_octets(octets: Octs) -> Result<Self, SvcParamsError>
102 where Octs: AsRef<[u8]> {
103 SvcParams::check_slice(octets.as_ref())?;
104 Ok(unsafe { Self::from_octets_unchecked(octets) })
105 }
106
107 pub unsafe fn from_octets_unchecked(octets: Octs) -> Self {
114 SvcParams { octets }
115 }
116}
117
118impl SvcParams<[u8]> {
119 pub fn from_slice(slice: &[u8]) -> Result<&Self, SvcParamsError> {
126 SvcParams::check_slice(slice)?;
127 Ok(unsafe { Self::from_slice_unchecked(slice) })
128 }
129
130 #[must_use]
137 pub unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
138 mem::transmute(slice)
140 }
141
142 fn check_slice(slice: &[u8]) -> Result<(), SvcParamsError> {
144 let mut parser = Parser::from_ref(slice);
145 let mut last_key = None;
146 while parser.remaining() > 0 {
147 let key = u16::parse(&mut parser)?;
148 if let Some(last_key) = last_key {
149 if key <= last_key {
150 Err(ParseError::form_error("unordered SVCB params"))?;
151 }
152 }
153 last_key = Some(key);
154 let len = u16::parse(&mut parser)?;
155 parser.advance(len.into())?;
156 }
157 Ok(())
158 }
159}
160
161impl<Octs> SvcParams<Octs> {
162 pub fn from_values<F>(op: F) -> Result<Self, PushError>
168 where
169 Octs: FromBuilder,
170 <Octs as FromBuilder>::Builder:
171 AsRef<[u8]> + OctetsBuilder + EmptyBuilder,
172 F: FnOnce(
173 &mut SvcParamsBuilder<<Octs as FromBuilder>::Builder>
174 ) -> Result<(), PushError>,
175 {
176 let mut res = SvcParamsBuilder::empty();
177 op(&mut res)?;
178 res.freeze().map_err(Into::into)
179 }
180}
181
182impl<Octs: AsRef<[u8]>> SvcParams<Octs> {
183 pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized + 'a>(
185 parser: &mut Parser<'a, Src>
186 ) -> Result<Self, ParseError> {
187 Self::from_octets(
188 parser.parse_octets(parser.remaining())?
189 ).map_err(Into::into)
190 }
191}
192
193impl<Octs: ?Sized> SvcParams<Octs> {
194 pub fn as_octets(&self) -> &Octs {
196 &self.octets
197 }
198}
199
200impl<Octs: AsRef<[u8]> + ?Sized> SvcParams<Octs> {
201 pub fn as_slice(&self) -> &[u8] {
203 self.octets.as_ref()
204 }
205
206 pub fn for_slice(&self) -> &SvcParams<[u8]> {
208 unsafe { SvcParams::from_slice_unchecked(self.octets.as_ref()) }
209 }
210
211 pub fn len(&self) -> usize {
213 self.octets.as_ref().len()
214 }
215
216 pub fn is_empty(&self) -> bool {
218 self.octets.as_ref().is_empty()
219 }
220
221 pub fn first<'s, Value>(&'s self) -> Option<Value>
231 where
232 Octs: Octets,
233 Value: ParseSvcParamValue<'s, Octs>,
234 {
235 self.iter::<Value>().next().and_then(Result::ok)
236 }
237
238 pub fn iter<Value>(&self) -> ValueIter<Octs, Value> {
240 ValueIter::new(self.as_octets())
241 }
242
243 pub fn iter_all(&self) -> ValueIter<Octs, AllValues<Octs>>
245 where Octs: Sized {
246 self.iter()
247 }
248
249 pub fn iter_raw(
251 &self
252 ) -> impl Iterator<Item = UnknownSvcParam<Octs::Range<'_>>>
253 where Octs: Octets + Sized {
254 self.iter().map(|item| item.expect("parsing cannot have failed"))
255 }
256
257 pub fn compose<Target: OctetsBuilder + ?Sized>(
259 &self, target: &mut Target
260 ) -> Result<(), Target::AppendError> {
261 target.append_slice(self.octets.as_ref())
262 }
263}
264
265impl<SrcOcts, Octs> OctetsFrom<SvcParams<SrcOcts>> for SvcParams<Octs>
268where Octs: OctetsFrom<SrcOcts> {
269 type Error = Octs::Error;
270
271 fn try_octets_from(
272 src: SvcParams<SrcOcts>
273 ) -> Result<Self, Self::Error> {
274 Ok(unsafe {
275 SvcParams::from_octets_unchecked(src.octets.try_octets_into()?)
276 })
277 }
278}
279
280impl<Octs, OtherOcts> PartialEq<SvcParams<OtherOcts>> for SvcParams<Octs>
283where
284 Octs: AsRef<[u8]> + ?Sized,
285 OtherOcts: AsRef<[u8]> + ?Sized,
286{
287 fn eq(&self, other: &SvcParams<OtherOcts>) -> bool {
288 self.as_slice().eq(other.as_slice())
289 }
290}
291
292impl<Octs: AsRef<[u8]> + ?Sized> Eq for SvcParams<Octs> { }
293
294impl<Octs: AsRef<[u8]> + ?Sized> hash::Hash for SvcParams<Octs> {
297 fn hash<H: hash::Hasher>(&self, state: &mut H) {
298 self.as_slice().hash(state)
299 }
300}
301
302impl<Octs, OtherOcts> PartialOrd<SvcParams<OtherOcts>> for SvcParams<Octs>
305where
306 Octs: AsRef<[u8]> + ?Sized,
307 OtherOcts: AsRef<[u8]> + ?Sized,
308{
309 fn partial_cmp(
310 &self, other: &SvcParams<OtherOcts>
311 ) -> Option<cmp::Ordering> {
312 self.as_slice().partial_cmp(other.as_slice())
313 }
314}
315
316impl<Octs: AsRef<[u8]> + ?Sized> Ord for SvcParams<Octs> {
317 fn cmp(&self, other: &Self) -> cmp::Ordering {
318 self.as_slice().cmp(other.as_slice())
319 }
320}
321
322impl<Octs, OtherOcts> CanonicalOrd<SvcParams<OtherOcts>> for SvcParams<Octs>
323where
324 Octs: AsRef<[u8]> + ?Sized,
325 OtherOcts: AsRef<[u8]> + ?Sized,
326{
327 fn canonical_cmp(
328 &self, other: &SvcParams<OtherOcts>
329 ) -> cmp::Ordering {
330 self.as_slice().cmp(other.as_slice())
331 }
332}
333
334impl<Octs: Octets + ?Sized> fmt::Display for SvcParams<Octs> {
337 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
338 let mut parser = Parser::from_ref(self.as_slice());
339 let mut first = true;
340 while parser.remaining() > 0 {
341 let key = SvcParamKey::parse(
342 &mut parser
343 ).expect("invalid SvcbParam");
344 let len = usize::from(
345 u16::parse(&mut parser).expect("invalid SvcParam")
346 );
347 let mut parser = parser.parse_parser(
348 len
349 ).expect("invalid SvcParam");
350 if first {
351 first = false;
352 }
353 else {
354 f.write_str(" ")?;
355 }
356 write!(
357 f, "{}", super::value::AllValues::parse_any(key, &mut parser)
358 )?;
359 };
360 Ok(())
361 }
362}
363
364impl<Octs: Octets + ?Sized> fmt::Debug for SvcParams<Octs> {
365 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
366 f.debug_tuple("SvcParams")
367 .field(&format_args!("{}", self))
368 .finish()
369 }
370}
371
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>: SvcParamValue + Sized {
467 fn parse_value(
472 key: SvcParamKey, parser: &mut Parser<'a, Octs>,
473 ) -> Result<Option<Self>, ParseError>;
474}
475
476pub trait ComposeSvcParamValue: SvcParamValue {
483 fn compose_len(&self) -> u16;
485
486 fn compose_value<Target: OctetsBuilder + ?Sized>(
488 &self, target: &mut Target,
489 ) -> Result<(), Target::AppendError>;
490}
491
492#[derive(Clone, Debug)]
499pub struct UnknownSvcParam<Octs> {
500 key: SvcParamKey,
502
503 value: Octs,
505}
506
507impl<Octs> UnknownSvcParam<Octs> {
508 pub fn new(key: SvcParamKey, value: Octs) -> Result<Self, LongSvcParam>
512 where Octs: AsRef<[u8]> {
513 LongSvcParam::check_len(value.as_ref().len())?;
514 Ok(unsafe { Self::new_unchecked(key, value) })
515 }
516
517 pub unsafe fn new_unchecked(key: SvcParamKey, value: Octs) -> Self {
524 Self { key, value }
525 }
526}
527
528impl<Octs: AsRef<[u8]>> UnknownSvcParam<Octs> {
529 pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
531 key: SvcParamKey,
532 parser: &mut Parser<'a, Src>,
533 ) -> Result<Self, ParseError> {
534 Self::new(
535 key, parser.parse_octets(parser.remaining())?
536 ).map_err(Into::into)
537 }
538
539 pub fn parse_param<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
543 parser: &mut Parser<'a, Src>,
544 ) -> Result<Self, ParseError> {
545 let key = SvcParamKey::parse(parser)?;
546 let len = usize::from(u16::parse(parser)?);
547 let value = parser.parse_octets(len)?;
548 Ok(unsafe { Self::new_unchecked(key, value) })
549 }
550
551 pub fn compose_param<Target: OctetsBuilder + ?Sized>(
555 &self, target: &mut Target
556 ) -> Result<(), Target::AppendError> {
557 self.key.compose(target)?;
558 self.compose_len().compose(target)?;
559 self.compose_value(target)
560 }
561}
562
563impl<Octs> UnknownSvcParam<Octs> {
564 pub fn key(&self) -> SvcParamKey {
566 self.key
567 }
568
569 pub fn value(&self) -> &Octs {
571 &self.value
572 }
573
574 pub fn as_slice(&self) -> &[u8]
576 where Octs: AsRef<[u8]> {
577 self.value.as_ref()
578 }
579
580 pub fn as_slice_mut(&mut self) -> &mut [u8]
582 where Octs: AsMut<[u8]> {
583 self.value.as_mut()
584 }
585}
586
587impl<Octs> AsRef<Octs> for UnknownSvcParam<Octs> {
590 fn as_ref(&self) -> &Octs {
591 self.value()
592 }
593}
594
595impl<Octs: AsRef<[u8]>> AsRef<[u8]> for UnknownSvcParam<Octs> {
596 fn as_ref(&self) -> &[u8] {
597 self.as_slice()
598 }
599}
600
601impl<Octs: AsMut<[u8]>> AsMut<[u8]> for UnknownSvcParam<Octs> {
602 fn as_mut(&mut self) -> &mut [u8] {
603 self.as_slice_mut()
604 }
605}
606
607impl<Octs, OtherOcts> PartialEq<UnknownSvcParam<OtherOcts>>
610for UnknownSvcParam<Octs>
611where
612 Octs: AsRef<[u8]>,
613 OtherOcts: AsRef<[u8]>,
614{
615 fn eq(&self, other: &UnknownSvcParam<OtherOcts>) -> bool {
616 self.as_slice().eq(other.as_slice())
617 }
618}
619
620impl<Octs: AsRef<[u8]>> Eq for UnknownSvcParam<Octs> { }
621
622impl<Octs: AsRef<[u8]>> hash::Hash for UnknownSvcParam<Octs> {
625 fn hash<H: hash::Hasher>(&self, state: &mut H) {
626 self.as_slice().hash(state)
627 }
628}
629
630impl<Octs> SvcParamValue for UnknownSvcParam<Octs> {
633 fn key(&self) -> SvcParamKey {
634 self.key
635 }
636}
637
638impl<'a, Octs: Octets + ?Sized> ParseSvcParamValue<'a, Octs>
639for UnknownSvcParam<Octs::Range<'a>> {
640 fn parse_value(
641 key: SvcParamKey,
642 parser: &mut Parser<'a, Octs>,
643 ) -> Result<Option<Self>, ParseError> {
644 Self::new(
645 key, parser.parse_octets(parser.remaining())?
646 ).map(Some).map_err(Into::into)
647 }
648}
649
650impl<Octs: AsRef<[u8]>> ComposeSvcParamValue for UnknownSvcParam<Octs> {
651 fn compose_len(&self) -> u16 {
652 u16::try_from(self.as_slice().len()).expect("long value")
653 }
654
655 fn compose_value<Target: OctetsBuilder + ?Sized>(
656 &self, target: &mut Target,
657 ) -> Result<(), Target::AppendError> {
658 target.append_slice(self.as_slice())
659 }
660}
661
662impl<Octs: AsRef<[u8]>> fmt::Display for UnknownSvcParam<Octs> {
665 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
666 write!(f, "{}", self.key)?;
667 let slice = self.value.as_ref();
668 if !slice.is_empty() {
669 f.write_str("=")?;
670 for &ch in slice {
671 Symbol::from_octet(ch).fmt(f)?;
672 }
673 }
674 Ok(())
675 }
676}
677
678
679#[derive(Clone, Debug)]
699pub struct SvcParamsBuilder<Octs> {
700 octets: Octs,
702}
703
704impl<Octs> SvcParamsBuilder<Octs> {
705 #[must_use]
707 pub fn empty() -> Self
708 where Octs: EmptyBuilder {
709 Self { octets: Octs::empty() }
710 }
711
712 pub fn from_params<Src: Octets + ?Sized>(
718 params: &SvcParams<Src>
719 ) -> Result<Self, ShortBuf>
720 where Octs: AsRef<[u8]> + OctetsBuilder + EmptyBuilder {
721 let mut octets = Octs::empty();
722 for item in params.iter::<UnknownSvcParam<_>>() {
723 let item = item.expect("invalid SvcParams");
724 let start = u32::try_from(
725 octets.as_ref().len()
726 ).map_err(|_| ShortBuf)?.checked_add(
727 u32::from(u32::COMPOSE_LEN)
728 ).ok_or(ShortBuf)?;
729 octets.append_slice(
730 start.to_ne_bytes().as_ref()
731 ).map_err(Into::into)?;
732 item.compose_param(&mut octets).map_err(Into::into)?;
733 }
734 octets.append_slice(
735 u32::MAX.to_be_bytes().as_ref()
736 ).map_err(Into::into)?;
737 Ok(Self { octets })
738 }
739
740 pub fn push<Value: ComposeSvcParamValue + ?Sized>(
745 &mut self, value: &Value
746 ) -> Result<(), PushError>
747 where Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]> {
748 self.push_raw(
749 value.key(), value.compose_len(), |octs| value.compose_value(octs)
750 )
751 }
752
753 pub(super) fn push_raw(
754 &mut self,
755 key: SvcParamKey,
756 value_len: u16,
757 value: impl FnOnce(&mut Octs) -> Result<(), Octs::AppendError>
758 ) -> Result<(), PushError>
759 where Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]> {
760 if self.octets.as_ref().is_empty() {
762 self.octets.append_slice(
763 &u32::from(u32::COMPOSE_LEN).to_ne_bytes()
764 )?;
765 key.compose(&mut self.octets)?;
766 value_len.compose(&mut self.octets)?;
767 (value)(&mut self.octets)?;
768 u32::MAX.compose(&mut self.octets)?;
769 return Ok(())
770 }
771
772 let start = u32::try_from(self.octets.as_ref().len()).map_err(|_|
775 PushError::ShortBuf
776 )?;
777
778 let mut pre = None;
780 let mut next = None;
781 let mut parser = Parser::from_ref(self.octets.as_ref());
782
783 parser.advance(u32::COMPOSE_LEN.into()).unwrap();
785
786 while parser.remaining() > 0 {
787 let tmp_start = u32::try_from(parser.pos()).unwrap();
788 let tmp = UnknownSvcParam::parse_param(&mut parser).unwrap();
789 let tmp_end = u32::try_from(parser.pos()).unwrap();
790 let tmp_key = tmp.key();
791 match tmp_key.cmp(&key) {
792 Ordering::Equal => return Err(PushError::DuplicateKey),
793 Ordering::Less => {
794 match pre {
795 Some((key, _)) => {
796 if tmp_key > key {
797 pre = Some((tmp_key, tmp_end));
798 }
799 }
800 None => {
801 pre = Some((tmp_key, tmp_end))
802 }
803 }
804 }
805 Ordering::Greater => {
806 match next {
807 Some((key, _)) => {
808 if tmp_key < key {
809 next = Some((tmp_key, tmp_start));
810 }
811 }
812 None => {
813 next = Some((tmp_key, tmp_start))
814 }
815 }
816 }
817 }
818 parser.advance(u32::COMPOSE_LEN.into()).unwrap();
819 }
820
821 key.compose(&mut self.octets)?;
823 value_len.compose(&mut self.octets)?;
824 (value)(&mut self.octets)?;
825
826 self.octets.append_slice(
828 &next.map(|(_, pos)| pos).unwrap_or(u32::MAX).to_ne_bytes()
829 )?;
830
831 let pos = pre.map(|(_, pos)| {
834 usize::try_from(pos).unwrap()
837 }).unwrap_or(0);
838 self.octets.as_mut()[
839 pos..pos + usize::from(u32::COMPOSE_LEN)
840 ].copy_from_slice(
841 &start.to_ne_bytes()
842 );
843
844 Ok(())
845 }
846
847 pub fn freeze<Target>(
854 &self
855 ) -> Result<
856 SvcParams<Target>,
857 <<Target as FromBuilder>::Builder as OctetsBuilder>::AppendError
858 >
859 where
860 Octs: AsRef<[u8]>,
861 Target: FromBuilder,
862 <Target as FromBuilder>::Builder: OctetsBuilder + EmptyBuilder
863 {
864 let mut target = <Target as FromBuilder>::Builder::empty();
865 if !self.octets.as_ref().is_empty() {
866 let mut parser = Parser::from_ref(self.octets.as_ref());
867 loop {
868 let pos = u32::from_ne_bytes(
869 Parse::parse(&mut parser).unwrap()
870 );
871 if pos == u32::MAX {
872 break;
873 }
874 let pos = usize::try_from(pos).unwrap();
875 parser.seek(pos).unwrap();
876 let param = UnknownSvcParam::parse_param(&mut parser).unwrap();
877 param.compose_param(&mut target)?;
878 }
879 }
880 Ok(unsafe {
881 SvcParams::from_octets_unchecked(
882 Target::from_builder(target)
883 )
884 })
885 }
886}
887
888pub struct SvcParamsError(ParseError);
894
895impl From<ShortInput> for SvcParamsError {
896 fn from(err: ShortInput) -> Self {
897 ParseError::from(err).into()
898 }
899}
900
901impl From<ParseError> for SvcParamsError {
902 fn from(err: ParseError) -> Self {
903 SvcParamsError(err)
904 }
905}
906
907impl From<SvcParamsError> for ParseError {
908 fn from(err: SvcParamsError) -> Self {
909 err.0
910 }
911}
912
913#[derive(Clone, Copy, Debug)]
917pub struct LongSvcParam(());
918
919impl LongSvcParam {
920 #[must_use]
921 pub fn as_str(self) -> &'static str {
922 "service parameter too long"
923 }
924
925 pub fn check_len(len: usize) -> Result<(), Self> {
926 if len > usize::from(u16::MAX) {
927 Err(LongSvcParam(()))
928 } else {
929 Ok(())
930 }
931 }
932}
933
934impl From<LongSvcParam> for ParseError {
935 fn from(src: LongSvcParam) -> Self {
936 ParseError::form_error(src.as_str())
937 }
938}
939
940impl fmt::Display for LongSvcParam {
941 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
942 f.write_str(self.as_str())
943 }
944}
945
946#[cfg(feature = "std")]
947impl std::error::Error for LongSvcParam {}
948
949
950#[derive(Clone, Copy, Debug)]
954#[non_exhaustive]
955pub enum PushError {
956 DuplicateKey,
958
959 ShortBuf,
961}
962
963impl<T: Into<ShortBuf>> From<T> for PushError {
964 fn from(_: T) -> Self {
965 PushError::ShortBuf
966 }
967}
968
969impl fmt::Display for PushError {
970 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
971 match self {
972 PushError::DuplicateKey => f.write_str("duplicate key"),
973 PushError::ShortBuf => ShortBuf.fmt(f)
974 }
975 }
976}
977
978#[cfg(feature = "std")]
979impl std::error::Error for PushError {}
980
981
982#[cfg(test)]
985mod test {
986 use super::*;
987 use super::super::value;
988 use octseq::array::Array;
989
990 type Octets512 = Array<512>;
991 type Params512 = SvcParams<Array<512>>;
992 type Builder512 = SvcParamsBuilder<Array<512>>;
993
994 fn octets512(slice: impl AsRef<[u8]>) -> Octets512 {
995 Octets512::try_from(slice.as_ref()).unwrap()
996 }
997
998
999 macro_rules! parse_compose {
1004 ( $rdata:expr, [ $( $value:expr )* ] ) => {
1005 let mut parser = Parser::from_ref($rdata.as_ref());
1007 let params = SvcParams::parse(&mut parser).unwrap();
1008
1009 let mut param_iter = params.iter_all();
1010 $(
1011 assert_eq!(
1012 param_iter.next().unwrap().unwrap(),
1013 AllValues::<Octets512>::from($value)
1014 );
1015 )*
1016 assert_eq!(None, param_iter.next());
1017
1018 let built = Params512::from_values(|_builder| {
1020 $(
1021 _builder.push(&$value).unwrap();
1022 )*
1023 Ok(())
1024 }).unwrap();
1025 let mut buf = Octets512::new();
1026 built.compose(&mut buf).unwrap();
1027 assert_eq!($rdata.as_ref(), buf.as_ref());
1028 }
1029 }
1030
1031 #[test]
1032 fn test_vectors_alias() {
1033 parse_compose!(b"", []);
1034 }
1035
1036 #[test]
1037 fn test_vectors_port_only() {
1038 parse_compose!(
1039 b"\x00\x03\
1040 \x00\x02\
1041 \x00\x35",
1042 [value::Port::new(53)]
1043 );
1044 }
1045
1046 #[test]
1047 fn test_vectors_unknown_param() {
1048 parse_compose!(
1049 b"\x02\x9b\
1050 \x00\x05\
1051 \x68\x65\x6c\x6c\x6f",
1052 [UnknownSvcParam::new(0x029b.into(), octets512(b"hello"))
1053 .unwrap()]
1054 );
1055 }
1056
1057 #[test]
1058 fn test_vectors_unknown_param_quote() {
1059 parse_compose!(
1060 b"\x02\x9b\
1061 \x00\x09\
1062 \x68\x65\x6c\x6c\x6f\xd2\x71\x6f\x6f",
1063 [UnknownSvcParam::new(
1064 0x029b.into(),
1065 octets512(b"\x68\x65\x6c\x6c\x6f\xd2\x71\x6f\x6f"),
1066 )
1067 .unwrap()]
1068 );
1069 }
1070
1071 #[test]
1072 fn test_vectors_ipv6hint() {
1073 use crate::base::net::Ipv6Addr;
1074 use core::str::FromStr;
1075
1076 parse_compose!(
1077 b"\x00\x06\
1078 \x00\x20\
1079 \x20\x01\x0d\xb8\x00\x00\x00\x00\
1080 \x00\x00\x00\x00\x00\x00\x00\x01\
1081 \x20\x01\x0d\xb8\x00\x00\x00\x00\
1082 \x00\x00\x00\x00\x00\x53\x00\x01",
1083 [value::Ipv6Hint::<Octets512>::from_addrs([
1084 Ipv6Addr::from_str("2001:db8::1").unwrap(),
1085 Ipv6Addr::from_str("2001:db8::53:1").unwrap(),
1086 ])
1087 .unwrap()]
1088 );
1089 }
1090
1091 #[test]
1092 fn test_vectors_ipv6hint_v4mapped() {
1093 use crate::base::net::Ipv6Addr;
1094 use core::str::FromStr;
1095
1096 parse_compose!(
1097 b"\x00\x06\
1098 \x00\x10\
1099 \x00\x00\x00\x00\x00\x00\x00\x00\
1100 \x00\x00\xff\xff\xc6\x33\x64\x64",
1101 [
1102 value::Ipv6Hint::<Octets512>::from_addrs([
1103 Ipv6Addr::from_str("::ffff:198.51.100.100").unwrap(),
1104 ])
1105 .unwrap()
1106 ]
1107 );
1108 }
1109
1110 #[cfg(feature = "std")]
1114 #[test]
1115 fn test_representation() {
1116 let mandatory = value::Mandatory::<Octets512>::from_keys(
1117 [
1118 SvcParamKey::ALPN,
1119 SvcParamKey::IPV4HINT,
1120 SvcParamKey::PRIVATE_RANGE_BEGIN.into(),
1121 ]
1122 .into_iter(),
1123 )
1124 .unwrap();
1125 assert_eq!(
1126 "mandatory=alpn,ipv4hint,key65280",
1127 format!("{}", mandatory)
1128 );
1129
1130 let mut alpn_builder = value::AlpnBuilder::<Octets512>::empty();
1131 alpn_builder.push("h2").unwrap();
1132 alpn_builder.push("h3-19").unwrap();
1133 assert_eq!("alpn=h2,h3-19", format!("{}", alpn_builder.freeze()));
1134
1135 assert_eq!("nodefaultalpn", format!("{}", value::NoDefaultAlpn));
1136
1137 assert_eq!(
1138 "ech",
1139 format!("{}", value::Ech::from_octets(Octets512::new()).unwrap())
1140 );
1141
1142 assert_eq!(
1143 "ipv4hint=192.0.2.1,192.0.2.2",
1144 format!(
1145 "{}",
1146 value::Ipv4Hint::<Octets512>::from_addrs([
1147 [192, 0, 2, 1].into(),
1148 [192, 0, 2, 2].into()
1149 ])
1150 .unwrap()
1151 )
1152 );
1153 }
1154
1155 #[test]
1158 fn empty_builder() {
1159 assert_eq!(
1160 Builder512::empty()
1161 .freeze::<Octets512>()
1162 .unwrap()
1163 .as_slice(),
1164 b""
1165 );
1166 }
1167
1168 #[test]
1169 fn one_value() {
1170 let mut builder = Builder512::empty();
1171 builder.push(&value::Port::new(53)).unwrap();
1172 assert_eq!(
1173 builder.freeze::<Octets512>().unwrap().as_slice(),
1174 b"\x00\x03\x00\x02\x00\x35"
1175 );
1176 }
1177
1178 #[test]
1179 fn three_values_in_order() {
1180 let mut builder = Builder512::empty();
1181 builder
1182 .push(&UnknownSvcParam::new(1.into(), b"223").unwrap())
1183 .unwrap();
1184 builder
1185 .push(&UnknownSvcParam::new(2.into(), b"224").unwrap())
1186 .unwrap();
1187 builder
1188 .push(&UnknownSvcParam::new(8.into(), b"225").unwrap())
1189 .unwrap();
1190 assert_eq!(
1191 builder.freeze::<Octets512>().unwrap().as_slice(),
1192 b"\x00\x01\x00\x03223\
1193 \x00\x02\x00\x03224\
1194 \x00\x08\x00\x03225"
1195 );
1196 }
1197
1198 #[test]
1199 fn three_values_out_of_order() {
1200 let mut builder = Builder512::empty();
1201 builder
1202 .push(&UnknownSvcParam::new(1.into(), b"223").unwrap())
1203 .unwrap();
1204 builder
1205 .push(&UnknownSvcParam::new(8.into(), b"225").unwrap())
1206 .unwrap();
1207 builder
1208 .push(&UnknownSvcParam::new(2.into(), b"224").unwrap())
1209 .unwrap();
1210 assert_eq!(
1211 builder.freeze::<Octets512>().unwrap().as_slice(),
1212 b"\x00\x01\x00\x03223\
1213 \x00\x02\x00\x03224\
1214 \x00\x08\x00\x03225"
1215 );
1216 }
1217
1218 #[test]
1219 fn three_values_with_collision() {
1220 let mut builder = Builder512::empty();
1221 builder
1222 .push(&UnknownSvcParam::new(1.into(), b"223").unwrap())
1223 .unwrap();
1224 builder
1225 .push(&UnknownSvcParam::new(8.into(), b"225").unwrap())
1226 .unwrap();
1227 assert!(builder
1228 .push(&UnknownSvcParam::new(8.into(), b"224").unwrap())
1229 .is_err());
1230 }
1231}