1use std::convert::Infallible;
22
23use minicbor::data::Type;
24use minicbor::{Decoder, Encoder};
25use weida_core::Error;
26
27use crate::varint::{VarintError, decode_varint, encode_varint};
28
29pub mod limits {
33 pub const MAX_ENDPOINT_BYTES: usize = 512;
35 pub const MAX_CONTENT_TYPE_BYTES: usize = 256;
37 pub const MAX_TRACEPARENT_BYTES: usize = 128;
39 pub const MAX_TRACESTATE_BYTES: usize = 512;
41 pub const MAX_TOPIC_BYTES: usize = 256;
43 pub const PRODUCER_BYTES: usize = 32;
49 pub const MAX_FILTER_BYTES: usize = 256;
51 pub const MAX_MESSAGE_BYTES: usize = 1024;
53 pub const MAX_LIST_ITEMS: usize = 64;
58 pub const MAX_REPORT_LEVELS: usize = 16;
66 pub const MAX_SKIP_DEPTH: usize = 8;
68}
69
70mod hello_key {
72 pub const VERSIONS: u64 = 0;
73 pub const MAX_HEADER_BYTES: u64 = 1;
74 pub const MAX_TRANSFERS: u64 = 2;
75 pub const CAPABILITIES: u64 = 3;
76 pub const REQUIRED_CAPABILITIES: u64 = 4;
77 pub const GUARANTEES_OFFERED: u64 = 5;
78 pub const GUARANTEES_REQUIRED: u64 = 6;
79}
80
81mod data_key {
83 pub const ENDPOINT: u64 = 0;
84 pub const CONTENT_LEN: u64 = 1;
85 pub const CONTENT_TYPE: u64 = 2;
86 pub const TRACEPARENT: u64 = 3;
87 pub const TRACESTATE: u64 = 4;
88 pub const TOPIC: u64 = 5;
89 pub const SEQUENCE: u64 = 6;
90 pub const PRODUCER: u64 = 7;
91 pub const ACHIEVED: u64 = 8;
92 pub const REPORT_ID: u64 = 9;
93 pub const REPORT: u64 = 10;
94 pub const REPORT_MODE: u64 = 11;
95 pub const SEGMENT: u64 = 13;
98}
99
100mod error_key {
102 pub const CODE: u64 = 0;
103 pub const MESSAGE: u64 = 1;
104}
105
106mod subscription_key {
108 pub const ENDPOINT: u64 = 0;
109 pub const FILTER: u64 = 1;
110 pub const MAX_AGE_MS: u64 = 2;
111}
112
113mod credit_key {
115 pub const ENDPOINT: u64 = 0;
116 pub const FILTER: u64 = 1;
117 pub const LIMIT: u64 = 2;
118}
119
120mod cursor_key {
122 pub const REPORT_ID: u64 = 0;
123}
124
125mod flow_key {
127 pub const ENDPOINT: u64 = 0;
128 pub const FLOW: u64 = 1;
129 pub const CONTENT_TYPE: u64 = 2;
130 pub const TRACEPARENT: u64 = 3;
131 pub const TRACESTATE: u64 = 4;
132 pub const TOPIC: u64 = 5;
133}
134
135pub mod filter {
150 use super::HeaderError;
151
152 pub const SEPARATOR: char = '.';
154 pub const ONE_SEGMENT: &str = "*";
156 pub const REST: &str = "#";
158
159 pub fn matches(topic: &str, filter: &str) -> bool {
181 if filter.is_empty() {
182 return true;
183 }
184 let mut topic_segments = topic.split(SEPARATOR);
185 let mut filter_segments = filter.split(SEPARATOR);
186 loop {
187 let Some(pattern) = filter_segments.next() else {
188 return topic_segments.next().is_none();
190 };
191 if pattern == REST {
194 return true;
195 }
196 let Some(segment) = topic_segments.next() else {
197 return false;
198 };
199 if pattern != ONE_SEGMENT && pattern != segment {
200 return false;
201 }
202 }
203 }
204
205 pub fn validate(filter: &str) -> Result<(), HeaderError> {
210 let mut segments = filter.split(SEPARATOR).peekable();
211 while let Some(segment) = segments.next() {
212 let is_last = segments.peek().is_none();
213 if segment.contains(ONE_SEGMENT) && segment != ONE_SEGMENT {
214 return Err(HeaderError::InvalidFilter(
215 "`*` must occupy a whole segment",
216 ));
217 }
218 if segment.contains(REST) {
219 if segment != REST {
220 return Err(HeaderError::InvalidFilter(
221 "`#` must occupy a whole segment",
222 ));
223 }
224 if !is_last {
225 return Err(HeaderError::InvalidFilter("`#` must be the final segment"));
226 }
227 }
228 }
229 Ok(())
230 }
231}
232
233mod guarantee_key {
235 pub const DELIVERY: u64 = 0;
236 pub const ACKNOWLEDGEMENT: u64 = 1;
237 pub const DURABILITY: u64 = 2;
238 pub const REPLICAS: u64 = 3;
239 pub const ORDERING: u64 = 4;
240 pub const DEDUPLICATION: u64 = 5;
241 pub const DEDUP_WINDOW_MS: u64 = 6;
242 pub const BACKPRESSURE: u64 = 7;
243 pub const PRODUCER_NAMING: u64 = 8;
244 pub const CONTROL_ISOLATED: u64 = 9;
245}
246
247macro_rules! wire_enum {
258 ($(#[$meta:meta])* $name:ident { $($(#[$vmeta:meta])* $variant:ident = $value:literal),+ $(,)? }) => {
259 $(#[$meta])*
260 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
261 pub enum $name {
262 $($(#[$vmeta])* $variant,)+
263 }
264
265 impl $name {
266 pub fn to_wire(self) -> u64 {
268 match self {
269 $($name::$variant => $value,)+
270 }
271 }
272
273 pub fn from_wire(value: u64) -> Option<$name> {
276 match value {
277 $($value => Some($name::$variant),)+
278 _ => None,
279 }
280 }
281 }
282
283 const _: () = {
288 let values = [$($value as u64),+];
289 let mut i = 1;
290 while i < values.len() {
291 assert!(
292 values[i - 1] < values[i],
293 concat!(
294 stringify!($name),
295 ": wire values must ascend with declaration order, ",
296 "because the derived Ord is the ladder"
297 )
298 );
299 i += 1;
300 }
301 };
302 };
303}
304
305wire_enum! {
306 Delivery {
310 #[default]
312 BestEffort = 0,
313 AtMostOnce = 1,
315 AtLeastOnce = 2,
317 }
318}
319
320wire_enum! {
321 Acknowledgement {
324 None = 0,
326 #[default]
328 TransportReceipt = 1,
329 Accepted = 2,
331 Stored = 3,
333 Replicated = 4,
335 Processed = 5,
337 }
338}
339
340wire_enum! {
341 Durability {
344 #[default]
346 Written = 0,
347 Flushed = 1,
349 }
350}
351
352wire_enum! {
353 OrderingMode {
355 #[default]
357 None = 0,
358 PerProducerDetect = 1,
360 PerProducerReassemble = 2,
362 PerKey = 3,
364 Total = 4,
366 }
367}
368
369wire_enum! {
370 Deduplication {
372 #[default]
374 None = 0,
375 Bounded = 1,
377 Durable = 2,
379 }
380}
381
382wire_enum! {
383 Backpressure {
386 #[default]
388 Block = 0,
389 Reject = 1,
391 Drop = 2,
393 Spill = 3,
395 Coalesce = 4,
397 }
398}
399
400wire_enum! {
401 ProducerNaming {
405 #[default]
409 Fingerprint = 0,
410 Stable = 1,
412 }
413}
414
415wire_enum! {
416 ReportMode {
425 #[default]
428 Progress = 0,
429 FinalOnly = 1,
431 }
432}
433
434#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
445pub enum CursorLevel {
446 Known(Acknowledgement),
448 Application(u64),
450}
451
452impl CursorLevel {
453 pub const APPLICATION_FLOOR: u64 = 16;
455
456 pub fn to_wire(self) -> u64 {
458 match self {
459 CursorLevel::Known(level) => level.to_wire(),
460 CursorLevel::Application(value) => value,
461 }
462 }
463
464 pub fn from_wire(value: u64) -> Option<CursorLevel> {
467 if value >= CursorLevel::APPLICATION_FLOOR {
468 Some(CursorLevel::Application(value))
469 } else {
470 Acknowledgement::from_wire(value).map(CursorLevel::Known)
471 }
472 }
473
474 pub fn application(value: u64) -> Option<CursorLevel> {
477 (value >= CursorLevel::APPLICATION_FLOOR).then_some(CursorLevel::Application(value))
478 }
479}
480
481#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
490pub struct GuaranteeSet {
491 pub delivery: Delivery,
493 pub acknowledgement: Acknowledgement,
495 pub durability: Option<Durability>,
497 pub replicas: Option<u64>,
499 pub ordering: OrderingMode,
501 pub deduplication: Deduplication,
503 pub dedup_window_ms: Option<u64>,
505 pub backpressure: Backpressure,
507 pub producer_naming: ProducerNaming,
509 pub control_isolated: bool,
513}
514
515impl GuaranteeSet {
516 pub const CORE: GuaranteeSet = GuaranteeSet {
518 delivery: Delivery::BestEffort,
519 acknowledgement: Acknowledgement::TransportReceipt,
520 durability: None,
521 replicas: None,
522 ordering: OrderingMode::None,
523 deduplication: Deduplication::None,
524 dedup_window_ms: None,
525 backpressure: Backpressure::Block,
526 producer_naming: ProducerNaming::Fingerprint,
527 control_isolated: false,
528 };
529
530 pub fn is_core(&self) -> bool {
533 *self == GuaranteeSet::CORE
534 }
535
536 fn validate(&self) -> Result<(), HeaderError> {
538 let stored_or_replicated = matches!(
539 self.acknowledgement,
540 Acknowledgement::Stored | Acknowledgement::Replicated
541 );
542 if self.durability.is_some() && !stored_or_replicated {
543 return Err(HeaderError::InvalidGuarantees(
544 "durability without Stored or Replicated",
545 ));
546 }
547 match self.replicas {
548 Some(_) if self.acknowledgement != Acknowledgement::Replicated => {
549 return Err(HeaderError::InvalidGuarantees(
550 "replicas without Replicated",
551 ));
552 }
553 Some(n) if n < 2 => {
554 return Err(HeaderError::InvalidGuarantees(
555 "a replica count below 2 is not a replication",
556 ));
557 }
558 _ => {}
559 }
560 match (self.deduplication, self.dedup_window_ms) {
561 (Deduplication::Bounded, None) => {
562 return Err(HeaderError::InvalidGuarantees(
563 "Bounded deduplication without a window",
564 ));
565 }
566 (level, Some(_)) if level != Deduplication::Bounded => {
567 return Err(HeaderError::InvalidGuarantees(
568 "a dedup window without Bounded deduplication",
569 ));
570 }
571 _ => {}
572 }
573 Ok(())
574 }
575
576 fn encode_into(
578 &self,
579 e: &mut Encoder<Vec<u8>>,
580 ) -> Result<(), minicbor::encode::Error<Infallible>> {
581 let core = GuaranteeSet::CORE;
582 let count = u64::from(self.delivery != core.delivery)
583 + u64::from(self.acknowledgement != core.acknowledgement)
584 + u64::from(self.durability.is_some())
585 + u64::from(self.replicas.is_some())
586 + u64::from(self.ordering != core.ordering)
587 + u64::from(self.deduplication != core.deduplication)
588 + u64::from(self.dedup_window_ms.is_some())
589 + u64::from(self.backpressure != core.backpressure)
590 + u64::from(self.producer_naming != core.producer_naming)
591 + u64::from(self.control_isolated != core.control_isolated);
592 e.map(count)?;
593 if self.delivery != core.delivery {
594 e.u64(guarantee_key::DELIVERY)?
595 .u64(self.delivery.to_wire())?;
596 }
597 if self.acknowledgement != core.acknowledgement {
598 e.u64(guarantee_key::ACKNOWLEDGEMENT)?
599 .u64(self.acknowledgement.to_wire())?;
600 }
601 if let Some(durability) = self.durability {
602 e.u64(guarantee_key::DURABILITY)?
603 .u64(durability.to_wire())?;
604 }
605 if let Some(replicas) = self.replicas {
606 e.u64(guarantee_key::REPLICAS)?.u64(replicas)?;
607 }
608 if self.ordering != core.ordering {
609 e.u64(guarantee_key::ORDERING)?
610 .u64(self.ordering.to_wire())?;
611 }
612 if self.deduplication != core.deduplication {
613 e.u64(guarantee_key::DEDUPLICATION)?
614 .u64(self.deduplication.to_wire())?;
615 }
616 if let Some(window) = self.dedup_window_ms {
617 e.u64(guarantee_key::DEDUP_WINDOW_MS)?.u64(window)?;
618 }
619 if self.backpressure != core.backpressure {
620 e.u64(guarantee_key::BACKPRESSURE)?
621 .u64(self.backpressure.to_wire())?;
622 }
623 if self.producer_naming != core.producer_naming {
624 e.u64(guarantee_key::PRODUCER_NAMING)?
625 .u64(self.producer_naming.to_wire())?;
626 }
627 if self.control_isolated != core.control_isolated {
628 e.u64(guarantee_key::CONTROL_ISOLATED)?
629 .u64(u64::from(self.control_isolated))?;
630 }
631 Ok(())
632 }
633
634 fn decode_from(m: &mut MapReader<'_, '_>) -> Result<GuaranteeSet, HeaderError> {
639 let mut set = GuaranteeSet::CORE;
640 let mut inner = MapReader::new(m.d)?;
641 while let Some(key) = inner.next_key()? {
642 match key {
643 guarantee_key::DELIVERY => set.delivery = level(inner.u64()?, "delivery")?,
644 guarantee_key::ACKNOWLEDGEMENT => {
645 set.acknowledgement = level(inner.u64()?, "acknowledgement")?;
646 }
647 guarantee_key::DURABILITY => {
648 set.durability = Some(level(inner.u64()?, "durability")?);
649 }
650 guarantee_key::REPLICAS => set.replicas = Some(inner.u64()?),
651 guarantee_key::ORDERING => set.ordering = level(inner.u64()?, "ordering")?,
652 guarantee_key::DEDUPLICATION => {
653 set.deduplication = level(inner.u64()?, "deduplication")?;
654 }
655 guarantee_key::DEDUP_WINDOW_MS => set.dedup_window_ms = Some(inner.u64()?),
656 guarantee_key::BACKPRESSURE => {
657 set.backpressure = level(inner.u64()?, "backpressure")?;
658 }
659 guarantee_key::PRODUCER_NAMING => {
660 set.producer_naming = level(inner.u64()?, "producer naming")?;
661 }
662 guarantee_key::CONTROL_ISOLATED => {
663 set.control_isolated = match inner.u64()? {
664 0 => false,
665 1 => true,
666 _ => {
667 return Err(HeaderError::InvalidGuarantees(
668 "control_isolated is 0 or 1",
669 ));
670 }
671 };
672 }
673 _ => inner.skip()?,
674 }
675 }
676 set.validate()?;
677 Ok(set)
678 }
679
680 pub fn intersect(&self, other: &GuaranteeSet) -> Result<GuaranteeSet, &'static str> {
689 if self.backpressure != other.backpressure {
690 return Err("backpressure");
691 }
692 if self.producer_naming != other.producer_naming {
693 return Err("producer naming");
694 }
695 if self.durability.is_some()
696 && other.durability.is_some()
697 && self.durability != other.durability
698 {
699 return Err("durability");
700 }
701 if self.replicas.is_some() && other.replicas.is_some() && self.replicas != other.replicas {
702 return Err("replicas");
703 }
704
705 let acknowledgement = self.acknowledgement.min(other.acknowledgement);
706 let keeps_durability = matches!(
707 acknowledgement,
708 Acknowledgement::Stored | Acknowledgement::Replicated
709 );
710 let deduplication = self.deduplication.min(other.deduplication);
711 let mut merged = GuaranteeSet {
712 delivery: self.delivery.min(other.delivery),
713 acknowledgement,
714 durability: keeps_durability
718 .then_some(self.durability.or(other.durability))
719 .flatten(),
720 replicas: (acknowledgement == Acknowledgement::Replicated)
721 .then_some(self.replicas.or(other.replicas))
722 .flatten(),
723 ordering: self.ordering.min(other.ordering),
724 deduplication,
725 dedup_window_ms: None,
727 backpressure: self.backpressure,
728 producer_naming: self.producer_naming,
729 control_isolated: self.control_isolated && other.control_isolated,
730 };
731 if deduplication == Deduplication::Bounded {
732 merged.dedup_window_ms = match (self.dedup_window_ms, other.dedup_window_ms) {
733 (Some(a), Some(b)) => Some(a.min(b)),
734 (Some(a), None) | (None, Some(a)) => Some(a),
735 (None, None) => None,
736 };
737 }
738 Ok(merged)
739 }
740
741 pub fn reaches(&self, required: &GuaranteeSet) -> bool {
747 if self.delivery < required.delivery
748 || self.acknowledgement < required.acknowledgement
749 || self.ordering < required.ordering
750 || self.deduplication < required.deduplication
751 {
752 return false;
753 }
754 if self.backpressure != required.backpressure
755 || self.producer_naming != required.producer_naming
756 {
757 return false;
758 }
759 if !self.control_isolated && required.control_isolated {
760 return false;
761 }
762 match (self.durability, required.durability) {
763 (_, None) => {}
764 (Some(have), Some(want)) if have >= want => {}
765 _ => return false,
766 }
767 match (self.replicas, required.replicas) {
768 (_, None) => {}
769 (Some(have), Some(want)) if have >= want => {}
770 _ => return false,
771 }
772 match (self.dedup_window_ms, required.dedup_window_ms) {
773 (_, None) => {}
774 (Some(have), Some(want)) if have >= want => {}
775 _ => return false,
776 }
777 true
778 }
779}
780
781fn level<T: WireLevel>(value: u64, dimension: &'static str) -> Result<T, HeaderError> {
783 T::from_wire_value(value).ok_or(HeaderError::UnknownLevel { dimension, value })
784}
785
786trait WireLevel: Sized {
788 fn from_wire_value(value: u64) -> Option<Self>;
789}
790
791macro_rules! impl_wire_level {
792 ($($name:ident),+ $(,)?) => {
793 $(impl WireLevel for $name {
794 fn from_wire_value(value: u64) -> Option<$name> {
795 $name::from_wire(value)
796 }
797 })+
798 };
799}
800
801impl_wire_level!(
802 Delivery,
803 Acknowledgement,
804 Durability,
805 OrderingMode,
806 Deduplication,
807 Backpressure,
808 ProducerNaming,
809 ReportMode,
810);
811
812#[derive(Clone, Debug, PartialEq, Eq)]
814pub enum HeaderError {
815 Malformed(&'static str),
817 Indefinite,
819 DuplicateKey(u64),
821 UnorderedKey(u64),
823 NonUintKey,
825 MissingKey(u64),
827 StringTooLong {
829 key: u64,
831 len: usize,
833 max: usize,
835 },
836 ListTooLong {
838 key: u64,
840 len: u64,
842 max: usize,
844 },
845 DepthExceeded,
847 TrailingBytes,
849 UnknownLevel {
852 dimension: &'static str,
854 value: u64,
856 },
857 InvalidGuarantees(&'static str),
860 InvalidFilter(&'static str),
862 InvalidReport(&'static str),
866}
867
868impl std::fmt::Display for HeaderError {
869 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
870 match self {
871 HeaderError::Malformed(what) => write!(f, "malformed header: {what}"),
872 HeaderError::Indefinite => f.write_str("indefinite-length items are not allowed"),
873 HeaderError::DuplicateKey(k) => write!(f, "duplicate header key {k}"),
874 HeaderError::UnorderedKey(k) => {
875 write!(f, "header key {k} is out of ascending order")
876 }
877 HeaderError::NonUintKey => f.write_str("header key is not an unsigned integer"),
878 HeaderError::MissingKey(k) => write!(f, "required header key {k} is missing"),
879 HeaderError::StringTooLong { key, len, max } => {
880 write!(
881 f,
882 "key {key}: text of {len} bytes exceeds the {max} byte cap"
883 )
884 }
885 HeaderError::ListTooLong { key, len, max } => {
886 write!(
887 f,
888 "key {key}: list of {len} items exceeds the {max} item cap"
889 )
890 }
891 HeaderError::DepthExceeded => f.write_str("unknown field nested too deeply"),
892 HeaderError::TrailingBytes => f.write_str("trailing bytes after the header"),
893 HeaderError::UnknownLevel { dimension, value } => {
894 write!(f, "unknown {dimension} level {value}")
895 }
896 HeaderError::InvalidGuarantees(why) => write!(f, "invalid guarantee set: {why}"),
897 HeaderError::InvalidFilter(why) => write!(f, "invalid topic filter: {why}"),
898 HeaderError::InvalidReport(reason) => write!(f, "invalid report: {reason}"),
899 }
900 }
901}
902
903impl std::error::Error for HeaderError {}
904
905impl From<HeaderError> for Error {
906 fn from(e: HeaderError) -> Error {
907 Error::Protocol(e.to_string())
908 }
909}
910
911fn encode_into_with(
919 out: &mut Vec<u8>,
920 f: impl FnOnce(&mut Encoder<Vec<u8>>) -> Result<(), minicbor::encode::Error<Infallible>>,
921) {
922 let mut e = Encoder::new(std::mem::take(out));
926 f(&mut e).expect("encoding into a Vec is infallible");
927 *out = e.into_writer();
928}
929
930fn skip_value(d: &mut Decoder<'_>, max_depth: usize) -> Result<(), HeaderError> {
937 let mut stack: Vec<u64> = Vec::new();
940 let mut remaining: u64 = 1;
941
942 loop {
943 if remaining == 0 {
944 match stack.pop() {
945 Some(outer) => {
946 remaining = outer;
947 continue;
948 }
949 None => return Ok(()),
950 }
951 }
952 remaining -= 1;
953
954 let ty = d
955 .datatype()
956 .map_err(|_| HeaderError::Malformed("truncated value"))?;
957 let nested = match ty {
958 Type::Bool => {
959 d.bool().map_err(|_| HeaderError::Malformed("bool"))?;
960 None
961 }
962 Type::Null => {
963 d.null().map_err(|_| HeaderError::Malformed("null"))?;
964 None
965 }
966 Type::Undefined => {
967 d.undefined()
968 .map_err(|_| HeaderError::Malformed("undefined"))?;
969 None
970 }
971 Type::U8
972 | Type::U16
973 | Type::U32
974 | Type::U64
975 | Type::I8
976 | Type::I16
977 | Type::I32
978 | Type::I64
979 | Type::Int => {
980 d.int().map_err(|_| HeaderError::Malformed("integer"))?;
981 None
982 }
983 Type::F32 | Type::F64 => {
984 d.f64().map_err(|_| HeaderError::Malformed("float"))?;
985 None
986 }
987 Type::Bytes => {
988 d.bytes()
989 .map_err(|_| HeaderError::Malformed("byte string"))?;
990 None
991 }
992 Type::String => {
993 d.str().map_err(|_| HeaderError::Malformed("text string"))?;
994 None
995 }
996 Type::Array => Some(
997 d.array()
998 .map_err(|_| HeaderError::Malformed("array"))?
999 .ok_or(HeaderError::Indefinite)?,
1000 ),
1001 Type::Map => {
1002 let pairs = d
1003 .map()
1004 .map_err(|_| HeaderError::Malformed("map"))?
1005 .ok_or(HeaderError::Indefinite)?;
1006 Some(
1007 pairs
1008 .checked_mul(2)
1009 .ok_or(HeaderError::Malformed("map length overflow"))?,
1010 )
1011 }
1012 Type::BytesIndef | Type::StringIndef | Type::ArrayIndef | Type::MapIndef => {
1013 return Err(HeaderError::Indefinite);
1014 }
1015 Type::Break => return Err(HeaderError::Malformed("unexpected break")),
1016 Type::Tag => return Err(HeaderError::Malformed("tags are not allowed")),
1019 Type::F16 => return Err(HeaderError::Malformed("half floats are not allowed")),
1020 Type::Simple => return Err(HeaderError::Malformed("simple values are not allowed")),
1021 Type::Unknown(_) => return Err(HeaderError::Malformed("unknown major type")),
1022 };
1023
1024 if let Some(count) = nested
1025 && count > 0
1026 {
1027 if stack.len() >= max_depth {
1028 return Err(HeaderError::DepthExceeded);
1029 }
1030 stack.push(remaining);
1031 remaining = count;
1032 }
1033 }
1034}
1035
1036struct MapReader<'a, 'b> {
1038 d: &'a mut Decoder<'b>,
1039 remaining: u64,
1040 seen: u64,
1043 last: Option<u64>,
1050}
1051
1052impl<'a, 'b> MapReader<'a, 'b> {
1053 fn new(d: &'a mut Decoder<'b>) -> Result<MapReader<'a, 'b>, HeaderError> {
1054 let len = d
1055 .map()
1056 .map_err(|_| HeaderError::Malformed("header is not a map"))?
1057 .ok_or(HeaderError::Indefinite)?;
1058 Ok(MapReader {
1059 d,
1060 remaining: len,
1061 seen: 0,
1062 last: None,
1063 })
1064 }
1065
1066 fn next_key(&mut self) -> Result<Option<u64>, HeaderError> {
1067 if self.remaining == 0 {
1068 return Ok(None);
1069 }
1070 self.remaining -= 1;
1071 match self.d.datatype() {
1072 Ok(Type::U8 | Type::U16 | Type::U32 | Type::U64) => {}
1073 Ok(_) => return Err(HeaderError::NonUintKey),
1074 Err(_) => return Err(HeaderError::Malformed("truncated key")),
1075 }
1076 let key = self.d.u64().map_err(|_| HeaderError::NonUintKey)?;
1077 if let Some(prev) = self.last {
1078 if key == prev {
1079 return Err(HeaderError::DuplicateKey(key));
1080 }
1081 if key < prev {
1082 return Err(HeaderError::UnorderedKey(key));
1083 }
1084 }
1085 self.last = Some(key);
1086 if key < 64 {
1087 self.seen |= 1u64 << key;
1088 }
1089 Ok(Some(key))
1090 }
1091
1092 fn saw(&self, key: u64) -> bool {
1093 key < 64 && self.seen & (1u64 << key) != 0
1094 }
1095
1096 fn require(&self, key: u64) -> Result<(), HeaderError> {
1097 if self.saw(key) {
1098 Ok(())
1099 } else {
1100 Err(HeaderError::MissingKey(key))
1101 }
1102 }
1103
1104 fn u64(&mut self) -> Result<u64, HeaderError> {
1105 self.d
1106 .u64()
1107 .map_err(|_| HeaderError::Malformed("expected an unsigned integer"))
1108 }
1109
1110 fn text(&mut self, key: u64, max: usize) -> Result<String, HeaderError> {
1111 let s = self
1112 .d
1113 .str()
1114 .map_err(|_| HeaderError::Malformed("expected a text string"))?;
1115 if s.len() > max {
1116 return Err(HeaderError::StringTooLong {
1117 key,
1118 len: s.len(),
1119 max,
1120 });
1121 }
1122 Ok(s.to_owned())
1123 }
1124
1125 fn byte_array<const N: usize>(&mut self, key: u64) -> Result<[u8; N], HeaderError> {
1132 let bytes = self
1133 .d
1134 .bytes()
1135 .map_err(|_| HeaderError::Malformed("expected a byte string"))?;
1136 if bytes.len() > N {
1137 return Err(HeaderError::StringTooLong {
1138 key,
1139 len: bytes.len(),
1140 max: N,
1141 });
1142 }
1143 bytes
1144 .try_into()
1145 .map_err(|_| HeaderError::Malformed("byte string has the wrong length"))
1146 }
1147
1148 fn uint_list(&mut self, key: u64) -> Result<Vec<u64>, HeaderError> {
1149 let len = self
1150 .d
1151 .array()
1152 .map_err(|_| HeaderError::Malformed("expected an array"))?
1153 .ok_or(HeaderError::Indefinite)?;
1154 if len > limits::MAX_LIST_ITEMS as u64 {
1155 return Err(HeaderError::ListTooLong {
1156 key,
1157 len,
1158 max: limits::MAX_LIST_ITEMS,
1159 });
1160 }
1161 let mut out = Vec::with_capacity(len as usize);
1163 for _ in 0..len {
1164 out.push(self.u64()?);
1165 }
1166 Ok(out)
1167 }
1168
1169 fn report_levels(&mut self) -> Result<Vec<CursorLevel>, HeaderError> {
1177 let len = self
1178 .d
1179 .array()
1180 .map_err(|_| HeaderError::Malformed("expected an array"))?
1181 .ok_or(HeaderError::Indefinite)?;
1182 if len > limits::MAX_REPORT_LEVELS as u64 {
1183 return Err(HeaderError::InvalidReport("too many report levels"));
1184 }
1185 let mut out: Vec<CursorLevel> = Vec::with_capacity(len as usize);
1187 let mut last: Option<u64> = None;
1188 for _ in 0..len {
1189 let value = self.u64()?;
1190 if let Some(prev) = last
1191 && value <= prev
1192 {
1193 return Err(HeaderError::InvalidReport("report levels must ascend"));
1194 }
1195 last = Some(value);
1196 out.push(
1197 CursorLevel::from_wire(value).ok_or(HeaderError::UnknownLevel {
1198 dimension: "report",
1199 value,
1200 })?,
1201 );
1202 }
1203 Ok(out)
1204 }
1205
1206 fn skip(&mut self) -> Result<(), HeaderError> {
1207 skip_value(self.d, limits::MAX_SKIP_DEPTH)
1208 }
1209}
1210
1211fn finish(d: &Decoder<'_>) -> Result<(), HeaderError> {
1213 if d.position() == d.input().len() {
1214 Ok(())
1215 } else {
1216 Err(HeaderError::TrailingBytes)
1217 }
1218}
1219
1220#[derive(Clone, Debug, PartialEq, Eq)]
1222pub struct Hello {
1223 pub versions: Vec<u64>,
1225 pub max_header_bytes: u64,
1227 pub max_transfers: u64,
1229 pub capabilities: Vec<u64>,
1231 pub required_capabilities: Vec<u64>,
1233 pub guarantees_offered: Option<GuaranteeSet>,
1239 pub guarantees_required: Option<GuaranteeSet>,
1245}
1246
1247impl Hello {
1248 pub fn v0(max_header_bytes: u64, max_transfers: u64) -> Hello {
1251 Hello {
1252 versions: vec![crate::VERSION],
1253 max_header_bytes,
1254 max_transfers,
1255 capabilities: Vec::new(),
1256 required_capabilities: Vec::new(),
1257 guarantees_offered: None,
1258 guarantees_required: None,
1259 }
1260 }
1261
1262 pub fn offered(&self) -> GuaranteeSet {
1264 self.guarantees_offered.unwrap_or(GuaranteeSet::CORE)
1265 }
1266
1267 pub fn required(&self) -> GuaranteeSet {
1269 self.guarantees_required.unwrap_or(GuaranteeSet::CORE)
1270 }
1271
1272 pub fn encode(&self) -> Vec<u8> {
1274 let mut out = Vec::new();
1275 self.encode_into(&mut out);
1276 out
1277 }
1278
1279 pub fn encode_into(&self, out: &mut Vec<u8>) {
1283 encode_into_with(out, |e| {
1284 let offered = self.guarantees_offered.filter(|s| !s.is_core());
1287 let required = self.guarantees_required.filter(|s| !s.is_core());
1288 e.map(5 + u64::from(offered.is_some()) + u64::from(required.is_some()))?;
1289 e.u64(hello_key::VERSIONS)?
1290 .array(self.versions.len() as u64)?;
1291 for v in &self.versions {
1292 e.u64(*v)?;
1293 }
1294 e.u64(hello_key::MAX_HEADER_BYTES)?
1295 .u64(self.max_header_bytes)?;
1296 e.u64(hello_key::MAX_TRANSFERS)?.u64(self.max_transfers)?;
1297 e.u64(hello_key::CAPABILITIES)?
1298 .array(self.capabilities.len() as u64)?;
1299 for c in &self.capabilities {
1300 e.u64(*c)?;
1301 }
1302 e.u64(hello_key::REQUIRED_CAPABILITIES)?
1303 .array(self.required_capabilities.len() as u64)?;
1304 for c in &self.required_capabilities {
1305 e.u64(*c)?;
1306 }
1307 if let Some(set) = offered {
1308 e.u64(hello_key::GUARANTEES_OFFERED)?;
1309 set.encode_into(e)?;
1310 }
1311 if let Some(set) = required {
1312 e.u64(hello_key::GUARANTEES_REQUIRED)?;
1313 set.encode_into(e)?;
1314 }
1315 Ok(())
1316 })
1317 }
1318
1319 pub fn decode(bytes: &[u8]) -> Result<Hello, HeaderError> {
1321 let mut d = Decoder::new(bytes);
1322 let mut versions = Vec::new();
1323 let mut max_header_bytes = 0;
1324 let mut max_transfers = 0;
1325 let mut capabilities = Vec::new();
1326 let mut required_capabilities = Vec::new();
1327 let mut guarantees_offered = None;
1328 let mut guarantees_required = None;
1329 {
1330 let mut m = MapReader::new(&mut d)?;
1331 while let Some(key) = m.next_key()? {
1332 match key {
1333 hello_key::VERSIONS => versions = m.uint_list(key)?,
1334 hello_key::MAX_HEADER_BYTES => max_header_bytes = m.u64()?,
1335 hello_key::MAX_TRANSFERS => max_transfers = m.u64()?,
1336 hello_key::CAPABILITIES => capabilities = m.uint_list(key)?,
1337 hello_key::REQUIRED_CAPABILITIES => required_capabilities = m.uint_list(key)?,
1338 hello_key::GUARANTEES_OFFERED => {
1339 guarantees_offered = Some(GuaranteeSet::decode_from(&mut m)?);
1340 }
1341 hello_key::GUARANTEES_REQUIRED => {
1342 guarantees_required = Some(GuaranteeSet::decode_from(&mut m)?);
1343 }
1344 _ => m.skip()?,
1345 }
1346 }
1347 for key in [
1348 hello_key::VERSIONS,
1349 hello_key::MAX_HEADER_BYTES,
1350 hello_key::MAX_TRANSFERS,
1351 hello_key::CAPABILITIES,
1352 hello_key::REQUIRED_CAPABILITIES,
1353 ] {
1354 m.require(key)?;
1355 }
1356 }
1357 finish(&d)?;
1358 let hello = Hello {
1359 versions,
1360 max_header_bytes,
1361 max_transfers,
1362 capabilities,
1363 required_capabilities,
1364 guarantees_offered,
1365 guarantees_required,
1366 };
1367 if !hello.offered().reaches(&hello.required()) {
1370 return Err(HeaderError::InvalidGuarantees(
1371 "guarantees_required is not covered by guarantees_offered",
1372 ));
1373 }
1374 Ok(hello)
1375 }
1376}
1377
1378#[derive(Clone, Debug, Default, PartialEq, Eq)]
1385pub struct DataHeader {
1386 pub endpoint: Option<String>,
1388 pub content_len: Option<u64>,
1390 pub content_type: Option<String>,
1392 pub traceparent: Option<String>,
1394 pub tracestate: Option<String>,
1396 pub topic: Option<String>,
1400 pub sequence: Option<u64>,
1409 pub producer: Option<[u8; limits::PRODUCER_BYTES]>,
1420 pub achieved: Option<Acknowledgement>,
1442 pub report_id: Option<u64>,
1449 pub report: Vec<CursorLevel>,
1458 pub report_mode: ReportMode,
1462 pub segment: Option<u64>,
1470}
1471
1472impl DataHeader {
1473 pub fn addressed(endpoint: impl Into<String>) -> DataHeader {
1475 DataHeader {
1476 endpoint: Some(endpoint.into()),
1477 ..DataHeader::default()
1478 }
1479 }
1480
1481 pub fn reply() -> DataHeader {
1486 DataHeader::default()
1487 }
1488
1489 pub fn encode(&self) -> Vec<u8> {
1506 let mut out = Vec::new();
1507 self.encode_into(&mut out);
1508 out
1509 }
1510
1511 pub fn encode_into(&self, out: &mut Vec<u8>) {
1515 let mut report: Vec<u64> = self.report.iter().map(|level| level.to_wire()).collect();
1518 report.sort_unstable();
1519 report.dedup();
1520 let count = u64::from(self.endpoint.is_some())
1521 + u64::from(self.content_len.is_some())
1522 + u64::from(self.content_type.is_some())
1523 + u64::from(self.traceparent.is_some())
1524 + u64::from(self.tracestate.is_some())
1525 + u64::from(self.topic.is_some())
1526 + u64::from(self.sequence.is_some())
1527 + u64::from(self.producer.is_some())
1528 + u64::from(self.achieved.is_some())
1529 + u64::from(self.report_id.is_some())
1530 + u64::from(!report.is_empty())
1531 + u64::from(self.report_mode != ReportMode::default())
1532 + u64::from(self.segment.is_some());
1533 encode_into_with(out, |e| {
1534 e.map(count)?;
1535 if let Some(endpoint) = &self.endpoint {
1536 e.u64(data_key::ENDPOINT)?.str(endpoint)?;
1537 }
1538 if let Some(len) = self.content_len {
1539 e.u64(data_key::CONTENT_LEN)?.u64(len)?;
1540 }
1541 if let Some(ct) = &self.content_type {
1542 e.u64(data_key::CONTENT_TYPE)?.str(ct)?;
1543 }
1544 if let Some(tp) = &self.traceparent {
1545 e.u64(data_key::TRACEPARENT)?.str(tp)?;
1546 }
1547 if let Some(ts) = &self.tracestate {
1548 e.u64(data_key::TRACESTATE)?.str(ts)?;
1549 }
1550 if let Some(topic) = &self.topic {
1551 e.u64(data_key::TOPIC)?.str(topic)?;
1552 }
1553 if let Some(sequence) = self.sequence {
1556 e.u64(data_key::SEQUENCE)?.u64(sequence)?;
1557 }
1558 if let Some(producer) = &self.producer {
1559 e.u64(data_key::PRODUCER)?.bytes(producer)?;
1560 }
1561 if let Some(achieved) = self.achieved {
1562 e.u64(data_key::ACHIEVED)?.u64(achieved.to_wire())?;
1563 }
1564 if let Some(report_id) = self.report_id {
1565 e.u64(data_key::REPORT_ID)?.u64(report_id)?;
1566 }
1567 if !report.is_empty() {
1568 e.u64(data_key::REPORT)?.array(report.len() as u64)?;
1569 for value in &report {
1570 e.u64(*value)?;
1571 }
1572 }
1573 if self.report_mode != ReportMode::default() {
1577 e.u64(data_key::REPORT_MODE)?
1578 .u64(self.report_mode.to_wire())?;
1579 }
1580 if let Some(segment) = self.segment {
1581 e.u64(data_key::SEGMENT)?.u64(segment)?;
1582 }
1583 Ok(())
1584 })
1585 }
1586
1587 pub fn decode(bytes: &[u8]) -> Result<DataHeader, HeaderError> {
1589 let mut d = Decoder::new(bytes);
1590 let mut header = DataHeader::default();
1591 {
1592 let mut m = MapReader::new(&mut d)?;
1593 while let Some(key) = m.next_key()? {
1594 match key {
1595 data_key::ENDPOINT => {
1596 header.endpoint = Some(m.text(key, limits::MAX_ENDPOINT_BYTES)?)
1597 }
1598 data_key::CONTENT_LEN => header.content_len = Some(m.u64()?),
1599 data_key::CONTENT_TYPE => {
1600 header.content_type = Some(m.text(key, limits::MAX_CONTENT_TYPE_BYTES)?)
1601 }
1602 data_key::TRACEPARENT => {
1603 header.traceparent = Some(m.text(key, limits::MAX_TRACEPARENT_BYTES)?)
1604 }
1605 data_key::TRACESTATE => {
1606 header.tracestate = Some(m.text(key, limits::MAX_TRACESTATE_BYTES)?)
1607 }
1608 data_key::TOPIC => header.topic = Some(m.text(key, limits::MAX_TOPIC_BYTES)?),
1609 data_key::SEQUENCE => header.sequence = Some(m.u64()?),
1610 data_key::PRODUCER => header.producer = Some(m.byte_array(key)?),
1611 data_key::ACHIEVED => {
1616 let value = m.u64()?;
1617 header.achieved = Some(Acknowledgement::from_wire(value).ok_or(
1618 HeaderError::UnknownLevel {
1619 dimension: "achieved",
1620 value,
1621 },
1622 )?);
1623 }
1624 data_key::REPORT_ID => header.report_id = Some(m.u64()?),
1625 data_key::REPORT => header.report = m.report_levels()?,
1626 data_key::REPORT_MODE => {
1627 header.report_mode = level(m.u64()?, "report_mode")?;
1628 }
1629 data_key::SEGMENT => header.segment = Some(m.u64()?),
1630 _ => m.skip()?,
1631 }
1632 }
1633 }
1634 finish(&d)?;
1635 if !header.report.is_empty() && header.report_id.is_none() {
1639 return Err(HeaderError::InvalidReport("report without report_id"));
1640 }
1641 if header.report_id.is_some() && header.report.is_empty() {
1642 return Err(HeaderError::InvalidReport("report_id without report"));
1643 }
1644 Ok(header)
1645 }
1646}
1647
1648#[derive(Clone, Debug, PartialEq, Eq)]
1653pub struct ErrorHeader {
1654 pub code: u64,
1656 pub message: Option<String>,
1658}
1659
1660impl ErrorHeader {
1661 pub fn new(code: weida_core::ErrorCode) -> ErrorHeader {
1663 ErrorHeader {
1664 code: code.to_wire(),
1665 message: None,
1666 }
1667 }
1668
1669 pub fn error_code(&self) -> Option<weida_core::ErrorCode> {
1671 weida_core::ErrorCode::from_wire(self.code)
1672 }
1673
1674 pub fn encode(&self) -> Vec<u8> {
1676 let mut out = Vec::new();
1677 self.encode_into(&mut out);
1678 out
1679 }
1680
1681 pub fn encode_into(&self, out: &mut Vec<u8>) {
1685 let count = 1 + u64::from(self.message.is_some());
1686 encode_into_with(out, |e| {
1687 e.map(count)?;
1688 e.u64(error_key::CODE)?.u64(self.code)?;
1689 if let Some(msg) = &self.message {
1690 e.u64(error_key::MESSAGE)?.str(msg)?;
1691 }
1692 Ok(())
1693 })
1694 }
1695
1696 pub fn decode(bytes: &[u8]) -> Result<ErrorHeader, HeaderError> {
1698 let mut d = Decoder::new(bytes);
1699 let mut code = 0;
1700 let mut message = None;
1701 {
1702 let mut m = MapReader::new(&mut d)?;
1703 while let Some(key) = m.next_key()? {
1704 match key {
1705 error_key::CODE => code = m.u64()?,
1706 error_key::MESSAGE => message = Some(m.text(key, limits::MAX_MESSAGE_BYTES)?),
1707 _ => m.skip()?,
1708 }
1709 }
1710 m.require(error_key::CODE)?;
1711 }
1712 finish(&d)?;
1713 Ok(ErrorHeader { code, message })
1714 }
1715}
1716
1717#[derive(Clone, Debug, PartialEq, Eq)]
1724pub struct SubscriptionHeader {
1725 pub endpoint: String,
1727 pub filter: String,
1730 pub max_age_ms: Option<u64>,
1735}
1736
1737impl SubscriptionHeader {
1738 pub fn new(endpoint: impl Into<String>, filter: impl Into<String>) -> SubscriptionHeader {
1740 SubscriptionHeader {
1741 endpoint: endpoint.into(),
1742 filter: filter.into(),
1743 max_age_ms: None,
1744 }
1745 }
1746
1747 pub fn encode(&self) -> Vec<u8> {
1749 let mut out = Vec::new();
1750 self.encode_into(&mut out);
1751 out
1752 }
1753
1754 pub fn encode_into(&self, out: &mut Vec<u8>) {
1758 encode_into_with(out, |e| {
1763 e.map(2 + u64::from(self.max_age_ms.is_some()))?;
1764 e.u64(subscription_key::ENDPOINT)?.str(&self.endpoint)?;
1765 e.u64(subscription_key::FILTER)?.str(&self.filter)?;
1766 if let Some(max_age_ms) = self.max_age_ms {
1767 e.u64(subscription_key::MAX_AGE_MS)?.u64(max_age_ms)?;
1768 }
1769 Ok(())
1770 })
1771 }
1772
1773 pub fn decode(bytes: &[u8]) -> Result<SubscriptionHeader, HeaderError> {
1775 let mut d = Decoder::new(bytes);
1776 let mut endpoint = None;
1777 let mut filter = None;
1778 let mut max_age_ms = None;
1779 {
1780 let mut m = MapReader::new(&mut d)?;
1781 while let Some(key) = m.next_key()? {
1782 match key {
1783 subscription_key::ENDPOINT => {
1784 endpoint = Some(m.text(key, limits::MAX_ENDPOINT_BYTES)?)
1785 }
1786 subscription_key::FILTER => {
1787 filter = Some(m.text(key, limits::MAX_FILTER_BYTES)?)
1788 }
1789 subscription_key::MAX_AGE_MS => max_age_ms = Some(m.u64()?),
1790 _ => m.skip()?,
1791 }
1792 }
1793 m.require(subscription_key::ENDPOINT)?;
1794 m.require(subscription_key::FILTER)?;
1795 }
1796 let filter = filter.expect("presence checked above");
1801 filter::validate(&filter)?;
1802 finish(&d)?;
1803 Ok(SubscriptionHeader {
1804 endpoint: endpoint.expect("presence checked above"),
1805 filter,
1806 max_age_ms,
1807 })
1808 }
1809}
1810
1811#[derive(Clone, Debug, PartialEq, Eq)]
1818pub struct FlowHeader {
1819 pub endpoint: String,
1821 pub flow: u64,
1824 pub content_type: Option<String>,
1826 pub traceparent: Option<String>,
1828 pub tracestate: Option<String>,
1830 pub topic: Option<String>,
1832}
1833
1834impl FlowHeader {
1835 pub fn new(endpoint: impl Into<String>, flow: u64) -> FlowHeader {
1837 FlowHeader {
1838 endpoint: endpoint.into(),
1839 flow,
1840 content_type: None,
1841 traceparent: None,
1842 tracestate: None,
1843 topic: None,
1844 }
1845 }
1846
1847 pub fn encode(&self) -> Vec<u8> {
1849 let mut out = Vec::new();
1850 self.encode_into(&mut out);
1851 out
1852 }
1853
1854 pub fn encode_into(&self, out: &mut Vec<u8>) {
1857 let count = 2
1858 + u64::from(self.content_type.is_some())
1859 + u64::from(self.traceparent.is_some())
1860 + u64::from(self.tracestate.is_some())
1861 + u64::from(self.topic.is_some());
1862 encode_into_with(out, |e| {
1863 e.map(count)?;
1864 e.u64(flow_key::ENDPOINT)?.str(&self.endpoint)?;
1865 e.u64(flow_key::FLOW)?.u64(self.flow)?;
1866 if let Some(ct) = &self.content_type {
1867 e.u64(flow_key::CONTENT_TYPE)?.str(ct)?;
1868 }
1869 if let Some(tp) = &self.traceparent {
1870 e.u64(flow_key::TRACEPARENT)?.str(tp)?;
1871 }
1872 if let Some(ts) = &self.tracestate {
1873 e.u64(flow_key::TRACESTATE)?.str(ts)?;
1874 }
1875 if let Some(topic) = &self.topic {
1876 e.u64(flow_key::TOPIC)?.str(topic)?;
1877 }
1878 Ok(())
1879 })
1880 }
1881
1882 pub fn decode(bytes: &[u8]) -> Result<FlowHeader, HeaderError> {
1884 let mut d = Decoder::new(bytes);
1885 let mut endpoint = None;
1886 let mut flow = None;
1887 let mut content_type = None;
1888 let mut traceparent = None;
1889 let mut tracestate = None;
1890 let mut topic = None;
1891 {
1892 let mut m = MapReader::new(&mut d)?;
1893 while let Some(key) = m.next_key()? {
1894 match key {
1895 flow_key::ENDPOINT => endpoint = Some(m.text(key, limits::MAX_ENDPOINT_BYTES)?),
1896 flow_key::FLOW => flow = Some(m.u64()?),
1897 flow_key::CONTENT_TYPE => {
1898 content_type = Some(m.text(key, limits::MAX_CONTENT_TYPE_BYTES)?)
1899 }
1900 flow_key::TRACEPARENT => {
1901 traceparent = Some(m.text(key, limits::MAX_TRACEPARENT_BYTES)?)
1902 }
1903 flow_key::TRACESTATE => {
1904 tracestate = Some(m.text(key, limits::MAX_TRACESTATE_BYTES)?)
1905 }
1906 flow_key::TOPIC => topic = Some(m.text(key, limits::MAX_TOPIC_BYTES)?),
1907 _ => m.skip()?,
1908 }
1909 }
1910 m.require(flow_key::ENDPOINT)?;
1911 m.require(flow_key::FLOW)?;
1912 }
1913 finish(&d)?;
1914 Ok(FlowHeader {
1915 endpoint: endpoint.expect("presence checked above"),
1916 flow: flow.expect("presence checked above"),
1917 content_type,
1918 traceparent,
1919 tracestate,
1920 topic,
1921 })
1922 }
1923}
1924
1925#[derive(Clone, Debug, PartialEq, Eq)]
1949pub struct CreditHeader {
1950 pub endpoint: String,
1952 pub filter: String,
1955 pub limit: u64,
1958}
1959
1960impl CreditHeader {
1961 pub fn new(endpoint: impl Into<String>, filter: impl Into<String>, limit: u64) -> CreditHeader {
1963 CreditHeader {
1964 endpoint: endpoint.into(),
1965 filter: filter.into(),
1966 limit,
1967 }
1968 }
1969
1970 pub fn encode(&self) -> Vec<u8> {
1972 let mut out = Vec::new();
1973 self.encode_into(&mut out);
1974 out
1975 }
1976
1977 pub fn encode_into(&self, out: &mut Vec<u8>) {
1981 encode_into_with(out, |e| {
1982 e.map(3)?;
1983 e.u64(credit_key::ENDPOINT)?.str(&self.endpoint)?;
1984 e.u64(credit_key::FILTER)?.str(&self.filter)?;
1985 e.u64(credit_key::LIMIT)?.u64(self.limit)?;
1986 Ok(())
1987 })
1988 }
1989
1990 pub fn decode(bytes: &[u8]) -> Result<CreditHeader, HeaderError> {
1992 let mut d = Decoder::new(bytes);
1993 let mut endpoint = None;
1994 let mut filter = None;
1995 let mut limit = None;
1996 {
1997 let mut m = MapReader::new(&mut d)?;
1998 while let Some(key) = m.next_key()? {
1999 match key {
2000 credit_key::ENDPOINT => {
2001 endpoint = Some(m.text(key, limits::MAX_ENDPOINT_BYTES)?)
2002 }
2003 credit_key::FILTER => filter = Some(m.text(key, limits::MAX_FILTER_BYTES)?),
2004 credit_key::LIMIT => limit = Some(m.u64()?),
2005 _ => m.skip()?,
2006 }
2007 }
2008 m.require(credit_key::ENDPOINT)?;
2009 m.require(credit_key::FILTER)?;
2010 m.require(credit_key::LIMIT)?;
2011 }
2012 let filter = filter.expect("presence checked above");
2015 filter::validate(&filter)?;
2016 finish(&d)?;
2017 Ok(CreditHeader {
2018 endpoint: endpoint.expect("presence checked above"),
2019 filter,
2020 limit: limit.expect("presence checked above"),
2021 })
2022 }
2023}
2024
2025#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2033pub struct CursorHeader {
2034 pub report_id: u64,
2036}
2037
2038impl CursorHeader {
2039 pub fn encode(&self) -> Vec<u8> {
2041 let mut out = Vec::new();
2042 self.encode_into(&mut out);
2043 out
2044 }
2045
2046 pub fn encode_into(&self, out: &mut Vec<u8>) {
2050 encode_into_with(out, |e| {
2051 e.map(1)?;
2052 e.u64(cursor_key::REPORT_ID)?.u64(self.report_id)?;
2053 Ok(())
2054 })
2055 }
2056
2057 pub fn decode(bytes: &[u8]) -> Result<CursorHeader, HeaderError> {
2059 let mut d = Decoder::new(bytes);
2060 let mut report_id = None;
2061 {
2062 let mut m = MapReader::new(&mut d)?;
2063 while let Some(key) = m.next_key()? {
2064 match key {
2065 cursor_key::REPORT_ID => report_id = Some(m.u64()?),
2066 _ => m.skip()?,
2067 }
2068 }
2069 m.require(cursor_key::REPORT_ID)?;
2070 }
2071 finish(&d)?;
2072 Ok(CursorHeader {
2073 report_id: report_id.expect("presence checked above"),
2074 })
2075 }
2076}
2077
2078pub const MAX_CURSOR_RECORD_LEN: usize = 2 * crate::varint::MAX_ENCODED_LEN;
2080
2081pub fn encode_cursor_record(
2088 level: CursorLevel,
2089 offset: u64,
2090 out: &mut Vec<u8>,
2091) -> Result<(), VarintError> {
2092 encode_varint(level.to_wire(), out)?;
2093 encode_varint(offset, out)
2094}
2095
2096pub fn decode_cursor_record(
2105 input: &[u8],
2106) -> Result<Option<(CursorLevel, u64, usize)>, HeaderError> {
2107 let Ok((raw_level, level_len)) = decode_varint(input) else {
2110 return Ok(None);
2111 };
2112 let Ok((offset, offset_len)) = decode_varint(&input[level_len..]) else {
2113 return Ok(None);
2114 };
2115 let level = CursorLevel::from_wire(raw_level).ok_or(HeaderError::UnknownLevel {
2116 dimension: "cursor",
2117 value: raw_level,
2118 })?;
2119 Ok(Some((level, offset, level_len + offset_len)))
2120}
2121
2122#[cfg(test)]
2123mod tests {
2124 fn encode_with(
2127 f: impl FnOnce(
2128 &mut minicbor::Encoder<Vec<u8>>,
2129 ) -> Result<(), minicbor::encode::Error<std::convert::Infallible>>,
2130 ) -> Vec<u8> {
2131 let mut out = Vec::new();
2132 super::encode_into_with(&mut out, f);
2133 out
2134 }
2135
2136 use super::*;
2137 use weida_core::ErrorCode;
2138
2139 #[test]
2142 fn golden_data_request_header() {
2143 let h = DataHeader::addressed("/t");
2144 let bytes = h.encode();
2145 assert_eq!(bytes, vec![0xA1, 0x00, 0x62, 0x2F, 0x74]);
2146 assert_eq!(bytes.len(), 0x05);
2147 assert_eq!(DataHeader::decode(&bytes).unwrap(), h);
2148 }
2149
2150 #[test]
2151 fn golden_data_reply_header() {
2152 let h = DataHeader::reply();
2154 let bytes = h.encode();
2155 assert_eq!(bytes, vec![0xA0]);
2156 assert_eq!(bytes.len(), 0x01);
2157 assert_eq!(DataHeader::decode(&bytes).unwrap(), h);
2158 }
2159
2160 #[test]
2161 fn golden_hello_header() {
2162 let h = Hello::v0(16384, 1024);
2163 let bytes = h.encode();
2164 assert_eq!(
2165 bytes,
2166 vec![
2167 0xA5, 0x00, 0x81, 0x00, 0x01, 0x19, 0x40, 0x00, 0x02, 0x19, 0x04, 0x00, 0x03, 0x80,
2168 0x04, 0x80
2169 ]
2170 );
2171 assert_eq!(bytes.len(), 0x10);
2172 assert_eq!(Hello::decode(&bytes).unwrap(), h);
2173 }
2174
2175 #[test]
2176 fn golden_error_header() {
2177 let h = ErrorHeader::new(ErrorCode::NoReply);
2178 let bytes = h.encode();
2179 assert_eq!(bytes, vec![0xA1, 0x00, 0x05]);
2180 assert_eq!(bytes.len(), 0x03);
2181 assert_eq!(ErrorHeader::decode(&bytes).unwrap(), h);
2182 }
2183
2184 #[test]
2185 fn golden_pub_copy_data_header() {
2186 let mut h = DataHeader::addressed("/md");
2187 h.topic = Some("px.eur".into());
2188 let bytes = h.encode();
2189 assert_eq!(
2190 bytes,
2191 vec![
2192 0xA2, 0x00, 0x63, 0x2F, 0x6D, 0x64, 0x05, 0x66, 0x70, 0x78, 0x2E, 0x65, 0x75, 0x72
2193 ]
2194 );
2195 assert_eq!(bytes.len(), 0x0E);
2196 assert_eq!(DataHeader::decode(&bytes).unwrap(), h);
2197 }
2198
2199 const VECTOR_PRODUCER: [u8; limits::PRODUCER_BYTES] = [
2202 0x9F, 0x86, 0xD0, 0x81, 0x88, 0x4C, 0x7D, 0x65, 0x9A, 0x2F, 0xEA, 0xA0, 0xC5, 0x5A, 0xD0,
2203 0x15, 0xA3, 0xBF, 0x4F, 0x1B, 0x2B, 0x0B, 0x82, 0x2C, 0xD1, 0x5D, 0x6C, 0x15, 0xB0, 0xF0,
2204 0x0A, 0x08,
2205 ];
2206
2207 #[test]
2208 fn golden_sequenced_data_header() {
2209 let mut h = DataHeader::addressed("/t");
2210 h.sequence = Some(1);
2211 let bytes = h.encode();
2212 assert_eq!(bytes, vec![0xA2, 0x00, 0x62, 0x2F, 0x74, 0x06, 0x01]);
2213 assert_eq!(bytes.len(), 0x07);
2214 assert_eq!(DataHeader::decode(&bytes).unwrap(), h);
2215 }
2216
2217 #[test]
2218 fn golden_relayed_data_header() {
2219 let mut h = DataHeader::addressed("/t");
2220 h.sequence = Some(1);
2221 h.producer = Some(VECTOR_PRODUCER);
2222 let bytes = h.encode();
2223 let mut expected = vec![0xA3, 0x00, 0x62, 0x2F, 0x74, 0x06, 0x01, 0x07, 0x58, 0x20];
2224 expected.extend_from_slice(&VECTOR_PRODUCER);
2225 assert_eq!(bytes, expected);
2226 assert_eq!(bytes.len(), 0x2A);
2227 assert_eq!(DataHeader::decode(&bytes).unwrap(), h);
2228 }
2229
2230 #[test]
2231 fn a_producer_longer_than_the_cap_is_rejected() {
2232 let bytes = encode_with(|e| {
2233 e.map(1)?;
2234 e.u64(data_key::PRODUCER)?
2235 .bytes(&[0u8; limits::PRODUCER_BYTES + 1])?;
2236 Ok(())
2237 });
2238 assert_eq!(
2239 DataHeader::decode(&bytes),
2240 Err(HeaderError::StringTooLong {
2241 key: data_key::PRODUCER,
2242 len: limits::PRODUCER_BYTES + 1,
2243 max: limits::PRODUCER_BYTES,
2244 })
2245 );
2246 }
2247
2248 #[test]
2249 fn a_producer_shorter_than_a_digest_is_rejected() {
2250 let bytes = encode_with(|e| {
2253 e.map(1)?;
2254 e.u64(data_key::PRODUCER)?.bytes(&[0u8; 16])?;
2255 Ok(())
2256 });
2257 assert!(matches!(
2258 DataHeader::decode(&bytes),
2259 Err(HeaderError::Malformed(_))
2260 ));
2261 }
2262
2263 #[test]
2264 fn the_new_keys_reject_the_wrong_cbor_type() {
2265 let sequence_as_text = encode_with(|e| {
2266 e.map(1)?;
2267 e.u64(data_key::SEQUENCE)?.str("7")?;
2268 Ok(())
2269 });
2270 assert!(DataHeader::decode(&sequence_as_text).is_err());
2271
2272 let producer_as_text = encode_with(|e| {
2273 e.map(1)?;
2274 e.u64(data_key::PRODUCER)?.str("sha256:…")?;
2275 Ok(())
2276 });
2277 assert!(DataHeader::decode(&producer_as_text).is_err());
2278 }
2279
2280 #[test]
2281 fn a_v0_header_carries_neither_new_key() {
2282 let mut h = DataHeader::addressed("/t");
2286 h.traceparent = Some("00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01".into());
2287 let bytes = h.encode();
2288 let mut d = Decoder::new(&bytes);
2289 let pairs = d.map().unwrap().unwrap();
2290 let keys: Vec<u64> = (0..pairs)
2291 .map(|_| {
2292 let key = d.u64().unwrap();
2293 d.skip().unwrap();
2294 key
2295 })
2296 .collect();
2297 assert_eq!(keys, vec![data_key::ENDPOINT, data_key::TRACEPARENT]);
2298 }
2299
2300 #[test]
2301 fn golden_subscription_headers() {
2302 let h = SubscriptionHeader::new("/md", "px.");
2303 let bytes = h.encode();
2304 assert_eq!(
2305 bytes,
2306 vec![
2307 0xA2, 0x00, 0x63, 0x2F, 0x6D, 0x64, 0x01, 0x63, 0x70, 0x78, 0x2E
2308 ]
2309 );
2310 assert_eq!(bytes.len(), 0x0B);
2311 assert_eq!(SubscriptionHeader::decode(&bytes).unwrap(), h);
2314 }
2315
2316 #[test]
2319 fn data_header_roundtrip_with_every_field() {
2320 let h = DataHeader {
2321 endpoint: Some("/transform".into()),
2322 content_len: Some(1 << 40),
2323 content_type: Some("application/octet-stream".into()),
2324 traceparent: Some("00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01".into()),
2325 tracestate: Some("vendor=value".into()),
2326 topic: Some("px.eur".into()),
2327 sequence: Some(u64::MAX),
2328 producer: Some([0x5A; limits::PRODUCER_BYTES]),
2329 achieved: Some(Acknowledgement::Processed),
2330 report_id: Some(7),
2331 report: vec![
2332 CursorLevel::Known(Acknowledgement::Accepted),
2333 CursorLevel::Known(Acknowledgement::Processed),
2334 CursorLevel::Application(CursorLevel::APPLICATION_FLOOR),
2335 ],
2336 report_mode: ReportMode::FinalOnly,
2337 segment: Some(u64::MAX),
2338 };
2339 assert_eq!(DataHeader::decode(&h.encode()).unwrap(), h);
2340 }
2341
2342 #[test]
2343 fn error_header_roundtrip_with_and_without_message() {
2344 let bare = ErrorHeader::new(ErrorCode::UnknownEndpoint);
2345 assert_eq!(ErrorHeader::decode(&bare.encode()).unwrap(), bare);
2346 assert_eq!(bare.error_code(), Some(ErrorCode::UnknownEndpoint));
2347
2348 let with_msg = ErrorHeader {
2349 code: 4,
2350 message: Some("handler panicked".into()),
2351 };
2352 assert_eq!(ErrorHeader::decode(&with_msg.encode()).unwrap(), with_msg);
2353 }
2354
2355 #[test]
2356 fn keys_are_emitted_in_ascending_order() {
2357 let h = DataHeader {
2358 endpoint: Some("/x".into()),
2359 content_len: Some(1),
2360 content_type: Some("t".into()),
2361 traceparent: Some("p".into()),
2362 tracestate: Some("s".into()),
2363 topic: Some("k".into()),
2364 sequence: Some(9),
2365 producer: Some([0u8; limits::PRODUCER_BYTES]),
2366 achieved: Some(Acknowledgement::Accepted),
2367 report_id: Some(1),
2368 report: vec![CursorLevel::Known(Acknowledgement::Stored)],
2369 report_mode: ReportMode::FinalOnly,
2370 segment: Some(3),
2371 };
2372 let bytes = h.encode();
2373 let mut d = Decoder::new(&bytes);
2374 let n = d.map().unwrap().unwrap();
2375 let mut last = None;
2376 for _ in 0..n {
2377 let key = d.u64().unwrap();
2378 if let Some(prev) = last {
2379 assert!(key > prev, "keys must ascend: {prev} then {key}");
2380 }
2381 last = Some(key);
2382 d.skip().unwrap();
2383 }
2384 }
2385
2386 #[test]
2387 fn an_unsorted_report_with_repeats_is_emitted_as_the_canonical_ascending_set() {
2388 let h = DataHeader {
2393 report_id: Some(1),
2394 report: vec![
2395 CursorLevel::Application(CursorLevel::APPLICATION_FLOOR),
2396 CursorLevel::Known(Acknowledgement::Stored),
2397 CursorLevel::Application(CursorLevel::APPLICATION_FLOOR),
2398 CursorLevel::Known(Acknowledgement::Accepted),
2399 CursorLevel::Known(Acknowledgement::Stored),
2400 ],
2401 ..DataHeader::reply()
2402 };
2403 let decoded = DataHeader::decode(&h.encode()).expect("encoder emits the canonical form");
2404 assert_eq!(
2405 decoded.report,
2406 vec![
2407 CursorLevel::Known(Acknowledgement::Accepted),
2408 CursorLevel::Known(Acknowledgement::Stored),
2409 CursorLevel::Application(CursorLevel::APPLICATION_FLOOR),
2410 ]
2411 );
2412 }
2413
2414 #[test]
2417 fn every_data_field_is_optional_at_the_decoder() {
2418 assert_eq!(DataHeader::decode(&[0xA0]).unwrap(), DataHeader::default());
2422
2423 let only_topic = encode_with(|e| {
2424 e.map(1)?;
2425 e.u64(data_key::TOPIC)?.str("px.eur")?;
2426 Ok(())
2427 });
2428 let h = DataHeader::decode(&only_topic).unwrap();
2429 assert_eq!(h.topic.as_deref(), Some("px.eur"));
2430 assert_eq!(h.endpoint, None);
2431 }
2432
2433 #[test]
2434 fn absent_fields_are_omitted_by_the_encoder() {
2435 let h = DataHeader::addressed("/t");
2436 assert_eq!(h.encode(), vec![0xA1, 0x00, 0x62, 0x2F, 0x74]);
2437 }
2438
2439 #[test]
2442 fn unknown_keys_are_skipped() {
2443 let h = DataHeader::addressed("/t");
2446 let extended = encode_with(|e| {
2447 e.map(2)?;
2448 e.u64(0)?.str("/t")?;
2449 e.u64(63)?.array(2)?.u64(7)?.map(1)?.u64(1)?.bool(true)?;
2450 Ok(())
2451 });
2452 assert_eq!(DataHeader::decode(&extended).unwrap(), h);
2453 }
2454
2455 #[test]
2456 fn unknown_keys_above_the_reserved_range_are_skipped() {
2457 let extended = encode_with(|e| {
2458 e.map(2)?;
2459 e.u64(1)?.u64(5)?;
2460 e.u64(1000)?.str("future")?;
2461 Ok(())
2462 });
2463 let h = DataHeader::decode(&extended).unwrap();
2464 assert_eq!(h.content_len, Some(5));
2465 }
2466
2467 #[test]
2468 fn skipping_tolerates_nesting_up_to_the_depth_limit() {
2469 for depth in [1usize, limits::MAX_SKIP_DEPTH] {
2470 let bytes = encode_with(|e| {
2471 e.map(2)?;
2472 e.u64(data_key::CONTENT_LEN)?.u64(1)?;
2473 e.u64(50)?;
2474 for _ in 0..depth {
2475 e.array(1)?;
2476 }
2477 e.u64(1)?;
2478 Ok(())
2479 });
2480 let h = DataHeader::decode(&bytes).unwrap_or_else(|e| panic!("depth {depth}: {e}"));
2481 assert_eq!(h.content_len, Some(1), "depth {depth}");
2482 }
2483 }
2484
2485 #[test]
2486 fn skipping_rejects_nesting_beyond_the_depth_limit() {
2487 let bytes = encode_with(|e| {
2488 e.map(1)?;
2489 e.u64(50)?;
2490 for _ in 0..(limits::MAX_SKIP_DEPTH + 1) {
2491 e.array(1)?;
2492 }
2493 e.u64(1)?;
2494 Ok(())
2495 });
2496 assert_eq!(
2497 DataHeader::decode(&bytes).unwrap_err(),
2498 HeaderError::DepthExceeded
2499 );
2500 }
2501
2502 #[test]
2503 fn skipping_a_wide_shallow_structure_is_fine() {
2504 let bytes = encode_with(|e| {
2505 e.map(2)?;
2506 e.u64(data_key::CONTENT_LEN)?.u64(1)?;
2507 e.u64(40)?.array(64)?;
2508 for i in 0..64u64 {
2509 e.u64(i)?;
2510 }
2511 Ok(())
2512 });
2513 assert_eq!(DataHeader::decode(&bytes).unwrap().content_len, Some(1));
2514 }
2515
2516 #[test]
2519 fn duplicate_keys_are_rejected() {
2520 let bytes = encode_with(|e| {
2521 e.map(2)?;
2522 e.u64(1)?.u64(1)?;
2523 e.u64(1)?.u64(2)?;
2524 Ok(())
2525 });
2526 assert_eq!(
2527 DataHeader::decode(&bytes).unwrap_err(),
2528 HeaderError::DuplicateKey(1)
2529 );
2530 }
2531
2532 #[test]
2533 fn non_uint_keys_are_rejected() {
2534 let bytes = encode_with(|e| {
2535 e.map(1)?;
2536 e.str("endpoint")?.str("/t")?;
2537 Ok(())
2538 });
2539 assert_eq!(
2540 DataHeader::decode(&bytes).unwrap_err(),
2541 HeaderError::NonUintKey
2542 );
2543
2544 let negative = encode_with(|e| {
2545 e.map(1)?;
2546 e.i64(-1)?.u64(1)?;
2547 Ok(())
2548 });
2549 assert_eq!(
2550 DataHeader::decode(&negative).unwrap_err(),
2551 HeaderError::NonUintKey
2552 );
2553 }
2554
2555 #[test]
2556 fn indefinite_maps_are_rejected() {
2557 let bytes = encode_with(|e| {
2558 e.begin_map()?;
2559 e.u64(1)?.u64(1)?;
2560 e.end()?;
2561 Ok(())
2562 });
2563 assert_eq!(
2564 DataHeader::decode(&bytes).unwrap_err(),
2565 HeaderError::Indefinite
2566 );
2567 }
2568
2569 #[test]
2570 fn indefinite_arrays_are_rejected() {
2571 let bytes = encode_with(|e| {
2572 e.map(5)?;
2573 e.u64(0)?.begin_array()?.u64(0)?.end()?;
2574 e.u64(1)?.u64(1)?;
2575 e.u64(2)?.u64(1)?;
2576 e.u64(3)?.array(0)?;
2577 e.u64(4)?.array(0)?;
2578 Ok(())
2579 });
2580 assert_eq!(Hello::decode(&bytes).unwrap_err(), HeaderError::Indefinite);
2581 }
2582
2583 #[test]
2584 fn value_type_mismatches_are_rejected() {
2585 let bytes = encode_with(|e| {
2586 e.map(1)?;
2587 e.u64(data_key::CONTENT_LEN)?.str("not a number")?;
2588 Ok(())
2589 });
2590 assert!(matches!(
2591 DataHeader::decode(&bytes).unwrap_err(),
2592 HeaderError::Malformed(_)
2593 ));
2594 }
2595
2596 #[test]
2597 fn missing_required_keys_are_rejected() {
2598 let bytes = encode_with(|e| {
2600 e.map(1)?;
2601 e.u64(error_key::MESSAGE)?.str("why")?;
2602 Ok(())
2603 });
2604 assert_eq!(
2605 ErrorHeader::decode(&bytes).unwrap_err(),
2606 HeaderError::MissingKey(error_key::CODE)
2607 );
2608
2609 let bytes = encode_with(|e| {
2611 e.map(4)?;
2612 e.u64(0)?.array(1)?.u64(0)?;
2613 e.u64(1)?.u64(16384)?;
2614 e.u64(2)?.u64(16)?;
2615 e.u64(4)?.array(0)?;
2616 Ok(())
2617 });
2618 assert_eq!(
2619 Hello::decode(&bytes).unwrap_err(),
2620 HeaderError::MissingKey(hello_key::CAPABILITIES)
2621 );
2622 }
2623
2624 #[test]
2627 fn an_empty_filter_is_legal_and_survives_the_roundtrip() {
2628 let h = SubscriptionHeader::new("/md", "");
2629 let bytes = h.encode();
2630 assert_eq!(SubscriptionHeader::decode(&bytes).unwrap(), h);
2631 assert!(
2634 bytes.contains(&0x60),
2635 "the empty filter is encoded: {bytes:?}"
2636 );
2637 }
2638
2639 #[test]
2640 fn the_filter_grammar_accepts_what_docs_protocol_6_4_permits() {
2641 for ok in [
2642 "",
2643 "#",
2644 "px",
2645 "px.eur",
2646 "px.*",
2647 "*.eur",
2648 "sensors.*.temp",
2649 "px.#",
2650 "px.",
2651 "a..b",
2652 ] {
2653 assert_eq!(filter::validate(ok), Ok(()), "{ok:?} must be legal");
2654 }
2655 }
2656
2657 #[test]
2658 fn the_filter_grammar_rejects_partial_and_misplaced_wildcards() {
2659 for bad in [
2660 "px*", "*px", "p*x.eur", "px.e*ur", "#.px", "px.#.eur", "px#",
2661 ] {
2662 assert!(
2663 matches!(filter::validate(bad), Err(HeaderError::InvalidFilter(_))),
2664 "{bad:?} must be rejected"
2665 );
2666 }
2667 }
2668
2669 #[test]
2670 fn an_illegal_filter_is_rejected_at_the_codec_boundary() {
2671 let bytes = SubscriptionHeader::new("/md", "px.#.eur").encode();
2675 assert!(matches!(
2676 SubscriptionHeader::decode(&bytes),
2677 Err(HeaderError::InvalidFilter(_))
2678 ));
2679 let e: Error = HeaderError::InvalidFilter("`#` must be the final segment").into();
2680 assert!(e.to_string().contains("invalid topic filter"));
2681 }
2682
2683 #[test]
2684 fn subscription_strings_are_capped() {
2685 for (key, max) in [
2686 (subscription_key::ENDPOINT, limits::MAX_ENDPOINT_BYTES),
2687 (subscription_key::FILTER, limits::MAX_FILTER_BYTES),
2688 ] {
2689 let build = |len: usize| {
2690 let text = "a".repeat(len);
2691 let mut h = SubscriptionHeader::new("/md", "px.");
2692 if key == subscription_key::ENDPOINT {
2693 h.endpoint = text;
2694 } else {
2695 h.filter = text;
2696 }
2697 h.encode()
2698 };
2699 assert_eq!(
2700 SubscriptionHeader::decode(&build(max + 1)).unwrap_err(),
2701 HeaderError::StringTooLong {
2702 key,
2703 len: max + 1,
2704 max
2705 },
2706 "key {key}"
2707 );
2708 assert!(
2709 SubscriptionHeader::decode(&build(max)).is_ok(),
2710 "key {key} at cap"
2711 );
2712 }
2713 }
2714
2715 #[test]
2716 fn subscription_headers_require_both_keys() {
2717 let only = |key: u64| {
2718 encode_with(|e| {
2719 e.map(1)?;
2720 e.u64(key)?.str("/md")?;
2721 Ok(())
2722 })
2723 };
2724 assert_eq!(
2725 SubscriptionHeader::decode(&only(subscription_key::ENDPOINT)).unwrap_err(),
2726 HeaderError::MissingKey(subscription_key::FILTER)
2727 );
2728 assert_eq!(
2729 SubscriptionHeader::decode(&only(subscription_key::FILTER)).unwrap_err(),
2730 HeaderError::MissingKey(subscription_key::ENDPOINT)
2731 );
2732 }
2733
2734 #[test]
2735 fn subscription_headers_reject_malformed_input() {
2736 assert!(SubscriptionHeader::decode(&[]).is_err());
2737 let mut bytes = SubscriptionHeader::new("/md", "px.").encode();
2739 bytes.push(0xff);
2740 assert_eq!(
2741 SubscriptionHeader::decode(&bytes).unwrap_err(),
2742 HeaderError::TrailingBytes
2743 );
2744 let extended = encode_with(|e| {
2746 e.map(3)?;
2747 e.u64(0)?.str("/md")?;
2748 e.u64(1)?.str("px.")?;
2749 e.u64(40)?.array(2)?.u64(1)?.u64(2)?;
2750 Ok(())
2751 });
2752 assert_eq!(
2753 SubscriptionHeader::decode(&extended).unwrap(),
2754 SubscriptionHeader::new("/md", "px.")
2755 );
2756 }
2757
2758 #[test]
2759 fn oversized_strings_are_rejected_per_field() {
2760 let with_text = |key: u64, text: String| -> Vec<u8> {
2762 let mut h = DataHeader::reply();
2763 match key {
2764 data_key::ENDPOINT => h.endpoint = Some(text),
2765 data_key::CONTENT_TYPE => h.content_type = Some(text),
2766 data_key::TRACEPARENT => h.traceparent = Some(text),
2767 data_key::TRACESTATE => h.tracestate = Some(text),
2768 data_key::TOPIC => h.topic = Some(text),
2769 other => panic!("key {other} is not a text field"),
2770 }
2771 h.encode()
2772 };
2773 let cases: [(u64, usize); 5] = [
2774 (data_key::ENDPOINT, limits::MAX_ENDPOINT_BYTES),
2775 (data_key::CONTENT_TYPE, limits::MAX_CONTENT_TYPE_BYTES),
2776 (data_key::TRACEPARENT, limits::MAX_TRACEPARENT_BYTES),
2777 (data_key::TRACESTATE, limits::MAX_TRACESTATE_BYTES),
2778 (data_key::TOPIC, limits::MAX_TOPIC_BYTES),
2779 ];
2780 for (key, max) in cases {
2781 assert_eq!(
2782 DataHeader::decode(&with_text(key, "a".repeat(max + 1))).unwrap_err(),
2783 HeaderError::StringTooLong {
2784 key,
2785 len: max + 1,
2786 max
2787 },
2788 "key {key}"
2789 );
2790 assert!(
2791 DataHeader::decode(&with_text(key, "a".repeat(max))).is_ok(),
2792 "key {key} at cap"
2793 );
2794 }
2795 }
2796
2797 #[test]
2798 fn unordered_keys_are_rejected() {
2799 let bytes = encode_with(|e| {
2802 e.map(3)?;
2803 e.u64(2)?.str("t")?;
2804 e.u64(1)?.u64(1)?;
2805 e.u64(3)?.str("p")?;
2806 Ok(())
2807 });
2808 assert_eq!(
2809 DataHeader::decode(&bytes).unwrap_err(),
2810 HeaderError::UnorderedKey(1)
2811 );
2812 }
2813
2814 #[test]
2815 fn duplicate_extension_keys_are_rejected() {
2816 let bytes = encode_with(|e| {
2817 e.map(3)?;
2818 e.u64(1)?.u64(1)?;
2819 e.u64(1000)?.u64(1)?;
2820 e.u64(1000)?.u64(2)?;
2821 Ok(())
2822 });
2823 assert_eq!(
2824 DataHeader::decode(&bytes).unwrap_err(),
2825 HeaderError::DuplicateKey(1000)
2826 );
2827 }
2828
2829 #[test]
2830 fn oversized_error_messages_are_rejected() {
2831 let big = "m".repeat(limits::MAX_MESSAGE_BYTES + 1);
2832 let bytes = encode_with(|e| {
2833 e.map(2)?;
2834 e.u64(error_key::CODE)?.u64(2)?;
2835 e.u64(error_key::MESSAGE)?.str(&big)?;
2836 Ok(())
2837 });
2838 assert_eq!(
2839 ErrorHeader::decode(&bytes).unwrap_err(),
2840 HeaderError::StringTooLong {
2841 key: error_key::MESSAGE,
2842 len: limits::MAX_MESSAGE_BYTES + 1,
2843 max: limits::MAX_MESSAGE_BYTES
2844 }
2845 );
2846 }
2847
2848 #[test]
2849 fn oversized_lists_are_rejected_without_allocating() {
2850 let bytes = encode_with(|e| {
2852 e.map(1)?;
2853 e.u64(0)?.array(u64::from(u32::MAX))?;
2854 Ok(())
2855 });
2856 assert_eq!(
2857 Hello::decode(&bytes).unwrap_err(),
2858 HeaderError::ListTooLong {
2859 key: hello_key::VERSIONS,
2860 len: u64::from(u32::MAX),
2861 max: limits::MAX_LIST_ITEMS
2862 }
2863 );
2864 }
2865
2866 #[test]
2867 fn lists_exactly_at_the_cap_are_accepted() {
2868 let bytes = encode_with(|e| {
2869 e.map(5)?;
2870 e.u64(0)?.array(limits::MAX_LIST_ITEMS as u64)?;
2871 for i in 0..limits::MAX_LIST_ITEMS as u64 {
2872 e.u64(i)?;
2873 }
2874 e.u64(1)?.u64(16384)?;
2875 e.u64(2)?.u64(16)?;
2876 e.u64(3)?.array(0)?;
2877 e.u64(4)?.array(0)?;
2878 Ok(())
2879 });
2880 assert_eq!(
2881 Hello::decode(&bytes).unwrap().versions.len(),
2882 limits::MAX_LIST_ITEMS
2883 );
2884 }
2885
2886 #[test]
2887 fn trailing_bytes_are_rejected() {
2888 let mut bytes = ErrorHeader::new(ErrorCode::Rejected).encode();
2889 bytes.push(0xff);
2890 assert_eq!(
2891 ErrorHeader::decode(&bytes).unwrap_err(),
2892 HeaderError::TrailingBytes
2893 );
2894 }
2895
2896 #[test]
2897 fn truncated_headers_are_rejected() {
2898 let full = DataHeader::addressed("/t").encode();
2899 for cut in 0..full.len() {
2900 assert!(
2901 DataHeader::decode(&full[..cut]).is_err(),
2902 "prefix of {cut} bytes must not decode"
2903 );
2904 }
2905 }
2906
2907 #[test]
2908 fn empty_input_is_rejected_for_every_header() {
2909 assert!(Hello::decode(&[]).is_err());
2910 assert!(DataHeader::decode(&[]).is_err());
2911 assert!(ErrorHeader::decode(&[]).is_err());
2912 assert!(SubscriptionHeader::decode(&[]).is_err());
2913 }
2914
2915 #[test]
2916 fn tags_are_rejected() {
2917 let bytes = encode_with(|e| {
2920 e.map(1)?;
2921 e.u64(50)?.tag(minicbor::data::IanaTag::Cbor)?.u64(1)?;
2922 Ok(())
2923 });
2924 assert_eq!(
2925 DataHeader::decode(&bytes).unwrap_err(),
2926 HeaderError::Malformed("tags are not allowed")
2927 );
2928 }
2929
2930 #[test]
2933 fn unknown_error_codes_survive_decoding() {
2934 let err = ErrorHeader {
2935 code: 99,
2936 message: None,
2937 };
2938 let decoded = ErrorHeader::decode(&err.encode()).unwrap();
2939 assert_eq!(decoded.code, 99);
2940 assert_eq!(decoded.error_code(), None);
2941 }
2942
2943 #[test]
2944 fn header_errors_become_protocol_errors() {
2945 let e: Error = HeaderError::DuplicateKey(3).into();
2946 assert!(matches!(e, Error::Protocol(_)));
2947 assert!(e.to_string().contains("duplicate header key 3"));
2948 }
2949}