middleware_core/
bridge.rs1#[derive(Clone, Copy, Debug, Eq, PartialEq)]
2pub enum BridgeTrafficKind {
3 Topic,
4 Service,
5 Mission,
6}
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub enum BridgeDropReason {
10 KindNotAllowed,
11 LabelMismatch,
12}
13
14#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
15pub struct BridgeStats {
16 pub forwarded: u64,
17 pub dropped_kind: u64,
18 pub dropped_label: u64,
19}
20
21#[derive(Clone, Debug, Eq, PartialEq)]
22pub struct BridgePolicy {
23 pub allow_topic: bool,
24 pub allow_service: bool,
25 pub allow_mission: bool,
26 pub include_labels: Vec<String>,
27}
28
29impl Default for BridgePolicy {
30 fn default() -> Self {
31 Self {
32 allow_topic: true,
33 allow_service: true,
34 allow_mission: true,
35 include_labels: Vec::new(),
36 }
37 }
38}
39
40impl BridgePolicy {
41 pub fn should_forward(&self, kind: BridgeTrafficKind, labels: &[String]) -> bool {
42 let kind_allowed = match kind {
43 BridgeTrafficKind::Topic => self.allow_topic,
44 BridgeTrafficKind::Service => self.allow_service,
45 BridgeTrafficKind::Mission => self.allow_mission,
46 };
47
48 if !kind_allowed {
49 return false;
50 }
51
52 if self.include_labels.is_empty() {
53 return true;
54 }
55
56 self.include_labels
57 .iter()
58 .all(|label| labels.iter().any(|candidate| candidate == label))
59 }
60
61 pub fn evaluate_with_stats(
62 &self,
63 kind: BridgeTrafficKind,
64 labels: &[String],
65 stats: &mut BridgeStats,
66 ) -> bool {
67 let kind_allowed = match kind {
68 BridgeTrafficKind::Topic => self.allow_topic,
69 BridgeTrafficKind::Service => self.allow_service,
70 BridgeTrafficKind::Mission => self.allow_mission,
71 };
72
73 if !kind_allowed {
74 stats.dropped_kind += 1;
75 return false;
76 }
77
78 if !self.include_labels.is_empty() {
79 let labels_match = self
80 .include_labels
81 .iter()
82 .all(|label| labels.iter().any(|candidate| candidate == label));
83 if !labels_match {
84 stats.dropped_label += 1;
85 return false;
86 }
87 }
88
89 stats.forwarded += 1;
90 true
91 }
92}