rseip/client/ab_eip/
value.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::ClientError;
8use bytes::{Buf, BufMut, Bytes, BytesMut};
9use core::marker::PhantomData;
10use rseip_core::{codec::*, Error};
11use smallvec::SmallVec;
12
13/// atomic data type: BOOL
14#[allow(clippy::upper_case_acronyms)]
15#[allow(unused)]
16pub type BOOL = bool;
17/// atomic data type: DWORD, 32-bit boolean array
18#[allow(clippy::upper_case_acronyms)]
19#[allow(unused)]
20pub type DWORD = u32;
21/// atomic data type: SINT, 8-bit integer
22#[allow(clippy::upper_case_acronyms)]
23#[allow(unused)]
24pub type SINT = i8;
25/// atomic data type: INT, 16-bit integer
26#[allow(clippy::upper_case_acronyms)]
27#[allow(unused)]
28pub type INT = i16;
29/// atomic data type: DINT, 32-bit integer
30#[allow(clippy::upper_case_acronyms)]
31#[allow(unused)]
32pub type DINT = i32;
33/// atomic data type: LINT, 64-bit integer
34#[allow(clippy::upper_case_acronyms)]
35#[allow(unused)]
36pub type LINT = i64;
37/// atomic data type: REAL, 32-bit float
38#[allow(clippy::upper_case_acronyms)]
39#[allow(unused)]
40pub type REAL = f32;
41
42/// tag type for AB PLC
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub enum TagType {
45    /// atomic data type: BOOL
46    Bool,
47    /// atomic data type: DWORD, 32-bit boolean array
48    Dword,
49    /// atomic data type: SINT, 8-bit integer
50    Sint,
51    /// atomic data type: INT, 16-bit integer
52    Int,
53    /// atomic data type: DINT, 32-bit integer
54    Dint,
55    /// atomic data type: LINT, 64-bit integer
56    Lint,
57    /// atomic data type: REAL, 32-bit float
58    Real,
59    /// structured tag
60    Structure(u16),
61}
62
63impl TagType {
64    /// two bytes type code
65    #[inline]
66    pub fn type_code(&self) -> u16 {
67        match self {
68            Self::Bool => 0xC1,
69            Self::Dword => 0xD3,
70            Self::Sint => 0xC2,
71            Self::Int => 0xC3,
72            Self::Dint => 0xC4,
73            Self::Lint => 0xC5,
74            Self::Real => 0xCA,
75            Self::Structure { .. } => 0x02A0,
76        }
77    }
78
79    /// is it a structure
80    pub fn is_structure(&self) -> bool {
81        match self {
82            Self::Structure(_) => true,
83            _ => false,
84        }
85    }
86
87    /// is it a atomic type
88    pub fn is_atomic(&self) -> bool {
89        !self.is_structure()
90    }
91
92    /// get structure handle if it's a structure
93    pub fn structure_handle(&self) -> Option<u16> {
94        match self {
95            Self::Structure(v) => Some(*v),
96            _ => None,
97        }
98    }
99}
100
101impl Encode for TagType {
102    #[inline]
103    fn encode_by_ref<A: Encoder>(
104        &self,
105        buf: &mut BytesMut,
106        encoder: &mut A,
107    ) -> Result<(), A::Error> {
108        match self {
109            Self::Bool => {
110                encoder.encode_u16(0xC1, buf)?;
111            }
112            Self::Sint => {
113                encoder.encode_u16(0xC2, buf)?;
114            }
115            Self::Int => {
116                encoder.encode_u16(0xC3, buf)?;
117            }
118            Self::Dint => {
119                encoder.encode_u16(0xC4, buf)?;
120            }
121            Self::Real => {
122                encoder.encode_u16(0xCA, buf)?;
123            }
124            Self::Dword => {
125                encoder.encode_u16(0xD3, buf)?;
126            }
127            Self::Lint => {
128                encoder.encode_u16(0xC5, buf)?;
129            }
130            Self::Structure(handle) => {
131                encoder.encode(&[0xA0, 0x02], buf)?;
132                encoder.encode_u16(*handle, buf)?;
133            }
134        }
135        Ok(())
136    }
137
138    #[inline(always)]
139    fn bytes_count(&self) -> usize {
140        match self {
141            Self::Structure(_) => 4,
142            _ => 2,
143        }
144    }
145}
146
147impl<'de> Decode<'de> for TagType {
148    #[inline]
149    fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
150    where
151        D: Decoder<'de>,
152    {
153        decoder.ensure_size(3)?;
154        let type_code = decoder.decode_u16();
155        let val = match type_code {
156            0xC2 => TagType::Sint,
157            0xC3 => TagType::Int,
158            0xC4 => TagType::Dint,
159            0xCA => TagType::Real,
160            0xD3 => TagType::Dword,
161            0xC5 => TagType::Lint,
162            0xC1 => TagType::Bool,
163            0x02A0 => {
164                decoder.ensure_size(2)?;
165                TagType::Structure(decoder.decode_u16())
166            }
167            _ => {
168                return Err(Error::custom(format!(
169                    "unexpected type code: {}",
170                    type_code
171                )))
172            }
173        };
174        Ok(val)
175    }
176}
177
178#[derive(Debug, Clone, PartialEq, Eq)]
179pub struct TagValue<V> {
180    pub tag_type: TagType,
181    pub value: V,
182}
183
184macro_rules! impl_atomic {
185    ($ty:ty, $size: tt) => {
186        impl<'de> Decode<'de> for TagValue<$ty> {
187            #[inline]
188            fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
189            where
190                D: Decoder<'de>,
191            {
192                let tag_type = decoder.decode_any()?;
193                let value = decoder.decode_any()?;
194                Ok(Self { tag_type, value })
195            }
196        }
197
198        impl Encode for TagValue<$ty> {
199            #[inline]
200            fn encode<A: Encoder>(
201                self,
202                buf: &mut BytesMut,
203                encoder: &mut A,
204            ) -> Result<(), A::Error> {
205                self.tag_type.encode(buf, encoder)?;
206                buf.put_slice(&[1, 0]);
207                self.value.encode(buf, encoder)?;
208                Ok(())
209            }
210            #[inline]
211            fn encode_by_ref<A: Encoder>(
212                &self,
213                buf: &mut BytesMut,
214                encoder: &mut A,
215            ) -> Result<(), A::Error> {
216                self.tag_type.encode(buf, encoder)?;
217                buf.put_slice(&[1, 0]);
218                self.value.encode_by_ref(buf, encoder)?;
219                Ok(())
220            }
221
222            #[inline]
223            fn bytes_count(&self) -> usize {
224                self.tag_type.bytes_count() + 2 + $size
225            }
226        }
227    };
228}
229
230impl_atomic!(bool, 1);
231impl_atomic!(i8, 1);
232impl_atomic!(u8, 1);
233impl_atomic!(i16, 2);
234impl_atomic!(u16, 2);
235impl_atomic!(i32, 4);
236impl_atomic!(u32, 4);
237impl_atomic!(i64, 8);
238impl_atomic!(u64, 8);
239impl_atomic!(f32, 4);
240impl_atomic!(f64, 8);
241
242macro_rules! impl_seq {
243    ($ty:tt) => {
244        impl<T> Encode for TagValue<$ty<T>>
245        where
246            T: Encode,
247        {
248            #[inline]
249            fn encode<A: Encoder>(self, buf: &mut BytesMut, encoder: &mut A) -> Result<(), A::Error>
250            where
251                Self: Sized,
252            {
253                self.tag_type.encode(buf, encoder)?;
254                encoder.encode_u16(self.value.len() as u16, buf)?;
255                self.value.encode(buf, encoder)?;
256                Ok(())
257            }
258
259            #[inline]
260            fn encode_by_ref<A: Encoder>(
261                &self,
262                buf: &mut BytesMut,
263                encoder: &mut A,
264            ) -> Result<(), A::Error> {
265                self.tag_type.encode(buf, encoder)?;
266                encoder.encode_u16(self.value.len() as u16, buf)?;
267                self.value.encode_by_ref(buf, encoder)?;
268                Ok(())
269            }
270
271            #[inline]
272            fn bytes_count(&self) -> usize {
273                self.tag_type.bytes_count() + 2 + self.value.bytes_count()
274            }
275        }
276    };
277}
278
279impl_seq!(Vec);
280
281impl<T, const N: usize> Encode for TagValue<[T; N]>
282where
283    T: Encode,
284{
285    #[inline]
286    fn encode<A: Encoder>(self, buf: &mut BytesMut, encoder: &mut A) -> Result<(), A::Error>
287    where
288        Self: Sized,
289    {
290        self.tag_type.encode(buf, encoder)?;
291        encoder.encode_u16(self.value.len() as u16, buf)?;
292        self.value.encode(buf, encoder)?;
293        Ok(())
294    }
295
296    #[inline]
297    fn encode_by_ref<A: Encoder>(
298        &self,
299        buf: &mut BytesMut,
300        encoder: &mut A,
301    ) -> Result<(), A::Error> {
302        self.tag_type.encode(buf, encoder)?;
303        encoder.encode_u16(self.value.len() as u16, buf)?;
304        self.value.encode_by_ref(buf, encoder)?;
305        Ok(())
306    }
307
308    #[inline]
309    fn bytes_count(&self) -> usize {
310        self.tag_type.bytes_count() + 2 + self.value.bytes_count()
311    }
312}
313
314impl<T> Encode for TagValue<&[T]>
315where
316    T: Encode,
317{
318    #[inline]
319    fn encode_by_ref<A: Encoder>(
320        &self,
321        buf: &mut BytesMut,
322        encoder: &mut A,
323    ) -> Result<(), A::Error> {
324        self.tag_type.encode(buf, encoder)?;
325        encoder.encode_u16(self.value.len() as u16, buf)?;
326        for item in self.value.iter() {
327            item.encode_by_ref(buf, encoder)?;
328        }
329        Ok(())
330    }
331
332    #[inline]
333    fn bytes_count(&self) -> usize {
334        self.tag_type.bytes_count() + 2 + self.value.iter().map(|v| v.bytes_count()).sum::<usize>()
335    }
336}
337
338impl<'de> Decode<'de> for TagValue<Bytes> {
339    #[inline]
340    fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
341    where
342        D: Decoder<'de>,
343    {
344        let tag_type: TagType = decoder.decode_any()?;
345        let data: BytesHolder = decoder.decode_any()?;
346        Ok(Self {
347            tag_type,
348            value: data.into(),
349        })
350    }
351}
352
353impl<'de, T> Decode<'de> for TagValue<Vec<T>>
354where
355    T: Decode<'de>,
356{
357    #[inline]
358    fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
359    where
360        D: Decoder<'de>,
361    {
362        let tag_type: TagType = decoder.decode_any()?;
363        let mut data = Vec::new();
364        while decoder.buf().has_remaining() {
365            let v: T = decoder.decode_any()?;
366            data.push(v);
367        }
368        Ok(Self {
369            tag_type,
370            value: data,
371        })
372    }
373}
374
375impl<'de, T> Decode<'de> for TagValue<SmallVec<T>>
376where
377    T: smallvec::Array,
378    T::Item: Decode<'de>,
379{
380    #[inline]
381    fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
382    where
383        D: Decoder<'de>,
384    {
385        let tag_type: TagType = decoder.decode_any()?;
386        let mut data = SmallVec::new();
387        while decoder.buf().has_remaining() {
388            let v: T::Item = decoder.decode_any()?;
389            data.push(v);
390        }
391        Ok(Self {
392            tag_type,
393            value: data,
394        })
395    }
396}
397
398#[derive(Debug)]
399pub struct TagValueTypedIter<T> {
400    tag_type: TagType,
401    decoder: LittleEndianDecoder<ClientError>,
402    _marker: PhantomData<T>,
403}
404
405impl<T> TagValueTypedIter<T> {
406    #[allow(unused)]
407    pub fn tag_type(&self) -> TagType {
408        self.tag_type
409    }
410
411    pub fn from_bytes(buf: Bytes) -> Result<Self, ClientError> {
412        let mut decoder = LittleEndianDecoder::new(buf);
413        let tag_type = decoder.decode_any()?;
414        Ok(Self {
415            tag_type,
416            decoder,
417            _marker: Default::default(),
418        })
419    }
420}
421
422impl<'de, T> Iterator for TagValueTypedIter<T>
423where
424    T: Decode<'de>,
425{
426    type Item = Result<T, ClientError>;
427    #[inline]
428    fn next(&mut self) -> Option<Self::Item> {
429        if self.decoder.has_remaining() {
430            Some(self.decoder.decode_any())
431        } else {
432            None
433        }
434    }
435}
436
437impl<'de, T> Decode<'de> for TagValueTypedIter<T> {
438    #[inline]
439    fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
440    where
441        D: Decoder<'de>,
442    {
443        let tag_type: TagType = decoder.decode_any()?;
444        let len = decoder.buf_mut().remaining();
445        let buf = decoder.buf_mut().copy_to_bytes(len);
446        let res = Self {
447            tag_type,
448            decoder: LittleEndianDecoder::new(buf),
449            _marker: Default::default(),
450        };
451        Ok(res)
452    }
453}
454
455#[derive(Debug)]
456pub struct TagValueIter {
457    tag_type: TagType,
458    decoder: LittleEndianDecoder<ClientError>,
459}
460
461impl TagValueIter {
462    #[allow(unused)]
463    pub fn tag_type(&self) -> TagType {
464        self.tag_type
465    }
466
467    pub fn from_bytes(buf: Bytes) -> Result<Self, ClientError> {
468        let mut decoder = LittleEndianDecoder::new(buf);
469        let tag_type = decoder.decode_any()?;
470        Ok(Self { tag_type, decoder })
471    }
472}
473
474impl TagValueIter {
475    #[inline]
476    pub fn next<'de, T>(&mut self) -> Option<Result<T, ClientError>>
477    where
478        T: Decode<'de>,
479    {
480        if self.decoder.has_remaining() {
481            Some(self.decoder.decode_any())
482        } else {
483            None
484        }
485    }
486}
487
488impl<'de> Decode<'de> for TagValueIter {
489    #[inline]
490    fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
491    where
492        D: Decoder<'de>,
493    {
494        let tag_type: TagType = decoder.decode_any()?;
495        let len = decoder.buf_mut().remaining();
496        let buf = decoder.buf_mut().copy_to_bytes(len);
497        let res = Self {
498            tag_type,
499            decoder: LittleEndianDecoder::new(buf),
500        };
501        Ok(res)
502    }
503}