open_dis_rust/entity_management/
is_group_of_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    pdu::Pdu,
14    pdu_header::{PduHeader, PduType, ProtocolFamily},
15};
16
17#[derive(Clone, Debug)]
18/// Implemented according to IEEE 1278.1-2012 ยง7.8.3
19pub struct IsGroupOfPdu {
20    pub pdu_header: PduHeader,
21    pub group_entity_id: EntityId,
22    pub grouped_entity_category: u8,
23    pub number_of_grouped_entities: u8,
24    pub pad2: u32,
25    pub latitude: f64,
26    pub longitude: f64,
27    pub grouped_entity_descriptions: Vec<u64>,
28}
29
30impl Default for IsGroupOfPdu {
31    /// Creates a default Is Group Of PDU with arbitrary aggregate ID
32    ///
33    /// # Examples
34    ///
35    /// Initializing an Is Group Of PDU:
36    /// ```
37    /// use open_dis_rust::entity_management::is_group_of_pdu::IsGroupOfPdu;
38    /// let is_group_of_pdu = IsGroupOfPdu::default();
39    /// ```
40    ///
41    fn default() -> Self {
42        IsGroupOfPdu {
43            pdu_header: PduHeader::default(
44                PduType::IsGroupOf,
45                ProtocolFamily::EntityManagement,
46                56,
47            ),
48            group_entity_id: EntityId::default(1),
49            grouped_entity_category: 0,
50            number_of_grouped_entities: 0,
51            pad2: 0,
52            latitude: 0.0,
53            longitude: 0.0,
54            grouped_entity_descriptions: vec![],
55        }
56    }
57}
58
59impl Pdu for IsGroupOfPdu {
60    fn serialize(&mut self, buf: &mut BytesMut) {
61        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
62            .expect("The length of the PDU should fit in a u16.");
63        self.pdu_header.serialize(buf);
64        self.group_entity_id.serialize(buf);
65        buf.put_u8(self.grouped_entity_category);
66        buf.put_u8(self.number_of_grouped_entities);
67        buf.put_u32(self.pad2);
68        buf.put_f64(self.latitude);
69        buf.put_f64(self.longitude);
70        for i in 0..self.grouped_entity_descriptions.len() {
71            buf.put_u64(self.grouped_entity_descriptions[i]);
72        }
73    }
74
75    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
76    where
77        Self: Sized,
78    {
79        let pdu_header = PduHeader::deserialize(&mut buffer);
80        if pdu_header.pdu_type == PduType::IsGroupOf {
81            let group_entity_id = EntityId::deserialize(&mut buffer);
82            let grouped_entity_category = buffer.get_u8();
83            let number_of_grouped_entities = buffer.get_u8();
84            let pad2 = buffer.get_u32();
85            let latitude = buffer.get_f64();
86            let longitude = buffer.get_f64();
87            let mut grouped_entity_descriptions: Vec<u64> = vec![];
88            for _i in 0..number_of_grouped_entities {
89                grouped_entity_descriptions.push(buffer.get_u64());
90            }
91            Ok(IsGroupOfPdu {
92                pdu_header,
93                group_entity_id,
94                grouped_entity_category,
95                number_of_grouped_entities,
96                pad2,
97                latitude,
98                longitude,
99                grouped_entity_descriptions,
100            })
101        } else {
102            Err(DISError::invalid_header(
103                format!("Expected PDU type IsGroupOf, got {:?}", pdu_header.pdu_type),
104                None,
105            ))
106        }
107    }
108
109    fn as_any(&self) -> &dyn Any {
110        self
111    }
112
113    fn deserialize_without_header(
114        mut buffer: BytesMut,
115        pdu_header: PduHeader,
116    ) -> Result<Self, DISError>
117    where
118        Self: Sized,
119    {
120        let group_entity_id = EntityId::deserialize(&mut buffer);
121        let grouped_entity_category = buffer.get_u8();
122        let number_of_grouped_entities = buffer.get_u8();
123        let pad2 = buffer.get_u32();
124        let latitude = buffer.get_f64();
125        let longitude = buffer.get_f64();
126        let mut grouped_entity_descriptions: Vec<u64> = vec![];
127        for _i in 0..number_of_grouped_entities {
128            grouped_entity_descriptions.push(buffer.get_u64());
129        }
130        Ok(IsGroupOfPdu {
131            pdu_header,
132            group_entity_id,
133            grouped_entity_category,
134            number_of_grouped_entities,
135            pad2,
136            latitude,
137            longitude,
138            grouped_entity_descriptions,
139        })
140    }
141}
142
143#[cfg(test)]
144mod tests {
145    use super::IsGroupOfPdu;
146    use crate::common::{
147        pdu::Pdu,
148        pdu_header::{PduHeader, PduType, ProtocolFamily},
149    };
150    use bytes::BytesMut;
151
152    #[test]
153    fn create_header() {
154        let is_group_of_pdu = IsGroupOfPdu::default();
155        let pdu_header = PduHeader::default(
156            PduType::IsGroupOf,
157            ProtocolFamily::EntityManagement,
158            448 / 8,
159        );
160
161        assert_eq!(
162            pdu_header.protocol_version,
163            is_group_of_pdu.pdu_header.protocol_version
164        );
165        assert_eq!(
166            pdu_header.exercise_id,
167            is_group_of_pdu.pdu_header.exercise_id
168        );
169        assert_eq!(pdu_header.pdu_type, is_group_of_pdu.pdu_header.pdu_type);
170        assert_eq!(
171            pdu_header.protocol_family,
172            is_group_of_pdu.pdu_header.protocol_family
173        );
174        assert_eq!(pdu_header.length, is_group_of_pdu.pdu_header.length);
175        assert_eq!(
176            pdu_header.status_record,
177            is_group_of_pdu.pdu_header.status_record
178        );
179    }
180
181    #[test]
182    fn deserialize_header() {
183        let mut is_group_of_pdu = IsGroupOfPdu::default();
184        let mut buffer = BytesMut::new();
185        is_group_of_pdu.serialize(&mut buffer);
186
187        let new_is_group_of_pdu = IsGroupOfPdu::deserialize(buffer).unwrap();
188        assert_eq!(new_is_group_of_pdu.pdu_header, is_group_of_pdu.pdu_header);
189    }
190}