open_dis_rust/minefield/
minefield_response_nack_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_id::EntityId,
10    pdu::Pdu,
11    pdu_header::{PduHeader, PduType, ProtocolFamily},
12};
13use bytes::{Buf, BufMut, BytesMut};
14use std::any::Any;
15
16#[derive(Clone, Debug)]
17/// Implemented according to IEEE 1278.1-2012 ยง7.9.5
18pub struct MinefieldResponseNackPdu {
19    pub pdu_header: PduHeader,
20    pub minefield_id: EntityId,
21    pub requesting_entity_id: EntityId,
22    pub request_id: u8,
23    pub number_of_missing_pdus: u8,
24    pub missing_pdu_sequence_numbers: Vec<u64>,
25}
26
27impl Default for MinefieldResponseNackPdu {
28    fn default() -> Self {
29        MinefieldResponseNackPdu {
30            pdu_header: PduHeader::default(
31                PduType::MinefieldResponseNack,
32                ProtocolFamily::Minefield,
33                56,
34            ),
35            minefield_id: EntityId::default(1),
36            requesting_entity_id: EntityId::default(2),
37            request_id: 0,
38            number_of_missing_pdus: 0,
39            missing_pdu_sequence_numbers: vec![],
40        }
41    }
42}
43
44impl Pdu for MinefieldResponseNackPdu {
45    fn serialize(&mut self, buf: &mut BytesMut) {
46        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
47            .expect("The length of the PDU should fit in a u16.");
48        self.pdu_header.serialize(buf);
49        self.minefield_id.serialize(buf);
50        self.requesting_entity_id.serialize(buf);
51        buf.put_u8(self.request_id);
52        buf.put_u8(self.number_of_missing_pdus);
53        for i in 0..self.missing_pdu_sequence_numbers.len() {
54            buf.put_u64(self.missing_pdu_sequence_numbers[i]);
55        }
56    }
57
58    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
59    where
60        Self: Sized,
61    {
62        let pdu_header = PduHeader::deserialize(&mut buffer);
63        if pdu_header.pdu_type == PduType::MinefieldResponseNack {
64            let minefield_id = EntityId::deserialize(&mut buffer);
65            let requesting_entity_id = EntityId::deserialize(&mut buffer);
66            let request_id = buffer.get_u8();
67            let number_of_missing_pdus = buffer.get_u8();
68            let mut missing_pdu_sequence_numbers: Vec<u64> = vec![];
69            for _i in 0..number_of_missing_pdus {
70                missing_pdu_sequence_numbers.push(buffer.get_u64());
71            }
72
73            Ok(MinefieldResponseNackPdu {
74                pdu_header,
75                minefield_id,
76                requesting_entity_id,
77                request_id,
78                number_of_missing_pdus,
79                missing_pdu_sequence_numbers,
80            })
81        } else {
82            Err(DISError::invalid_header(
83                format!(
84                    "Expected PDU type MinefieldResponseNack, got {:?}",
85                    pdu_header.pdu_type
86                ),
87                None,
88            ))
89        }
90    }
91
92    fn as_any(&self) -> &dyn Any {
93        self
94    }
95
96    fn deserialize_without_header(
97        mut buffer: BytesMut,
98        pdu_header: PduHeader,
99    ) -> Result<Self, DISError>
100    where
101        Self: Sized,
102    {
103        let minefield_id = EntityId::deserialize(&mut buffer);
104        let requesting_entity_id = EntityId::deserialize(&mut buffer);
105        let request_id = buffer.get_u8();
106        let number_of_missing_pdus = buffer.get_u8();
107        let mut missing_pdu_sequence_numbers: Vec<u64> = vec![];
108        for _i in 0..number_of_missing_pdus {
109            missing_pdu_sequence_numbers.push(buffer.get_u64());
110        }
111
112        Ok(MinefieldResponseNackPdu {
113            pdu_header,
114            minefield_id,
115            requesting_entity_id,
116            request_id,
117            number_of_missing_pdus,
118            missing_pdu_sequence_numbers,
119        })
120    }
121}
122
123#[cfg(test)]
124mod tests {
125    use super::MinefieldResponseNackPdu;
126    use crate::common::pdu_header::{PduHeader, PduType, ProtocolFamily};
127
128    #[test]
129    fn create_header() {
130        let minefield_response_nack_pdu = MinefieldResponseNackPdu::default();
131        let pdu_header = PduHeader::default(
132            PduType::MinefieldResponseNack,
133            ProtocolFamily::Minefield,
134            448 / 8,
135        );
136
137        assert_eq!(
138            pdu_header.protocol_version,
139            minefield_response_nack_pdu.pdu_header.protocol_version
140        );
141        assert_eq!(
142            pdu_header.exercise_id,
143            minefield_response_nack_pdu.pdu_header.exercise_id
144        );
145        assert_eq!(
146            pdu_header.pdu_type,
147            minefield_response_nack_pdu.pdu_header.pdu_type
148        );
149        assert_eq!(
150            pdu_header.protocol_family,
151            minefield_response_nack_pdu.pdu_header.protocol_family
152        );
153        assert_eq!(
154            pdu_header.length,
155            minefield_response_nack_pdu.pdu_header.length
156        );
157        assert_eq!(
158            pdu_header.status_record,
159            minefield_response_nack_pdu.pdu_header.status_record
160        );
161    }
162}