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