bacnet_server/server/
event_information_budget.rs1use super::*;
3
4#[derive(Clone, Copy, Debug, PartialEq, Eq)]
7pub struct GetEventInformationBudget {
8 pub max_objects: usize,
10 pub max_returned_summaries: usize,
12 pub max_service_ack_bytes: usize,
14}
15
16impl Default for GetEventInformationBudget {
17 fn default() -> Self {
18 Self {
19 max_objects: 4096,
20 max_returned_summaries: 256,
21 max_service_ack_bytes: 16384,
22 }
23 }
24}
25
26impl GetEventInformationBudget {
27 pub fn validate(&self) -> Result<(), Error> {
29 for (name, value) in [
30 ("event_information_max_objects", self.max_objects),
31 (
32 "event_information_max_returned_summaries",
33 self.max_returned_summaries,
34 ),
35 (
36 "event_information_max_service_ack_bytes",
37 self.max_service_ack_bytes,
38 ),
39 ] {
40 if value == 0 {
41 return Err(Error::Encoding(format!("{name} must be positive")));
42 }
43 }
44 Ok(())
45 }
46}
47
48impl<T: TransportPort + 'static> ServerBuilder<T> {
49 pub fn get_event_information_budget(mut self, budget: GetEventInformationBudget) -> Self {
51 self.config.get_event_information_budget = budget;
52 self
53 }
54}
55impl BipServerBuilder {
56 pub fn get_event_information_budget(mut self, budget: GetEventInformationBudget) -> Self {
58 self.config.get_event_information_budget = budget;
59 self
60 }
61}
62#[cfg(feature = "sc-tls")]
63impl ScServerBuilder {
64 pub fn get_event_information_budget(mut self, budget: GetEventInformationBudget) -> Self {
66 self.config.get_event_information_budget = budget;
67 self
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74 use crate::server::test_transport::TestTransport;
75
76 #[tokio::test]
77 async fn get_event_information_all_builders_validate_before_start_or_dial() {
78 let default = GetEventInformationBudget::default();
79 assert_eq!(
80 (
81 default.max_objects,
82 default.max_returned_summaries,
83 default.max_service_ack_bytes
84 ),
85 (4096, 256, 16384)
86 );
87 assert_eq!(
88 ServerConfig::default().get_event_information_budget,
89 default
90 );
91 assert!(format!("{:?}", ServerConfig::default()).contains("get_event_information_budget"));
92 GetEventInformationBudget {
93 max_objects: usize::MAX,
94 max_returned_summaries: usize::MAX,
95 max_service_ack_bytes: usize::MAX,
96 }
97 .validate()
98 .unwrap();
99 for budget in [
100 GetEventInformationBudget {
101 max_objects: 0,
102 ..default
103 },
104 GetEventInformationBudget {
105 max_returned_summaries: 0,
106 ..default
107 },
108 GetEventInformationBudget {
109 max_service_ack_bytes: 0,
110 ..default
111 },
112 ] {
113 let direct = BACnetServer::start(
114 ServerConfig {
115 get_event_information_budget: budget,
116 ..Default::default()
117 },
118 ObjectDatabase::new(),
119 TestTransport::never_start(),
120 )
121 .await
122 .err();
123 let generic = BACnetServer::generic_builder()
124 .transport(TestTransport::never_start())
125 .get_event_information_budget(budget)
126 .build()
127 .await
128 .err();
129 let bip = BACnetServer::bip_builder()
130 .port(0)
131 .get_event_information_budget(budget)
132 .build()
133 .await
134 .err();
135 for error in [direct, generic, bip] {
136 assert!(
137 matches!(error, Some(Error::Encoding(m)) if m.contains("event_information_max_"))
138 );
139 }
140 #[cfg(feature = "sc-tls")]
141 {
142 let error = BACnetServer::sc_builder()
143 .hub_url("not-a-websocket-url")
144 .tls_config(crate::server::sc_builder::test_tls_config())
145 .device_uuid(crate::server::sc_builder::TEST_DEVICE_UUID)
146 .get_event_information_budget(budget)
147 .build()
148 .await
149 .err();
150 assert!(
151 matches!(error, Some(Error::Encoding(m)) if m.contains("event_information_max_"))
152 );
153 }
154 }
155 }
156}