open_dis_rust/synthetic_environment/
environmental_process_pdu.rs

1//     open-dis-rust - Rust implementation of the IEEE 1278.1-2012 Distributed Interactive
2//                     Simulation (DIS) application protocol
3//     Copyright (C) 2023 Cameron Howell
4//
5//     Licensed under the BSD 2-Clause License
6
7use bytes::{Buf, BufMut, BytesMut};
8use std::any::Any;
9
10use crate::common::{
11    dis_error::DISError,
12    entity_id::EntityId,
13    entity_type::EntityType,
14    pdu::Pdu,
15    pdu_header::{PduHeader, PduType, ProtocolFamily},
16};
17
18use super::data_types::environment::Environment;
19
20#[derive(Clone, Debug)]
21/// Implemented according to IEEE 1278.1-2012 ยง7.10.2
22pub struct EnvironmentalProcessPdu {
23    pub pdu_header: PduHeader,
24    pub environmental_process_id: EntityId,
25    pub environment_type: EntityType,
26    pub model_type: u8,
27    pub environment_status: u8,
28    pub number_of_environment_records: u8,
29    pub sequence_number: u8,
30    pub environment_records: Vec<Environment>,
31}
32
33impl Default for EnvironmentalProcessPdu {
34    /// Creates a default Environmental Process PDU with arbitrary environmental process ID
35    ///
36    /// # Examples
37    ///
38    /// Initializing an Environmental Process PDU:
39    /// ```
40    /// use open_dis_rust::synthetic_environment::environmental_process_pdu::EnvironmentalProcessPdu;
41    /// let environmental_process_pdu = EnvironmentalProcessPdu::default();
42    /// ```
43    ///
44    fn default() -> Self {
45        EnvironmentalProcessPdu {
46            pdu_header: PduHeader::default(
47                PduType::EnvironmentalProcess,
48                ProtocolFamily::SyntheticEnvironment,
49                56,
50            ),
51            environmental_process_id: EntityId::default(1),
52            environment_type: EntityType::default(),
53            model_type: 0,
54            environment_status: 0,
55            number_of_environment_records: 0,
56            sequence_number: 0,
57            environment_records: vec![],
58        }
59    }
60}
61
62impl Pdu for EnvironmentalProcessPdu {
63    fn serialize(&mut self, buf: &mut BytesMut) {
64        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
65            .expect("The length of the PDU should fit in a u16.");
66        self.pdu_header.serialize(buf);
67        self.environmental_process_id.serialize(buf);
68        self.environment_type.serialize(buf);
69        buf.put_u8(self.model_type);
70        buf.put_u8(self.environment_status);
71        buf.put_u8(self.number_of_environment_records);
72        buf.put_u8(self.sequence_number);
73        for i in 0..self.environment_records.len() {
74            self.environment_records[i].serialize(buf);
75        }
76    }
77
78    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
79    where
80        Self: Sized,
81    {
82        let pdu_header = PduHeader::deserialize(&mut buffer);
83        if pdu_header.pdu_type == PduType::EnvironmentalProcess {
84            let environmental_process_id = EntityId::deserialize(&mut buffer);
85            let environment_type = EntityType::deserialize(&mut buffer);
86            let model_type = buffer.get_u8();
87            let environment_status = buffer.get_u8();
88            let number_of_environment_records = buffer.get_u8();
89            let sequence_number = buffer.get_u8();
90            let mut environment_records: Vec<Environment> = vec![];
91            for _i in 0..number_of_environment_records {
92                environment_records.push(Environment::deserialize(&mut buffer));
93            }
94            Ok(EnvironmentalProcessPdu {
95                pdu_header,
96                environmental_process_id,
97                environment_type,
98                model_type,
99                environment_status,
100                number_of_environment_records,
101                sequence_number,
102                environment_records,
103            })
104        } else {
105            Err(DISError::invalid_header(
106                format!(
107                    "Expected PDU type EnvironmentalProcess, got {:?}",
108                    pdu_header.pdu_type
109                ),
110                None,
111            ))
112        }
113    }
114
115    fn as_any(&self) -> &dyn Any {
116        self
117    }
118
119    fn deserialize_without_header(
120        mut buffer: BytesMut,
121        pdu_header: PduHeader,
122    ) -> Result<Self, DISError>
123    where
124        Self: Sized,
125    {
126        let environmental_process_id = EntityId::deserialize(&mut buffer);
127        let environment_type = EntityType::deserialize(&mut buffer);
128        let model_type = buffer.get_u8();
129        let environment_status = buffer.get_u8();
130        let number_of_environment_records = buffer.get_u8();
131        let sequence_number = buffer.get_u8();
132        let mut environment_records: Vec<Environment> = vec![];
133        for _i in 0..number_of_environment_records {
134            environment_records.push(Environment::deserialize(&mut buffer));
135        }
136        Ok(EnvironmentalProcessPdu {
137            pdu_header,
138            environmental_process_id,
139            environment_type,
140            model_type,
141            environment_status,
142            number_of_environment_records,
143            sequence_number,
144            environment_records,
145        })
146    }
147}
148
149#[cfg(test)]
150mod tests {
151    use super::EnvironmentalProcessPdu;
152    use crate::common::{
153        pdu::Pdu,
154        pdu_header::{PduHeader, PduType, ProtocolFamily},
155    };
156    use bytes::BytesMut;
157
158    #[test]
159    fn create_header() {
160        let environmental_process_pdu = EnvironmentalProcessPdu::default();
161        let pdu_header = PduHeader::default(
162            PduType::EnvironmentalProcess,
163            ProtocolFamily::SyntheticEnvironment,
164            448 / 8,
165        );
166
167        assert_eq!(
168            pdu_header.protocol_version,
169            environmental_process_pdu.pdu_header.protocol_version
170        );
171        assert_eq!(
172            pdu_header.exercise_id,
173            environmental_process_pdu.pdu_header.exercise_id
174        );
175        assert_eq!(
176            pdu_header.pdu_type,
177            environmental_process_pdu.pdu_header.pdu_type
178        );
179        assert_eq!(
180            pdu_header.protocol_family,
181            environmental_process_pdu.pdu_header.protocol_family
182        );
183        assert_eq!(
184            pdu_header.length,
185            environmental_process_pdu.pdu_header.length
186        );
187        assert_eq!(
188            pdu_header.status_record,
189            environmental_process_pdu.pdu_header.status_record
190        );
191    }
192
193    #[test]
194    fn deserialize_header() {
195        let mut environmental_process_pdu = EnvironmentalProcessPdu::default();
196        let mut buffer = BytesMut::new();
197        environmental_process_pdu.serialize(&mut buffer);
198
199        let new_environmental_process_pdu = EnvironmentalProcessPdu::deserialize(buffer).unwrap();
200        assert_eq!(
201            new_environmental_process_pdu.pdu_header,
202            environmental_process_pdu.pdu_header
203        );
204    }
205}