1use smallvec::SmallVec;
2
3use ndn_transport::FaceId;
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq)]
7pub enum DropReason {
8 MalformedPacket,
9 UnknownFace,
10 LoopDetected,
11 Suppressed,
12 RateLimited,
13 HopLimitExceeded,
14 ScopeViolation,
15 FragmentCollect,
18 ValidationFailed,
20 ValidationTimeout,
22 Other,
23}
24
25#[derive(Clone, Copy, Debug, PartialEq, Eq)]
27pub enum NackReason {
28 NoRoute,
29 Duplicate,
30 Congestion,
31 NotYet,
32}
33
34pub enum Action {
40 Continue(super::context::PacketContext),
42 Send(super::context::PacketContext, SmallVec<[FaceId; 4]>),
44 Satisfy(super::context::PacketContext),
46 Drop(DropReason),
48 Nack(super::context::PacketContext, NackReason),
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55 use crate::context::PacketContext;
56 use bytes::Bytes;
57 use ndn_transport::FaceId;
58 use smallvec::smallvec;
59
60 #[test]
61 fn drop_reason_variants_are_distinct() {
62 let reasons = [
63 DropReason::MalformedPacket,
64 DropReason::UnknownFace,
65 DropReason::LoopDetected,
66 DropReason::Suppressed,
67 DropReason::RateLimited,
68 DropReason::HopLimitExceeded,
69 DropReason::ScopeViolation,
70 DropReason::FragmentCollect,
71 DropReason::ValidationFailed,
72 DropReason::ValidationTimeout,
73 DropReason::Other,
74 ];
75 for (i, a) in reasons.iter().enumerate() {
76 for (j, b) in reasons.iter().enumerate() {
77 assert_eq!(i == j, a == b);
78 }
79 }
80 }
81
82 #[test]
83 fn nack_reason_variants_are_distinct() {
84 let reasons = [
85 NackReason::NoRoute,
86 NackReason::Duplicate,
87 NackReason::Congestion,
88 NackReason::NotYet,
89 ];
90 for (i, a) in reasons.iter().enumerate() {
91 for (j, b) in reasons.iter().enumerate() {
92 assert_eq!(i == j, a == b);
93 }
94 }
95 }
96
97 fn ctx() -> PacketContext {
98 PacketContext::new(Bytes::from_static(b"\x05\x01\x00"), FaceId(0), 0)
99 }
100
101 #[test]
102 fn action_continue_wraps_context() {
103 let a = Action::Continue(ctx());
104 assert!(matches!(a, Action::Continue(_)));
105 }
106
107 #[test]
108 fn action_drop_holds_reason() {
109 let a = Action::Drop(DropReason::LoopDetected);
110 assert!(matches!(a, Action::Drop(DropReason::LoopDetected)));
111 }
112
113 #[test]
114 fn action_nack_holds_reason() {
115 let a = Action::Nack(ctx(), NackReason::NoRoute);
116 assert!(matches!(a, Action::Nack(_, NackReason::NoRoute)));
117 }
118
119 #[test]
120 fn action_send_holds_faces() {
121 let faces: SmallVec<[FaceId; 4]> = smallvec![FaceId(1), FaceId(2)];
122 let a = Action::Send(ctx(), faces);
123 if let Action::Send(_, f) = a {
124 assert_eq!(f.len(), 2);
125 } else {
126 panic!("expected Send");
127 }
128 }
129
130 #[test]
131 fn forwarding_action_suppress() {
132 assert!(matches!(
133 ForwardingAction::Suppress,
134 ForwardingAction::Suppress
135 ));
136 }
137
138 #[test]
139 fn forwarding_action_forward_after() {
140 let delay = std::time::Duration::from_millis(10);
141 let a = ForwardingAction::ForwardAfter {
142 faces: smallvec![FaceId(3)],
143 delay,
144 };
145 if let ForwardingAction::ForwardAfter { faces, delay: d } = a {
146 assert_eq!(faces.len(), 1);
147 assert_eq!(d.as_millis(), 10);
148 } else {
149 panic!("expected ForwardAfter");
150 }
151 }
152}
153
154pub enum ForwardingAction {
156 Forward(SmallVec<[FaceId; 4]>),
158 ForwardAfter {
160 faces: SmallVec<[FaceId; 4]>,
161 delay: std::time::Duration,
162 },
163 Nack(NackReason),
165 Suppress,
167}