Skip to main content

fennec_modbus/protocol/function/
write_multiple.rs

1//! Codecs for functions that write multiple coils or registers.
2
3use core::marker::PhantomData;
4
5use bytes::{Buf, BufMut};
6
7use crate::{
8    Error,
9    protocol::{
10        Address,
11        codec::{BitSize, Decode, Encode},
12        function::{IntoValue, size_argument},
13    },
14};
15
16/// Address range and values for writing operations.
17///
18/// # Example
19///
20/// ```rust
21/// use fennec_modbus::protocol::{codec::Encode, function::write_multiple::Args};
22///
23/// assert_eq!(
24///     Args::new(1_u16, [0x000A_u16, 0x0102]).to_bytes(),
25///     [
26///         0x00, 0x01, // starting address
27///         0x00, 0x02, // register count
28///         0x04, // byte count
29///         0x00, 0x0A, // register 1
30///         0x01, 0x02, // register 2
31///     ]
32/// );
33/// ```
34pub struct Args<A, V, S>(
35    /// Bare starting address.
36    A,
37    /// Value to write.
38    V,
39    /// Binding to the size type, normally [`size_argument::Bits`] or [`size_argument::Words`].
40    PhantomData<S>,
41);
42
43impl<A, V, S> Args<A, V, S> {
44    pub const fn new(address: A, value: V) -> Self {
45        Self(address, value, PhantomData)
46    }
47}
48
49impl<A: Address, V: BitSize + Encode> Encode for Args<A, V, size_argument::Words> {
50    fn encode(&self, to: &mut impl BufMut) {
51        V::assert_valid::<246>();
52        self.0.encode(to);
53        to.put_u16(V::N_WORDS);
54        to.put_u8(V::N_BYTES);
55        self.1.encode(to);
56    }
57}
58
59/// Writing output.
60///
61/// # Example
62///
63/// ```rust
64/// use fennec_modbus::protocol::{codec::Decode, function::write_multiple::Output};
65///
66/// let mut bytes: &[u8] = &[0x00, 0x01, 0x00, 0x02];
67/// let output = Output::decode(&mut bytes).unwrap();
68/// assert_eq!(output.starting_address, 1);
69/// assert_eq!(output.count, 2);
70/// ```
71pub struct Output {
72    /// Starting address.
73    pub starting_address: u16,
74
75    /// Count of registers or coils – according to the operation.
76    pub count: u16,
77}
78
79impl IntoValue for Output {
80    type Value = Self;
81
82    fn into_value(self) -> Self::Value {
83        self
84    }
85}
86
87impl Decode for Output {
88    fn decode(from: &mut impl Buf) -> Result<Self, Error> {
89        Ok(Self { starting_address: u16::decode(from)?, count: u16::decode(from)? })
90    }
91}