rseip_core/cip/
common_packet.rs

1// rseip
2//
3// rseip - Ethernet/IP (CIP) in pure Rust.
4// Copyright: 2021, Joylei <leingliu@gmail.com>
5// License: MIT
6
7use crate::{codec::*, hex::AsHex, Error};
8use bytes::{Buf, Bytes, BytesMut};
9use core::{
10    marker::PhantomData,
11    ops::{Deref, DerefMut},
12};
13use smallvec::SmallVec;
14
15type Array<T> = [CommonPacketItem<T>; 4];
16
17/// common packet format
18#[derive(Default, Debug)]
19pub struct CommonPacket<T>(SmallVec<Array<T>>);
20
21impl<T> CommonPacket<T> {
22    /// new object
23    #[inline]
24    pub fn new() -> Self {
25        Self(Default::default())
26    }
27
28    /// append an item
29    #[inline]
30    pub fn push(&mut self, item: CommonPacketItem<T>) {
31        self.0.push(item);
32    }
33
34    /// panic if idx is out of range
35    #[inline]
36    pub fn remove(&mut self, idx: usize) -> CommonPacketItem<T> {
37        self.0.remove(idx)
38    }
39}
40
41impl<T> Deref for CommonPacket<T> {
42    type Target = [CommonPacketItem<T>];
43    #[inline]
44    fn deref(&self) -> &Self::Target {
45        &self.0
46    }
47}
48
49impl<T> DerefMut for CommonPacket<T> {
50    #[inline]
51    fn deref_mut(&mut self) -> &mut Self::Target {
52        &mut self.0
53    }
54}
55
56impl<T> From<Vec<CommonPacketItem<T>>> for CommonPacket<T> {
57    #[inline]
58    fn from(src: Vec<CommonPacketItem<T>>) -> Self {
59        Self(SmallVec::from_vec(src))
60    }
61}
62
63impl<T> IntoIterator for CommonPacket<T> {
64    type Item = CommonPacketItem<T>;
65    type IntoIter = crate::iter::IntoIter<Array<T>>;
66    fn into_iter(self) -> Self::IntoIter {
67        crate::iter::IntoIter::new(self.0)
68    }
69}
70
71/// common packet format item
72#[derive(Debug)]
73pub struct CommonPacketItem<T> {
74    pub type_code: u16,
75    pub data: T,
76}
77
78impl CommonPacketItem<Bytes> {
79    /// null address
80    #[inline]
81    pub fn with_null_addr() -> Self {
82        Self {
83            type_code: 0,
84            data: Bytes::from_static(&[0x00, 0x00]),
85        }
86    }
87
88    /// unconnected data item
89    #[inline]
90    pub fn with_unconnected_data(data: Bytes) -> Self {
91        Self {
92            type_code: 0xB2,
93            data,
94        }
95    }
96
97    /// connected data item
98    #[inline]
99    pub fn with_connected_data(data: Bytes) -> Self {
100        Self {
101            type_code: 0xB1,
102            data,
103        }
104    }
105
106    /// is null address
107    #[inline]
108    pub fn is_null_addr(&self) -> bool {
109        if self.type_code != 0 {
110            return false;
111        }
112        self.data.is_empty()
113    }
114}
115
116impl<T> CommonPacketItem<T> {
117    /// ensure current item matches the specified type code
118    #[inline]
119    pub fn ensure_type_code<E: Error>(&self, type_code: u16) -> Result<(), E> {
120        if self.type_code != type_code {
121            return Err(E::invalid_value(
122                format_args!("common packet item type {}", self.type_code.as_hex()),
123                type_code.as_hex(),
124            ));
125        }
126        Ok(())
127    }
128}
129
130/// lazy decoder for common packet
131pub struct CommonPacketIter<'de, D> {
132    pub(crate) decoder: D,
133    offset: u16,
134    total: u16,
135    _marker: PhantomData<&'de D>,
136}
137
138impl<'de, D> CommonPacketIter<'de, D>
139where
140    D: Decoder<'de>,
141{
142    #[inline]
143    pub fn new(mut decoder: D) -> Result<Self, D::Error> {
144        let item_count: u16 = decoder.decode_any()?;
145        Ok(Self {
146            decoder,
147            total: item_count,
148            offset: 0,
149            _marker: Default::default(),
150        })
151    }
152
153    #[inline]
154    pub fn len(&self) -> usize {
155        self.total as usize
156    }
157
158    #[inline]
159    pub fn is_empty(&self) -> bool {
160        self.total == 0
161    }
162
163    #[inline]
164    fn has_remaining(&self) -> bool {
165        !(self.total == 0 || self.offset >= self.total)
166    }
167
168    /// next common packet item, strong typed
169    #[inline]
170    pub fn next_typed<T>(&mut self) -> Option<Result<CommonPacketItem<T>, D::Error>>
171    where
172        T: Decode<'de> + 'static,
173    {
174        self.move_next()
175    }
176
177    /// next common packet item
178    #[inline]
179    pub fn next_item(&mut self) -> Option<Result<CommonPacketItem<Bytes>, D::Error>> {
180        self.move_next()
181    }
182
183    /// next common packet item
184    #[inline]
185    fn move_next<T>(&mut self) -> Option<Result<T, D::Error>>
186    where
187        T: Decode<'de>,
188    {
189        if !self.has_remaining() {
190            return None;
191        }
192
193        let res = self.decoder.decode_any();
194        if res.is_ok() {
195            self.offset += 1;
196        }
197        Some(res)
198    }
199
200    /// visit next common packet item
201    #[inline]
202    pub fn accept<V>(
203        &mut self,
204        expected_type_code: u16,
205        visitor: V,
206    ) -> Option<Result<CommonPacketItem<V::Value>, D::Error>>
207    where
208        V: Visitor<'de>,
209    {
210        if !self.has_remaining() {
211            return None;
212        }
213        let res =
214            CommonPacketItem::validate_and_decode(&mut self.decoder, expected_type_code, visitor);
215        if res.is_ok() {
216            self.offset += 1;
217        }
218        Some(res)
219    }
220}
221
222impl<T: Encode> Encode for CommonPacket<T> {
223    #[inline]
224    fn encode<A: Encoder>(self, buf: &mut BytesMut, encoder: &mut A) -> Result<(), A::Error>
225    where
226        Self: Sized,
227    {
228        debug_assert!(self.len() <= u16::MAX as usize);
229        encoder.encode(self.len() as u16, buf)?;
230        for item in self.into_iter() {
231            encoder.encode(item, buf)?;
232        }
233        Ok(())
234    }
235    #[inline]
236    fn encode_by_ref<A: Encoder>(
237        &self,
238        buf: &mut BytesMut,
239        encoder: &mut A,
240    ) -> Result<(), A::Error> {
241        debug_assert!(self.len() <= u16::MAX as usize);
242        encoder.encode(self.len() as u16, buf)?;
243        for item in self.0.iter() {
244            encoder.encode_by_ref(item, buf)?;
245        }
246        Ok(())
247    }
248
249    #[inline]
250    fn bytes_count(&self) -> usize {
251        let count: usize = self.iter().map(|v| v.bytes_count()).sum();
252        count + 2
253    }
254}
255
256impl<T> CommonPacketItem<T> {
257    pub fn validate_and_decode<'de, D, V>(
258        mut decoder: D,
259        expected_type_code: u16,
260        visitor: V,
261    ) -> Result<Self, D::Error>
262    where
263        D: Decoder<'de>,
264        V: Visitor<'de, Value = T>,
265    {
266        decoder.ensure_size(4)?;
267        let type_code = decoder.decode_u16();
268        if type_code != expected_type_code {
269            return Err(Error::invalid_value(
270                format_args!("common packet type code {:#02x}", type_code),
271                expected_type_code.as_hex(),
272            ));
273        }
274        let item_length = decoder.decode_u16();
275        let data = decoder.decode_sized(item_length as usize, visitor)?;
276        Ok(Self { type_code, data })
277    }
278
279    pub fn decode_with<'de, D, V>(mut decoder: D, visitor: V) -> Result<Self, D::Error>
280    where
281        D: Decoder<'de>,
282        V: Visitor<'de, Value = T>,
283    {
284        decoder.ensure_size(4)?;
285        let type_code = decoder.decode_u16();
286        let item_length = decoder.decode_u16();
287        let data = decoder.decode_sized(item_length as usize, visitor)?;
288        Ok(Self { type_code, data })
289    }
290}
291
292impl<'de, T: Decode<'de> + 'static> Decode<'de> for CommonPacket<T> {
293    #[inline]
294    fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
295    where
296        D: Decoder<'de>,
297    {
298        let item_count: u16 = decoder.decode_any()?;
299        let mut cpf = CommonPacket::new();
300        for _ in 0..item_count {
301            cpf.push(decoder.decode_any()?);
302        }
303        Ok(cpf)
304    }
305}
306
307impl<'de> Decode<'de> for CommonPacketItem<Bytes> {
308    #[inline]
309    fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
310    where
311        D: Decoder<'de>,
312    {
313        decoder.ensure_size(4)?;
314        let type_code = decoder.decode_u16();
315        let item_length = decoder.decode_u16() as usize;
316        decoder.ensure_size(item_length)?;
317        Ok(Self {
318            type_code,
319            data: decoder.buf_mut().copy_to_bytes(item_length),
320        })
321    }
322}
323
324impl<'de, T: Decode<'de> + 'static> Decode<'de> for CommonPacketItem<T> {
325    #[inline]
326    fn decode<D>(decoder: D) -> Result<Self, D::Error>
327    where
328        D: Decoder<'de>,
329    {
330        Self::decode_with(decoder, visitor::any())
331    }
332}
333
334impl<T: Encode> Encode for CommonPacketItem<T> {
335    #[inline]
336    fn encode<A: Encoder>(self, buf: &mut BytesMut, encoder: &mut A) -> Result<(), A::Error> {
337        debug_assert!(self.bytes_count() <= u16::MAX as usize);
338        encoder.encode_u16(self.type_code, buf)?;
339        encoder.encode_u16(self.data.bytes_count() as u16, buf)?;
340        encoder.encode(self.data, buf)?;
341        Ok(())
342    }
343    #[inline]
344    fn encode_by_ref<A: Encoder>(
345        &self,
346        buf: &mut BytesMut,
347        encoder: &mut A,
348    ) -> Result<(), A::Error> {
349        debug_assert!(self.bytes_count() <= u16::MAX as usize);
350        encoder.encode_u16(self.type_code, buf)?;
351        encoder.encode_u16(self.data.bytes_count() as u16, buf)?;
352        encoder.encode_by_ref(&self.data, buf)?;
353        Ok(())
354    }
355    #[inline]
356    fn bytes_count(&self) -> usize {
357        4 + self.data.bytes_count()
358    }
359}