bacnet_emb/application_protocol/
segment.rs1#[cfg(feature = "alloc")]
5use {
6 crate::common::spooky::Phantom,
7 alloc::{vec, vec::Vec},
8};
9
10use crate::{
11 application_protocol::application_pdu::{ApduType, PduFlags},
12 common::{
13 error::Error,
14 io::{Reader, Writer},
15 },
16};
17
18#[cfg(not(feature = "alloc"))]
19#[cfg_attr(feature = "defmt", derive(defmt::Format))]
20#[derive(Debug, Clone)]
21pub struct Segment<'a> {
22 pub apdu_type: ApduType,
23 pub more_follows: bool,
24
25 pub invoke_id: u8,
26 pub sequence_number: u8,
27 pub window_size: u8, pub service_choice: u8,
29
30 pub data: &'a [u8],
32}
33
34#[cfg(feature = "alloc")]
35#[cfg_attr(feature = "defmt", derive(defmt::Format))]
36#[derive(Debug, Clone)]
37pub struct Segment<'a> {
38 pub apdu_type: ApduType,
39 pub more_follows: bool,
40
41 pub invoke_id: u8,
42 pub sequence_number: u8,
43 pub window_size: u8, pub service_choice: u8,
45
46 pub data: Vec<u8>,
48 _phantom: &'a Phantom,
49}
50
51impl<'a> Segment<'a> {
52 #[cfg(feature = "alloc")]
53 pub fn new(
54 apdu_type: ApduType,
55 more_follows: bool,
56 invoke_id: u8,
57 sequence_number: u8,
58 window_size: u8,
59 service_choice: u8,
60 data: Vec<u8>,
61 ) -> Self {
62 use crate::common::spooky::PHANTOM;
63
64 Segment {
65 apdu_type,
66 more_follows,
67 invoke_id,
68 sequence_number,
69 window_size,
70 service_choice,
71 data,
72 _phantom: &PHANTOM,
73 }
74 }
75
76 #[cfg(not(feature = "alloc"))]
77 pub fn new(
78 apdu_type: ApduType,
79 more_follows: bool,
80 invoke_id: u8,
81 sequence_number: u8,
82 window_size: u8,
83 service_choice: u8,
84 data: &'a [u8],
85 ) -> Self {
86 Segment {
87 apdu_type,
88 more_follows,
89 invoke_id,
90 sequence_number,
91 window_size,
92 service_choice,
93 data,
94 }
95 }
96
97 #[cfg_attr(feature = "alloc", bacnet_macros::remove_lifetimes_from_fn_args)]
98 pub fn decode(
99 more_follows: bool,
100 apdu_type: ApduType,
101 reader: &mut Reader,
102 buf: &'a [u8],
103 ) -> Result<Self, Error> {
104 let invoke_id = reader.read_byte(buf)?;
105 let sequence_number = reader.read_byte(buf)?;
106 let window_size = reader.read_byte(buf)?;
107 let service_choice = reader.read_byte(buf)?;
108 let data = Self::decode_data(reader, buf)?;
109
110 let segment = Self::new(
111 apdu_type,
112 more_follows,
113 invoke_id,
114 sequence_number,
115 window_size,
116 service_choice,
117 data,
118 );
119 Ok(segment)
120 }
121
122 #[cfg(feature = "alloc")]
123 fn decode_data(reader: &mut Reader, buf: &[u8]) -> Result<Vec<u8>, Error> {
124 let len = reader.end - reader.index;
126 let mut data = vec![0u8; len];
127 let slice = reader.read_slice(len, buf)?;
128 data.copy_from_slice(slice);
129 Ok(data)
130 }
131
132 #[cfg(not(feature = "alloc"))]
133 fn decode_data(reader: &mut Reader, buf: &'a [u8]) -> Result<&'a [u8], Error> {
134 let len = reader.end - reader.index;
136 let data = reader.read_slice(len, buf)?;
137 Ok(data)
138 }
139
140 pub fn encode(&self, writer: &mut Writer) {
141 let mut control = ((self.apdu_type.clone() as u8) << 4) | PduFlags::SegmentedMessage as u8;
142 if self.more_follows {
143 control |= PduFlags::MoreFollows as u8;
144 }
145 writer.push(control);
146 writer.push(self.invoke_id);
147 writer.push(self.sequence_number);
148 writer.push(self.window_size);
149 writer.push(self.service_choice);
150 writer.extend_from_slice(&self.data);
151 }
152
153 pub fn encode_for_accumulation(&self, writer: &mut Writer) -> usize {
157 let start = writer.index;
158 if self.sequence_number == 0 {
159 writer.push((self.apdu_type.clone() as u8) << 4);
160 writer.push(self.invoke_id);
161 writer.push(self.service_choice);
162 }
163 writer.extend_from_slice(&self.data);
164 writer.index - start
165 }
166}
167
168#[cfg(test)]
169mod tests {
170 use crate::{
171 application_protocol::application_pdu::ApduType,
172 common::io::{Reader, Writer},
173 };
174
175 use super::Segment;
176
177 #[test]
178 fn reversable() {
179 let input: [u8; 7] = [60, 1, 0, 1, 1, 2, 3];
181 let mut reader = Reader::new_with_len(input.len() - 1);
182 let decoded =
183 Segment::decode(true, ApduType::ComplexAck, &mut reader, &input[1..]).unwrap();
184
185 let mut output: [u8; 7] = [0; 7];
187 let mut writer = Writer::new(&mut output);
188 decoded.encode(&mut writer);
189 assert_eq!(input, output);
190 }
191
192 #[test]
193 fn decoding() {
194 let input: [u8; 6] = [1, 12, 1, 1, 2, 3];
196 let mut reader = Reader::new_with_len(input.len());
197 let decoded = Segment::decode(false, ApduType::ComplexAck, &mut reader, &input).unwrap();
198 assert_eq!(decoded.more_follows, false);
199 assert_eq!(decoded.sequence_number, 12);
200 assert_eq!(decoded.window_size, 1);
201 assert_eq!(decoded.apdu_type, ApduType::ComplexAck);
202 }
203}