open_dis_rust/synthetic_environment/
linear_object_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 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    simulation_address::SimulationAddress,
16};
17
18use super::data_types::{
19    linear_segment_parameter::LinearSegmentParameter, object_type::ObjectType,
20};
21
22#[derive(Clone, Debug)]
23/// Implemented according to IEEE 1278.1-2012 ยง7.10.5
24pub struct LinearObjectStatePdu {
25    pub pdu_header: PduHeader,
26    pub object_id: EntityId,
27    pub referenced_object_id: EntityId,
28    pub update_number: u16,
29    pub force_id: u8,
30    pub number_of_segments: u8,
31    pub requester_id: SimulationAddress,
32    pub receiving_id: SimulationAddress,
33    pub object_type: ObjectType,
34    pub linear_segment_parameters: Vec<LinearSegmentParameter>,
35}
36
37impl Default for LinearObjectStatePdu {
38    /// Creates a default Linear Object State PDU with arbitrary environmental process ID
39    ///
40    /// # Examples
41    ///
42    /// Initializing an Linear Object State PDU:
43    /// ```
44    /// use open_dis_rust::synthetic_environment::linear_object_state_pdu::LinearObjectStatePdu;
45    /// let linear_object_state_pdu = LinearObjectStatePdu::default();
46    /// ```
47    ///
48    fn default() -> Self {
49        LinearObjectStatePdu {
50            pdu_header: PduHeader::default(
51                PduType::LinearObjectState,
52                ProtocolFamily::SyntheticEnvironment,
53                56,
54            ),
55            object_id: EntityId::default(1),
56            referenced_object_id: EntityId::default(2),
57            update_number: 0,
58            force_id: 0,
59            number_of_segments: 0,
60            requester_id: SimulationAddress::default(),
61            receiving_id: SimulationAddress::default(),
62            object_type: ObjectType::default(),
63            linear_segment_parameters: vec![],
64        }
65    }
66}
67
68impl Pdu for LinearObjectStatePdu {
69    fn serialize(&mut self, buf: &mut BytesMut) {
70        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
71            .expect("The length of the PDU should fit in a u16.");
72        self.pdu_header.serialize(buf);
73        self.object_id.serialize(buf);
74        self.referenced_object_id.serialize(buf);
75        buf.put_u16(self.update_number);
76        buf.put_u8(self.force_id);
77        buf.put_u8(self.number_of_segments);
78        self.requester_id.serialize(buf);
79        self.receiving_id.serialize(buf);
80        self.object_type.serialize(buf);
81        for i in 0..self.linear_segment_parameters.len() {
82            self.linear_segment_parameters[i].serialize(buf);
83        }
84    }
85
86    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
87    where
88        Self: Sized,
89    {
90        let pdu_header = PduHeader::deserialize(&mut buffer);
91        if pdu_header.pdu_type == PduType::LinearObjectState {
92            let object_id = EntityId::deserialize(&mut buffer);
93            let referenced_object_id = EntityId::deserialize(&mut buffer);
94            let update_number = buffer.get_u16();
95            let force_id = buffer.get_u8();
96            let number_of_segments = buffer.get_u8();
97            let requester_id = SimulationAddress::deserialize(&mut buffer);
98            let receiving_id = SimulationAddress::deserialize(&mut buffer);
99            let object_type = ObjectType::deserialize(&mut buffer);
100            let mut linear_segment_parameters: Vec<LinearSegmentParameter> = vec![];
101            for _i in 0..number_of_segments {
102                linear_segment_parameters.push(LinearSegmentParameter::deserialize(&mut buffer));
103            }
104            Ok(LinearObjectStatePdu {
105                pdu_header,
106                object_id,
107                referenced_object_id,
108                update_number,
109                force_id,
110                number_of_segments,
111                requester_id,
112                receiving_id,
113                object_type,
114                linear_segment_parameters,
115            })
116        } else {
117            Err(DISError::invalid_header(
118                format!(
119                    "Expected PDU type LinearObjectState, got {:?}",
120                    pdu_header.pdu_type
121                ),
122                None,
123            ))
124        }
125    }
126
127    fn as_any(&self) -> &dyn Any {
128        self
129    }
130
131    fn deserialize_without_header(
132        mut buffer: BytesMut,
133        pdu_header: PduHeader,
134    ) -> Result<Self, DISError>
135    where
136        Self: Sized,
137    {
138        let object_id = EntityId::deserialize(&mut buffer);
139        let referenced_object_id = EntityId::deserialize(&mut buffer);
140        let update_number = buffer.get_u16();
141        let force_id = buffer.get_u8();
142        let number_of_segments = buffer.get_u8();
143        let requester_id = SimulationAddress::deserialize(&mut buffer);
144        let receiving_id = SimulationAddress::deserialize(&mut buffer);
145        let object_type = ObjectType::deserialize(&mut buffer);
146        let mut linear_segment_parameters: Vec<LinearSegmentParameter> = vec![];
147        for _i in 0..number_of_segments {
148            linear_segment_parameters.push(LinearSegmentParameter::deserialize(&mut buffer));
149        }
150        Ok(LinearObjectStatePdu {
151            pdu_header,
152            object_id,
153            referenced_object_id,
154            update_number,
155            force_id,
156            number_of_segments,
157            requester_id,
158            receiving_id,
159            object_type,
160            linear_segment_parameters,
161        })
162    }
163}
164
165#[cfg(test)]
166mod tests {
167    use super::LinearObjectStatePdu;
168    use crate::common::{
169        pdu::Pdu,
170        pdu_header::{PduHeader, PduType, ProtocolFamily},
171    };
172    use bytes::BytesMut;
173
174    #[test]
175    fn create_header() {
176        let linear_object_state_pdu = LinearObjectStatePdu::default();
177        let pdu_header = PduHeader::default(
178            PduType::LinearObjectState,
179            ProtocolFamily::SyntheticEnvironment,
180            448 / 8,
181        );
182
183        assert_eq!(
184            pdu_header.protocol_version,
185            linear_object_state_pdu.pdu_header.protocol_version
186        );
187        assert_eq!(
188            pdu_header.exercise_id,
189            linear_object_state_pdu.pdu_header.exercise_id
190        );
191        assert_eq!(
192            pdu_header.pdu_type,
193            linear_object_state_pdu.pdu_header.pdu_type
194        );
195        assert_eq!(
196            pdu_header.protocol_family,
197            linear_object_state_pdu.pdu_header.protocol_family
198        );
199        assert_eq!(pdu_header.length, linear_object_state_pdu.pdu_header.length);
200        assert_eq!(
201            pdu_header.status_record,
202            linear_object_state_pdu.pdu_header.status_record
203        );
204    }
205
206    #[test]
207    fn deserialize_header() {
208        let mut linear_object_state_pdu = LinearObjectStatePdu::default();
209        let mut buffer = BytesMut::new();
210        linear_object_state_pdu.serialize(&mut buffer);
211
212        let new_linear_object_state_pdu = LinearObjectStatePdu::deserialize(buffer).unwrap();
213        assert_eq!(
214            new_linear_object_state_pdu.pdu_header,
215            linear_object_state_pdu.pdu_header
216        );
217    }
218}