open_dis_rust/minefield/
minefield_state_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 crate::common::{
8    dis_error::DISError,
9    entity_type::EntityType,
10    euler_angles::EulerAngles,
11    pdu::Pdu,
12    pdu_header::{PduHeader, PduType, ProtocolFamily},
13    vector3_double::Vector3Double,
14};
15use bytes::{Buf, BufMut, BytesMut};
16use std::any::Any;
17
18use super::data_types::{minefield_identifier::MinefieldIdentifier, point::Point};
19
20#[derive(Clone, Debug)]
21/// Implemented according to IEEE 1278.1-2012 ยง7.9.2
22pub struct MinefieldStatePdu {
23    pub pdu_header: PduHeader,
24    pub minefield_id: MinefieldIdentifier,
25    pub minefield_sequence: u16,
26    pub force_id: u8,
27    pub number_of_perimeter_points: u8,
28    pub minefield_type: EntityType,
29    pub number_of_mine_types: u16,
30    pub minefield_location: Vector3Double,
31    pub minefield_orientation: EulerAngles,
32    pub appearance: u16,
33    pub protocol_mode: u16,
34    pub perimeter_points: Vec<Point>,
35    pub mine_type: Vec<EntityType>,
36}
37
38impl Default for MinefieldStatePdu {
39    fn default() -> Self {
40        MinefieldStatePdu {
41            pdu_header: PduHeader::default(PduType::MinefieldState, ProtocolFamily::Minefield, 56),
42            minefield_id: MinefieldIdentifier::default(),
43            minefield_sequence: 0,
44            force_id: 0,
45            number_of_perimeter_points: 0,
46            minefield_type: EntityType::default(),
47            number_of_mine_types: 0,
48            minefield_location: Vector3Double::default(),
49            minefield_orientation: EulerAngles::default(),
50            appearance: 0,
51            protocol_mode: 0,
52            perimeter_points: vec![Point::default()],
53            mine_type: vec![EntityType::default()],
54        }
55    }
56}
57
58impl Pdu for MinefieldStatePdu {
59    fn serialize(&mut self, buf: &mut BytesMut) {
60        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
61            .expect("The length of the PDU should fit in a u16.");
62        self.pdu_header.serialize(buf);
63        self.minefield_id.serialize(buf);
64        buf.put_u16(self.minefield_sequence);
65        buf.put_u8(self.force_id);
66        buf.put_u8(self.number_of_perimeter_points);
67        self.minefield_type.serialize(buf);
68        buf.put_u16(self.number_of_mine_types);
69        self.minefield_location.serialize(buf);
70        self.minefield_orientation.serialize(buf);
71        buf.put_u16(self.appearance);
72        buf.put_u16(self.protocol_mode);
73        for i in 0..self.perimeter_points.len() {
74            self.perimeter_points[i].serialize(buf);
75        }
76        for i in 0..self.mine_type.len() {
77            self.mine_type[i].serialize(buf);
78        }
79    }
80
81    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
82    where
83        Self: Sized,
84    {
85        let pdu_header = PduHeader::deserialize(&mut buffer);
86        if pdu_header.pdu_type == PduType::MinefieldState {
87            let minefield_id = MinefieldIdentifier::deserialize(&mut buffer);
88            let minefield_sequence = buffer.get_u16();
89            let force_id = buffer.get_u8();
90            let number_of_perimeter_points = buffer.get_u8();
91            let minefield_type = EntityType::deserialize(&mut buffer);
92            let number_of_mine_types = buffer.get_u16();
93            let minefield_location = Vector3Double::deserialize(&mut buffer);
94            let minefield_orientation = EulerAngles::deserialize(&mut buffer);
95            let appearance = buffer.get_u16();
96            let protocol_mode = buffer.get_u16();
97            let mut perimeter_points: Vec<Point> = vec![];
98            for _i in 0..number_of_perimeter_points {
99                perimeter_points.push(Point::deserialize(&mut buffer));
100            }
101            let mut mine_type: Vec<EntityType> = vec![];
102            for _i in 0..number_of_mine_types {
103                mine_type.push(EntityType::deserialize(&mut buffer));
104            }
105
106            Ok(MinefieldStatePdu {
107                pdu_header,
108                minefield_id,
109                minefield_sequence,
110                force_id,
111                number_of_perimeter_points,
112                minefield_type,
113                number_of_mine_types,
114                minefield_location,
115                minefield_orientation,
116                appearance,
117                protocol_mode,
118                perimeter_points,
119                mine_type,
120            })
121        } else {
122            Err(DISError::invalid_header(
123                format!(
124                    "Expected PDU type MinefieldState, got {:?}",
125                    pdu_header.pdu_type
126                ),
127                None,
128            ))
129        }
130    }
131
132    fn as_any(&self) -> &dyn Any {
133        self
134    }
135
136    fn deserialize_without_header(
137        mut buffer: BytesMut,
138        pdu_header: PduHeader,
139    ) -> Result<Self, DISError>
140    where
141        Self: Sized,
142    {
143        let minefield_id = MinefieldIdentifier::deserialize(&mut buffer);
144        let minefield_sequence = buffer.get_u16();
145        let force_id = buffer.get_u8();
146        let number_of_perimeter_points = buffer.get_u8();
147        let minefield_type = EntityType::deserialize(&mut buffer);
148        let number_of_mine_types = buffer.get_u16();
149        let minefield_location = Vector3Double::deserialize(&mut buffer);
150        let minefield_orientation = EulerAngles::deserialize(&mut buffer);
151        let appearance = buffer.get_u16();
152        let protocol_mode = buffer.get_u16();
153        let mut perimeter_points: Vec<Point> = vec![];
154        for _i in 0..number_of_perimeter_points {
155            perimeter_points.push(Point::deserialize(&mut buffer));
156        }
157        let mut mine_type: Vec<EntityType> = vec![];
158        for _i in 0..number_of_mine_types {
159            mine_type.push(EntityType::deserialize(&mut buffer));
160        }
161
162        Ok(MinefieldStatePdu {
163            pdu_header,
164            minefield_id,
165            minefield_sequence,
166            force_id,
167            number_of_perimeter_points,
168            minefield_type,
169            number_of_mine_types,
170            minefield_location,
171            minefield_orientation,
172            appearance,
173            protocol_mode,
174            perimeter_points,
175            mine_type,
176        })
177    }
178}
179
180#[cfg(test)]
181mod tests {
182    use super::MinefieldStatePdu;
183    use crate::common::pdu_header::{PduHeader, PduType, ProtocolFamily};
184
185    #[test]
186    fn create_header() {
187        let minefield_state_pdu = MinefieldStatePdu::default();
188        let pdu_header =
189            PduHeader::default(PduType::MinefieldState, ProtocolFamily::Minefield, 448 / 8);
190
191        assert_eq!(
192            pdu_header.protocol_version,
193            minefield_state_pdu.pdu_header.protocol_version
194        );
195        assert_eq!(
196            pdu_header.exercise_id,
197            minefield_state_pdu.pdu_header.exercise_id
198        );
199        assert_eq!(pdu_header.pdu_type, minefield_state_pdu.pdu_header.pdu_type);
200        assert_eq!(
201            pdu_header.protocol_family,
202            minefield_state_pdu.pdu_header.protocol_family
203        );
204        assert_eq!(pdu_header.length, minefield_state_pdu.pdu_header.length);
205        assert_eq!(
206            pdu_header.status_record,
207            minefield_state_pdu.pdu_header.status_record
208        );
209    }
210}