open_dis_rust/simulation_management/
stop_freeze_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    clock_time::ClockTime,
12    dis_error::DISError,
13    entity_id::EntityId,
14    enums::{FrozenBehavior, Reason},
15    pdu::Pdu,
16    pdu_header::{PduHeader, PduType, ProtocolFamily},
17};
18
19#[derive(Copy, Clone, Debug)]
20/// Implemented according to IEEE 1278.1-2012 ยง7.5.5
21pub struct StopFreezePdu {
22    pub pdu_header: PduHeader,
23    pub originating_entity_id: EntityId,
24    pub receiving_entity_id: EntityId,
25    pub real_world_time: ClockTime,
26    pub reason: Reason,
27    pub frozen_behavior: FrozenBehavior,
28    pub padding: i16,
29    pub request_id: u32,
30}
31
32impl Default for StopFreezePdu {
33    fn default() -> Self {
34        StopFreezePdu {
35            pdu_header: PduHeader::default(
36                PduType::StopFreeze,
37                ProtocolFamily::SimulationManagement,
38                40,
39            ),
40            originating_entity_id: EntityId::default(1),
41            receiving_entity_id: EntityId::default(2),
42            real_world_time: ClockTime::default(),
43            reason: Reason::default(),
44            frozen_behavior: FrozenBehavior::default(),
45            padding: 0,
46            request_id: 0,
47        }
48    }
49}
50
51impl Pdu for StopFreezePdu {
52    fn serialize(&mut self, buf: &mut BytesMut) {
53        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
54            .expect("The length of the PDU should fit in a u16.");
55        self.pdu_header.serialize(buf);
56        self.originating_entity_id.serialize(buf);
57        self.receiving_entity_id.serialize(buf);
58        self.real_world_time.serialize(buf);
59        buf.put_u8(self.reason as u8);
60        buf.put_u8(self.frozen_behavior.as_u8());
61        buf.put_i16(self.padding);
62        buf.put_u32(self.request_id);
63    }
64
65    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
66    where
67        Self: Sized,
68    {
69        let pdu_header = PduHeader::deserialize(&mut buffer);
70        if pdu_header.pdu_type == PduType::StopFreeze {
71            let originating_entity_id = EntityId::deserialize(&mut buffer);
72            let receiving_entity_id = EntityId::deserialize(&mut buffer);
73            let real_world_time = ClockTime::deserialize(&mut buffer);
74            let reason = Reason::deserialize(&mut buffer);
75            let frozen_behavior = FrozenBehavior::from_u8(buffer.get_u8()).unwrap();
76            let padding = buffer.get_i16();
77            let request_id = buffer.get_u32();
78
79            Ok(StopFreezePdu {
80                pdu_header,
81                originating_entity_id,
82                receiving_entity_id,
83                real_world_time,
84                reason,
85                frozen_behavior,
86                padding,
87                request_id,
88            })
89        } else {
90            Err(DISError::invalid_header(
91                format!(
92                    "Expected PDU type StopFreeze, got {:?}",
93                    pdu_header.pdu_type
94                ),
95                None,
96            ))
97        }
98    }
99
100    fn as_any(&self) -> &dyn Any {
101        self
102    }
103
104    fn deserialize_without_header(
105        mut buffer: BytesMut,
106        pdu_header: PduHeader,
107    ) -> Result<Self, DISError>
108    where
109        Self: Sized,
110    {
111        let originating_entity_id = EntityId::deserialize(&mut buffer);
112        let receiving_entity_id = EntityId::deserialize(&mut buffer);
113        let real_world_time = ClockTime::deserialize(&mut buffer);
114        let reason = Reason::deserialize(&mut buffer);
115        let frozen_behavior = FrozenBehavior::from_u8(buffer.get_u8()).unwrap();
116        let padding = buffer.get_i16();
117        let request_id = buffer.get_u32();
118
119        Ok(StopFreezePdu {
120            pdu_header,
121            originating_entity_id,
122            receiving_entity_id,
123            real_world_time,
124            reason,
125            frozen_behavior,
126            padding,
127            request_id,
128        })
129    }
130}
131
132#[cfg(test)]
133mod tests {
134    use super::StopFreezePdu;
135    use crate::common::{
136        pdu::Pdu,
137        pdu_header::{PduHeader, PduType, ProtocolFamily},
138    };
139    use bytes::BytesMut;
140
141    #[test]
142    fn create_header() {
143        let stop_freeze_pdu = StopFreezePdu::default();
144        let pdu_header = PduHeader::default(
145            PduType::StopFreeze,
146            ProtocolFamily::SimulationManagement,
147            40,
148        );
149
150        assert_eq!(
151            pdu_header.protocol_version,
152            stop_freeze_pdu.pdu_header.protocol_version
153        );
154        assert_eq!(
155            pdu_header.exercise_id,
156            stop_freeze_pdu.pdu_header.exercise_id
157        );
158        assert_eq!(pdu_header.pdu_type, stop_freeze_pdu.pdu_header.pdu_type);
159        assert_eq!(
160            pdu_header.protocol_family,
161            stop_freeze_pdu.pdu_header.protocol_family
162        );
163        assert_eq!(pdu_header.length, stop_freeze_pdu.pdu_header.length);
164        assert_eq!(
165            pdu_header.status_record,
166            stop_freeze_pdu.pdu_header.status_record
167        );
168    }
169
170    #[test]
171    fn deserialize_header() {
172        let mut stop_freeze_pdu = StopFreezePdu::default();
173        let mut buffer = BytesMut::new();
174        stop_freeze_pdu.serialize(&mut buffer);
175
176        let new_stop_freeze_pdu = StopFreezePdu::deserialize(buffer).unwrap();
177        assert_eq!(new_stop_freeze_pdu.pdu_header, stop_freeze_pdu.pdu_header);
178    }
179}