1use super::value::AllValues;
6use crate::base::iana::SvcParamKey;
7use crate::base::scan::Symbol;
8use crate::base::wire::{Compose, Parse, ParseError};
9use octseq::builder::{EmptyBuilder, FromBuilder, OctetsBuilder, ShortBuf};
10use octseq::octets::{Octets, OctetsFrom, OctetsInto};
11use octseq::parse::{Parser, ShortInput};
12use core::{cmp, fmt, hash};
13use core::cmp::Ordering;
14use core::marker::PhantomData;
15
16#[derive(Clone, Default)]
67#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
68pub struct SvcParams<Octs: ?Sized> {
69 #[cfg_attr(
70 feature = "serde",
71 serde(
72 serialize_with =
73 "octseq::serde::SerializeOctets::serialize_octets",
74 deserialize_with =
75 "octseq::serde::DeserializeOctets::deserialize_octets",
76 bound(
77 serialize = "Octs: octseq::serde::SerializeOctets",
78 deserialize =
79 "Octs: octseq::serde::DeserializeOctets<'de> + Sized",
80 )
81 )
82 )]
83 octets: Octs,
84}
85
86impl<Octs> SvcParams<Octs> {
87 pub fn from_octets(octets: Octs) -> Result<Self, SvcParamsError>
94 where Octs: AsRef<[u8]> {
95 SvcParams::check_slice(octets.as_ref())?;
96 Ok(unsafe { Self::from_octets_unchecked(octets) })
97 }
98
99 pub unsafe fn from_octets_unchecked(octets: Octs) -> Self {
106 SvcParams { octets }
107 }
108}
109
110impl SvcParams<[u8]> {
111 pub fn from_slice(slice: &[u8]) -> Result<&Self, SvcParamsError> {
118 SvcParams::check_slice(slice)?;
119 Ok(unsafe { Self::from_slice_unchecked(slice) })
120 }
121
122 #[must_use]
129 pub unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
130 &*(slice as *const [u8] as *const Self)
131 }
132
133 fn check_slice(slice: &[u8]) -> Result<(), SvcParamsError> {
135 let mut parser = Parser::from_ref(slice);
136 let mut last_key = None;
137 while parser.remaining() > 0 {
138 let key = u16::parse(&mut parser)?;
139 if let Some(last_key) = last_key {
140 if key <= last_key {
141 Err(ParseError::form_error("unordered SVCB params"))?;
142 }
143 }
144 last_key = Some(key);
145 let len = u16::parse(&mut parser)?;
146 parser.advance(len.into())?;
147 }
148 Ok(())
149 }
150}
151
152impl<Octs> SvcParams<Octs> {
153 pub fn from_values<F>(op: F) -> Result<Self, PushError>
159 where
160 Octs: FromBuilder,
161 <Octs as FromBuilder>::Builder:
162 AsRef<[u8]> + OctetsBuilder + EmptyBuilder,
163 F: FnOnce(
164 &mut SvcParamsBuilder<<Octs as FromBuilder>::Builder>
165 ) -> Result<(), PushError>,
166 {
167 let mut res = SvcParamsBuilder::empty();
168 op(&mut res)?;
169 res.freeze().map_err(Into::into)
170 }
171}
172
173impl<Octs: AsRef<[u8]>> SvcParams<Octs> {
174 pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized + 'a>(
176 parser: &mut Parser<'a, Src>
177 ) -> Result<Self, ParseError> {
178 Self::from_octets(
179 parser.parse_octets(parser.remaining())?
180 ).map_err(Into::into)
181 }
182}
183
184impl<Octs: ?Sized> SvcParams<Octs> {
185 pub fn as_octets(&self) -> &Octs {
187 &self.octets
188 }
189}
190
191impl<Octs: AsRef<[u8]> + ?Sized> SvcParams<Octs> {
192 pub fn as_slice(&self) -> &[u8] {
194 self.octets.as_ref()
195 }
196
197 pub fn for_slice(&self) -> &SvcParams<[u8]> {
199 unsafe { SvcParams::from_slice_unchecked(self.octets.as_ref()) }
200 }
201
202 pub fn len(&self) -> usize {
204 self.octets.as_ref().len()
205 }
206
207 pub fn is_empty(&self) -> bool {
209 self.octets.as_ref().is_empty()
210 }
211
212 pub fn first<'s, Value>(&'s self) -> Option<Value>
222 where
223 Octs: Octets,
224 Value: ParseSvcParamValue<'s, Octs>,
225 {
226 self.iter::<Value>().next().and_then(Result::ok)
227 }
228
229 pub fn iter<Value>(&self) -> ValueIter<Octs, Value> {
231 ValueIter::new(self.as_octets())
232 }
233
234 pub fn iter_all(&self) -> ValueIter<Octs, AllValues<Octs>>
236 where Octs: Sized {
237 self.iter()
238 }
239
240 pub fn iter_raw(
242 &self
243 ) -> impl Iterator<Item = UnknownSvcParam<Octs::Range<'_>>>
244 where Octs: Octets + Sized {
245 self.iter().map(|item| item.expect("parsing cannot have failed"))
246 }
247
248 pub fn compose<Target: OctetsBuilder + ?Sized>(
250 &self, target: &mut Target
251 ) -> Result<(), Target::AppendError> {
252 target.append_slice(self.octets.as_ref())
253 }
254}
255
256impl<SrcOcts, Octs> OctetsFrom<SvcParams<SrcOcts>> for SvcParams<Octs>
259where Octs: OctetsFrom<SrcOcts> {
260 type Error = Octs::Error;
261
262 fn try_octets_from(
263 src: SvcParams<SrcOcts>
264 ) -> Result<Self, Self::Error> {
265 Ok(unsafe {
266 SvcParams::from_octets_unchecked(src.octets.try_octets_into()?)
267 })
268 }
269}
270
271impl<Octs, OtherOcts> PartialEq<SvcParams<OtherOcts>> for SvcParams<Octs>
274where
275 Octs: AsRef<[u8]> + ?Sized,
276 OtherOcts: AsRef<[u8]> + ?Sized,
277{
278 fn eq(&self, other: &SvcParams<OtherOcts>) -> bool {
279 self.as_slice().eq(other.as_slice())
280 }
281}
282
283impl<Octs: AsRef<[u8]> + ?Sized> Eq for SvcParams<Octs> { }
284
285impl<Octs: AsRef<[u8]> + ?Sized> hash::Hash for SvcParams<Octs> {
288 fn hash<H: hash::Hasher>(&self, state: &mut H) {
289 self.as_slice().hash(state)
290 }
291}
292
293impl<Octs, OtherOcts> PartialOrd<SvcParams<OtherOcts>> for SvcParams<Octs>
296where
297 Octs: AsRef<[u8]> + ?Sized,
298 OtherOcts: AsRef<[u8]> + ?Sized,
299{
300 fn partial_cmp(
301 &self, other: &SvcParams<OtherOcts>
302 ) -> Option<cmp::Ordering> {
303 self.as_slice().partial_cmp(other.as_slice())
304 }
305}
306
307impl<Octs: AsRef<[u8]> + ?Sized> Ord for SvcParams<Octs> {
308 fn cmp(&self, other: &Self) -> cmp::Ordering {
309 self.as_slice().cmp(other.as_slice())
310 }
311}
312
313impl<Octs: Octets + ?Sized> fmt::Display for SvcParams<Octs> {
316 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
317 let mut parser = Parser::from_ref(self.as_slice());
318 let mut first = true;
319 while parser.remaining() > 0 {
320 let key = SvcParamKey::parse(
321 &mut parser
322 ).expect("invalid SvcbParam");
323 let len = usize::from(
324 u16::parse(&mut parser).expect("invalid SvcParam")
325 );
326 let mut parser = parser.parse_parser(
327 len
328 ).expect("invalid SvcParam");
329 if first {
330 first = false;
331 }
332 else {
333 f.write_str(" ")?;
334 }
335 write!(
336 f, "{}", super::value::AllValues::parse_any(key, &mut parser)
337 )?;
338 };
339 Ok(())
340 }
341}
342
343impl<Octs: Octets + ?Sized> fmt::Debug for SvcParams<Octs> {
344 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
345 f.debug_tuple("SvcParams").field(
346 &format_args!("{}", self)
347 ).finish()
348 }
349}
350
351
352#[derive(Clone, Debug)]
359pub struct ValueIter<'a, Octs: ?Sized, Value> {
360 parser: Parser<'a, Octs>,
361 marker: PhantomData<Value>,
362}
363
364impl<'a, Octs: AsRef<[u8]> + ?Sized, Value> ValueIter<'a, Octs, Value> {
365 fn new(octets: &'a Octs) -> Self {
366 ValueIter {
367 parser: Parser::from_ref(octets),
368 marker: PhantomData,
369 }
370 }
371
372 fn next_step(&mut self) -> Result<Option<Value>, ParseError>
373 where
374 Octs: Octets,
375 Value: ParseSvcParamValue<'a, Octs>,
376 {
377 let key = SvcParamKey::parse(&mut self.parser)?;
378 let len = usize::from(u16::parse(&mut self.parser)?);
379 let mut parser = self.parser.parse_parser(len)?;
380 let res = Value::parse_value(key, &mut parser)?;
381 if res.is_some() && parser.remaining() > 0 {
382 return Err(ParseError::form_error(
383 "trailing data in SVCB parameter",
384 ));
385 }
386 Ok(res)
387 }
388}
389
390impl<'a, Octs, Value> Iterator for ValueIter<'a, Octs, Value>
391where
392 Octs: Octets + ?Sized,
393 Value: ParseSvcParamValue<'a, Octs>,
394{
395 type Item = Result<Value, ParseError>;
396
397 fn next(&mut self) -> Option<Self::Item> {
398 while self.parser.remaining() > 0 {
399 match self.next_step() {
400 Ok(Some(res)) => return Some(Ok(res)),
401 Ok(None) => { }
402 Err(err) => {
403 self.parser.advance_to_end();
405 return Some(Err(err));
406 }
407 }
408 }
409 None
410 }
411}
412
413pub trait SvcParamValue {
417 fn key(&self) -> SvcParamKey;
419}
420
421pub trait ParseSvcParamValue<'a, Octs: ?Sized>: SvcParamValue + Sized {
423 fn parse_value(
428 key: SvcParamKey, parser: &mut Parser<'a, Octs>,
429 ) -> Result<Option<Self>, ParseError>;
430}
431
432pub trait ComposeSvcParamValue: SvcParamValue {
439 fn compose_len(&self) -> u16;
441
442 fn compose_value<Target: OctetsBuilder + ?Sized>(
444 &self, target: &mut Target,
445 ) -> Result<(), Target::AppendError>;
446}
447
448#[derive(Clone, Debug)]
455pub struct UnknownSvcParam<Octs> {
456 key: SvcParamKey,
458
459 value: Octs,
461}
462
463impl<Octs> UnknownSvcParam<Octs> {
464 pub fn new(key: SvcParamKey, value: Octs) -> Result<Self, LongSvcParam>
468 where Octs: AsRef<[u8]> {
469 LongSvcParam::check_len(value.as_ref().len())?;
470 Ok(unsafe { Self::new_unchecked(key, value) })
471 }
472
473 pub unsafe fn new_unchecked(key: SvcParamKey, value: Octs) -> Self {
480 Self { key, value }
481 }
482}
483
484impl<Octs: AsRef<[u8]>> UnknownSvcParam<Octs> {
485 pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
487 key: SvcParamKey,
488 parser: &mut Parser<'a, Src>,
489 ) -> Result<Self, ParseError> {
490 Self::new(
491 key, parser.parse_octets(parser.remaining())?
492 ).map_err(Into::into)
493 }
494
495 pub fn parse_param<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
499 parser: &mut Parser<'a, Src>,
500 ) -> Result<Self, ParseError> {
501 let key = SvcParamKey::parse(parser)?;
502 let len = usize::from(u16::parse(parser)?);
503 let value = parser.parse_octets(len)?;
504 Ok(unsafe { Self::new_unchecked(key, value) })
505 }
506
507 pub fn compose_param<Target: OctetsBuilder + ?Sized>(
511 &self, target: &mut Target
512 ) -> Result<(), Target::AppendError> {
513 self.key.compose(target)?;
514 self.compose_len().compose(target)?;
515 self.compose_value(target)
516 }
517}
518
519impl<Octs> UnknownSvcParam<Octs> {
520 pub fn key(&self) -> SvcParamKey {
522 self.key
523 }
524
525 pub fn value(&self) -> &Octs {
527 &self.value
528 }
529
530 pub fn as_slice(&self) -> &[u8]
532 where Octs: AsRef<[u8]> {
533 self.value.as_ref()
534 }
535
536 pub fn as_slice_mut(&mut self) -> &mut [u8]
538 where Octs: AsMut<[u8]> {
539 self.value.as_mut()
540 }
541}
542
543impl<Octs> AsRef<Octs> for UnknownSvcParam<Octs> {
546 fn as_ref(&self) -> &Octs {
547 self.value()
548 }
549}
550
551impl<Octs: AsRef<[u8]>> AsRef<[u8]> for UnknownSvcParam<Octs> {
552 fn as_ref(&self) -> &[u8] {
553 self.as_slice()
554 }
555}
556
557impl<Octs: AsMut<[u8]>> AsMut<[u8]> for UnknownSvcParam<Octs> {
558 fn as_mut(&mut self) -> &mut [u8] {
559 self.as_slice_mut()
560 }
561}
562
563impl<Octs, OtherOcts> PartialEq<UnknownSvcParam<OtherOcts>>
566for UnknownSvcParam<Octs>
567where
568 Octs: AsRef<[u8]>,
569 OtherOcts: AsRef<[u8]>,
570{
571 fn eq(&self, other: &UnknownSvcParam<OtherOcts>) -> bool {
572 self.as_slice().eq(other.as_slice())
573 }
574}
575
576impl<Octs: AsRef<[u8]>> Eq for UnknownSvcParam<Octs> { }
577
578impl<Octs: AsRef<[u8]>> hash::Hash for UnknownSvcParam<Octs> {
581 fn hash<H: hash::Hasher>(&self, state: &mut H) {
582 self.as_slice().hash(state)
583 }
584}
585
586impl<Octs> SvcParamValue for UnknownSvcParam<Octs> {
589 fn key(&self) -> SvcParamKey {
590 self.key
591 }
592}
593
594impl<'a, Octs: Octets + ?Sized> ParseSvcParamValue<'a, Octs>
595for UnknownSvcParam<Octs::Range<'a>> {
596 fn parse_value(
597 key: SvcParamKey,
598 parser: &mut Parser<'a, Octs>,
599 ) -> Result<Option<Self>, ParseError> {
600 Self::new(
601 key, parser.parse_octets(parser.remaining())?
602 ).map(Some).map_err(Into::into)
603 }
604}
605
606impl<Octs: AsRef<[u8]>> ComposeSvcParamValue for UnknownSvcParam<Octs> {
607 fn compose_len(&self) -> u16 {
608 u16::try_from(self.as_slice().len()).expect("long value")
609 }
610
611 fn compose_value<Target: OctetsBuilder + ?Sized>(
612 &self, target: &mut Target,
613 ) -> Result<(), Target::AppendError> {
614 target.append_slice(self.as_slice())
615 }
616}
617
618impl<Octs: AsRef<[u8]>> fmt::Display for UnknownSvcParam<Octs> {
621 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
622 write!(f, "{}", self.key)?;
623 let slice = self.value.as_ref();
624 if !slice.is_empty() {
625 f.write_str("=")?;
626 for &ch in slice {
627 Symbol::from_octet(ch).fmt(f)?;
628 }
629 }
630 Ok(())
631 }
632}
633
634
635#[derive(Clone, Debug)]
655pub struct SvcParamsBuilder<Octs> {
656 octets: Octs,
658}
659
660impl<Octs> SvcParamsBuilder<Octs> {
661 #[must_use]
663 pub fn empty() -> Self
664 where Octs: EmptyBuilder {
665 Self { octets: Octs::empty() }
666 }
667
668 pub fn from_params<Src: Octets + ?Sized>(
674 params: &SvcParams<Src>
675 ) -> Result<Self, ShortBuf>
676 where Octs: AsRef<[u8]> + OctetsBuilder + EmptyBuilder {
677 let mut octets = Octs::empty();
678 for item in params.iter::<UnknownSvcParam<_>>() {
679 let item = item.expect("invalid SvcParams");
680 let start = u32::try_from(
681 octets.as_ref().len()
682 ).map_err(|_| ShortBuf)?.checked_add(
683 u32::from(u32::COMPOSE_LEN)
684 ).ok_or(ShortBuf)?;
685 octets.append_slice(
686 start.to_ne_bytes().as_ref()
687 ).map_err(Into::into)?;
688 item.compose_param(&mut octets).map_err(Into::into)?;
689 }
690 octets.append_slice(
691 u32::MAX.to_be_bytes().as_ref()
692 ).map_err(Into::into)?;
693 Ok(Self { octets })
694 }
695
696 pub fn push<Value: ComposeSvcParamValue + ?Sized>(
701 &mut self, value: &Value
702 ) -> Result<(), PushError>
703 where Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]> {
704 self.push_raw(
705 value.key(), value.compose_len(), |octs| value.compose_value(octs)
706 )
707 }
708
709 pub(super) fn push_raw(
710 &mut self,
711 key: SvcParamKey,
712 value_len: u16,
713 value: impl FnOnce(&mut Octs) -> Result<(), Octs::AppendError>
714 ) -> Result<(), PushError>
715 where Octs: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]> {
716 if self.octets.as_ref().is_empty() {
718 self.octets.append_slice(
719 &u32::from(u32::COMPOSE_LEN).to_ne_bytes()
720 )?;
721 key.compose(&mut self.octets)?;
722 value_len.compose(&mut self.octets)?;
723 (value)(&mut self.octets)?;
724 u32::MAX.compose(&mut self.octets)?;
725 return Ok(())
726 }
727
728 let start = u32::try_from(self.octets.as_ref().len()).map_err(|_|
731 PushError::ShortBuf
732 )?;
733
734 let mut pre = None;
736 let mut next = None;
737 let mut parser = Parser::from_ref(self.octets.as_ref());
738
739 parser.advance(u32::COMPOSE_LEN.into()).unwrap();
741
742 while parser.remaining() > 0 {
743 let tmp_start = u32::try_from(parser.pos()).unwrap();
744 let tmp = UnknownSvcParam::parse_param(&mut parser).unwrap();
745 let tmp_end = u32::try_from(parser.pos()).unwrap();
746 let tmp_key = tmp.key();
747 match tmp_key.cmp(&key) {
748 Ordering::Equal => return Err(PushError::DuplicateKey),
749 Ordering::Less => {
750 match pre {
751 Some((key, _)) => {
752 if tmp_key > key {
753 pre = Some((tmp_key, tmp_end));
754 }
755 }
756 None => {
757 pre = Some((tmp_key, tmp_end))
758 }
759 }
760 }
761 Ordering::Greater => {
762 match next {
763 Some((key, _)) => {
764 if tmp_key < key {
765 next = Some((tmp_key, tmp_start));
766 }
767 }
768 None => {
769 next = Some((tmp_key, tmp_start))
770 }
771 }
772 }
773 }
774 parser.advance(u32::COMPOSE_LEN.into()).unwrap();
775 }
776
777 key.compose(&mut self.octets)?;
779 value_len.compose(&mut self.octets)?;
780 (value)(&mut self.octets)?;
781
782 self.octets.append_slice(
784 &next.map(|(_, pos)| pos).unwrap_or(u32::MAX).to_ne_bytes()
785 )?;
786
787 let pos = pre.map(|(_, pos)| {
790 usize::try_from(pos).unwrap()
793 }).unwrap_or(0);
794 self.octets.as_mut()[
795 pos..pos + usize::from(u32::COMPOSE_LEN)
796 ].copy_from_slice(
797 &start.to_ne_bytes()
798 );
799
800 Ok(())
801 }
802
803 pub fn freeze<Target>(
810 &self
811 ) -> Result<
812 SvcParams<Target>,
813 <<Target as FromBuilder>::Builder as OctetsBuilder>::AppendError
814 >
815 where
816 Octs: AsRef<[u8]>,
817 Target: FromBuilder,
818 <Target as FromBuilder>::Builder: OctetsBuilder + EmptyBuilder
819 {
820 let mut target = <Target as FromBuilder>::Builder::empty();
821 if !self.octets.as_ref().is_empty() {
822 let mut parser = Parser::from_ref(self.octets.as_ref());
823 loop {
824 let pos = u32::from_ne_bytes(
825 Parse::parse(&mut parser).unwrap()
826 );
827 if pos == u32::MAX {
828 break;
829 }
830 let pos = usize::try_from(pos).unwrap();
831 parser.seek(pos).unwrap();
832 let param = UnknownSvcParam::parse_param(&mut parser).unwrap();
833 param.compose_param(&mut target)?;
834 }
835 }
836 Ok(unsafe {
837 SvcParams::from_octets_unchecked(
838 Target::from_builder(target)
839 )
840 })
841 }
842}
843
844pub struct SvcParamsError(ParseError);
850
851impl From<ShortInput> for SvcParamsError {
852 fn from(err: ShortInput) -> Self {
853 ParseError::from(err).into()
854 }
855}
856
857impl From<ParseError> for SvcParamsError {
858 fn from(err: ParseError) -> Self {
859 SvcParamsError(err)
860 }
861}
862
863impl From<SvcParamsError> for ParseError {
864 fn from(err: SvcParamsError) -> Self {
865 err.0
866 }
867}
868
869#[derive(Clone, Copy, Debug)]
873pub struct LongSvcParam(());
874
875impl LongSvcParam {
876 #[must_use]
877 pub fn as_str(self) -> &'static str {
878 "service parameter too long"
879 }
880
881 pub fn check_len(len: usize) -> Result<(), Self> {
882 if len > usize::from(u16::MAX) {
883 Err(LongSvcParam(()))
884 } else {
885 Ok(())
886 }
887 }
888}
889
890impl From<LongSvcParam> for ParseError {
891 fn from(src: LongSvcParam) -> Self {
892 ParseError::form_error(src.as_str())
893 }
894}
895
896impl fmt::Display for LongSvcParam {
897 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
898 f.write_str(self.as_str())
899 }
900}
901
902#[cfg(feature = "std")]
903impl std::error::Error for LongSvcParam {}
904
905
906#[derive(Clone, Copy, Debug)]
910#[non_exhaustive]
911pub enum PushError {
912 DuplicateKey,
914
915 ShortBuf,
917}
918
919impl<T: Into<ShortBuf>> From<T> for PushError {
920 fn from(_: T) -> Self {
921 PushError::ShortBuf
922 }
923}
924
925impl fmt::Display for PushError {
926 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
927 match self {
928 PushError::DuplicateKey => f.write_str("duplicate key"),
929 PushError::ShortBuf => ShortBuf.fmt(f)
930 }
931 }
932}
933
934#[cfg(feature = "std")]
935impl std::error::Error for PushError {}
936
937
938#[cfg(test)]
941mod test {
942 use super::*;
943 use super::super::value;
944 use octseq::array::Array;
945
946 type Octets512 = Array<512>;
947 type Params512 = SvcParams<Array<512>>;
948 type Builder512 = SvcParamsBuilder<Array<512>>;
949
950 fn octets512(slice: impl AsRef<[u8]>) -> Octets512 {
951 Octets512::try_from(slice.as_ref()).unwrap()
952 }
953
954
955 macro_rules! parse_compose {
960 ( $rdata:expr, [ $( $value:expr )* ] ) => {
961 let mut parser = Parser::from_ref($rdata.as_ref());
963 let params = SvcParams::parse(&mut parser).unwrap();
964
965 let mut param_iter = params.iter_all();
966 $(
967 assert_eq!(
968 param_iter.next().unwrap().unwrap(),
969 AllValues::<Octets512>::from($value)
970 );
971 )*
972 assert_eq!(None, param_iter.next());
973
974 let built = Params512::from_values(|_builder| {
976 $(
977 _builder.push(&$value).unwrap();
978 )*
979 Ok(())
980 }).unwrap();
981 let mut buf = Octets512::new();
982 built.compose(&mut buf).unwrap();
983 assert_eq!($rdata.as_ref(), buf.as_ref());
984 }
985 }
986
987 #[test]
988 fn test_vectors_alias() {
989 parse_compose!(b"", []);
990 }
991
992 #[test]
993 fn test_vectors_port_only() {
994 parse_compose!(
995 b"\x00\x03\
996 \x00\x02\
997 \x00\x35",
998 [ value::Port::new(53) ]
999 );
1000 }
1001
1002 #[test]
1003 fn test_vectors_unknown_param() {
1004 parse_compose!(
1005 b"\x02\x9b\
1006 \x00\x05\
1007 \x68\x65\x6c\x6c\x6f",
1008 [
1009 UnknownSvcParam::new(
1010 0x029b.into(),
1011 octets512(b"hello")
1012 ).unwrap()
1013 ]
1014 );
1015 }
1016
1017 #[test]
1018 fn test_vectors_unknown_param_quote() {
1019 parse_compose!(
1020 b"\x02\x9b\
1021 \x00\x09\
1022 \x68\x65\x6c\x6c\x6f\xd2\x71\x6f\x6f",
1023 [
1024 UnknownSvcParam::new(
1025 0x029b.into(),
1026 octets512(b"\x68\x65\x6c\x6c\x6f\xd2\x71\x6f\x6f"),
1027 ).unwrap()
1028 ]
1029 );
1030 }
1031
1032 #[test]
1033 fn test_vectors_ipv6hint() {
1034 use crate::base::net::Ipv6Addr;
1035 use core::str::FromStr;
1036
1037 parse_compose!(
1038 b"\x00\x06\
1039 \x00\x20\
1040 \x20\x01\x0d\xb8\x00\x00\x00\x00\
1041 \x00\x00\x00\x00\x00\x00\x00\x01\
1042 \x20\x01\x0d\xb8\x00\x00\x00\x00\
1043 \x00\x00\x00\x00\x00\x53\x00\x01",
1044 [
1045 value::Ipv6Hint::<Octets512>::from_addrs([
1046 Ipv6Addr::from_str("2001:db8::1").unwrap(),
1047 Ipv6Addr::from_str("2001:db8::53:1").unwrap(),
1048 ]).unwrap()
1049 ]
1050 );
1051 }
1052
1053 #[test]
1054 fn test_vectors_ipv6hint_v4mapped() {
1055 use crate::base::net::Ipv6Addr;
1056 use core::str::FromStr;
1057
1058 parse_compose!(
1059 b"\x00\x06\
1060 \x00\x10\
1061 \x00\x00\x00\x00\x00\x00\x00\x00\
1062 \x00\x00\xff\xff\xc6\x33\x64\x64",
1063 [
1064 value::Ipv6Hint::<Octets512>::from_addrs([
1065 Ipv6Addr::from_str("::ffff:198.51.100.100").unwrap(),
1066 ]).unwrap()
1067 ]
1068 );
1069 }
1070
1071 #[cfg(feature = "std")]
1075 #[test]
1076 fn test_representation() {
1077 use crate::base::iana::svcb::SVC_PARAM_KEY_PRIVATE_RANGE_BEGIN;
1078
1079 let mandatory = value::Mandatory::<Octets512>::from_keys(
1080 [
1081 SvcParamKey::Alpn,
1082 SvcParamKey::Ipv4Hint,
1083 SVC_PARAM_KEY_PRIVATE_RANGE_BEGIN.into()
1084 ].into_iter()
1085 ).unwrap();
1086 assert_eq!(
1087 "mandatory=alpn,ipv4hint,key65280",
1088 format!("{}", mandatory)
1089 );
1090
1091 let mut alpn_builder = value::AlpnBuilder::<Octets512>::empty();
1092 alpn_builder.push("h2").unwrap();
1093 alpn_builder.push("h3-19").unwrap();
1094 assert_eq!(
1095 "alpn=h2,h3-19",
1096 format!("{}", alpn_builder.freeze())
1097 );
1098
1099 assert_eq!("nodefaultalpn", format!("{}", value::NoDefaultAlpn));
1100
1101 assert_eq!(
1102 "ech",
1103 format!(
1104 "{}",
1105 value::Ech::from_octets(Octets512::new()).unwrap()
1106 )
1107 );
1108
1109 assert_eq!(
1110 "ipv4hint=192.0.2.1,192.0.2.2",
1111 format!(
1112 "{}",
1113 value::Ipv4Hint::<Octets512>::from_addrs(
1114 [
1115 [192, 0, 2, 1].into(), [192, 0, 2, 2].into()
1116 ]
1117 ).unwrap()
1118 )
1119 );
1120 }
1121
1122
1123 #[test]
1126 fn empty_builder() {
1127 assert_eq!(
1128 Builder512::empty().freeze::<Octets512>().unwrap().as_slice(),
1129 b""
1130 );
1131 }
1132
1133 #[test]
1134 fn one_value() {
1135 let mut builder = Builder512::empty();
1136 builder.push(&value::Port::new(53)).unwrap();
1137 assert_eq!(
1138 builder.freeze::<Octets512>().unwrap().as_slice(),
1139 b"\x00\x03\x00\x02\x00\x35"
1140 );
1141 }
1142
1143 #[test]
1144 fn three_values_in_order() {
1145 let mut builder = Builder512::empty();
1146 builder.push(
1147 &UnknownSvcParam::new(1.into(), b"223").unwrap()
1148 ).unwrap();
1149 builder.push(
1150 &UnknownSvcParam::new(2.into(), b"224").unwrap()
1151 ).unwrap();
1152 builder.push(
1153 &UnknownSvcParam::new(8.into(), b"225").unwrap()
1154 ).unwrap();
1155 assert_eq!(
1156 builder.freeze::<Octets512>().unwrap().as_slice(),
1157 b"\x00\x01\x00\x03223\
1158 \x00\x02\x00\x03224\
1159 \x00\x08\x00\x03225"
1160 );
1161 }
1162
1163 #[test]
1164 fn three_values_out_of_order() {
1165 let mut builder = Builder512::empty();
1166 builder.push(
1167 &UnknownSvcParam::new(1.into(), b"223").unwrap()
1168 ).unwrap();
1169 builder.push(
1170 &UnknownSvcParam::new(8.into(), b"225").unwrap()
1171 ).unwrap();
1172 builder.push(
1173 &UnknownSvcParam::new(2.into(), b"224").unwrap()
1174 ).unwrap();
1175 assert_eq!(
1176 builder.freeze::<Octets512>().unwrap().as_slice(),
1177 b"\x00\x01\x00\x03223\
1178 \x00\x02\x00\x03224\
1179 \x00\x08\x00\x03225"
1180 );
1181 }
1182
1183 #[test]
1184 fn three_values_with_collision() {
1185 let mut builder = Builder512::empty();
1186 builder.push(
1187 &UnknownSvcParam::new(1.into(), b"223").unwrap()
1188 ).unwrap();
1189 builder.push(
1190 &UnknownSvcParam::new(8.into(), b"225").unwrap()
1191 ).unwrap();
1192 assert!(
1193 builder.push(
1194 &UnknownSvcParam::new(8.into(), b"224").unwrap()
1195 ).is_err()
1196 );
1197 }
1198}
1199