Skip to main content

sunspec/models/
model7.rs

1//! Secure Write Response Model (DRAFT 1)
2/// Secure Write Response Model (DRAFT 1)
3///
4/// Include a digital signature over the response
5///
6/// Detail: Used in conjunction with a Secure Write Request
7#[derive(Debug)]
8#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
9pub struct Model7 {
10    /// Request Sequence
11    ///
12    /// Sequence number from the request
13    pub rq_seq: u16,
14    /// Status
15    ///
16    /// Status of last write operation
17    pub sts: Sts,
18    /// Timestamp
19    ///
20    /// Timestamp value is the number of seconds since January 1, 2000
21    pub ts: u32,
22    /// Milliseconds
23    ///
24    /// Millisecond counter 0-999
25    pub ms: u16,
26    /// Sequence
27    ///
28    /// Sequence number of response
29    ///
30    /// Detail: Shall be advanced for each response
31    pub seq: u16,
32    /// Alarm
33    ///
34    /// Bitmask alarm code
35    pub alm: Alm,
36    /// Algorithm
37    ///
38    /// Algorithm used to compute the digital signature
39    ///
40    /// Detail: For future proof
41    pub alg: Alg,
42    /// N
43    ///
44    /// Number of registers comprising the digital signature.
45    ///
46    /// Detail: The value of N must be at least 4 (64 bits)
47    pub n: u16,
48    #[allow(missing_docs)]
49    pub repeating: Vec<Repeating>,
50}
51#[allow(missing_docs)]
52impl Model7 {
53    pub const RQ_SEQ: crate::Point<Self, u16> = crate::Point::new(0, 1, false);
54    pub const STS: crate::Point<Self, Sts> = crate::Point::new(1, 1, false);
55    pub const TS: crate::Point<Self, u32> = crate::Point::new(2, 2, false);
56    pub const MS: crate::Point<Self, u16> = crate::Point::new(4, 1, false);
57    pub const SEQ: crate::Point<Self, u16> = crate::Point::new(5, 1, false);
58    pub const ALM: crate::Point<Self, Alm> = crate::Point::new(6, 1, false);
59    pub const ALG: crate::Point<Self, Alg> = crate::Point::new(8, 1, false);
60    pub const N: crate::Point<Self, u16> = crate::Point::new(9, 1, true);
61}
62impl crate::Group for Model7 {
63    const LEN: u16 = 10;
64}
65impl Model7 {
66    fn parse_group(data: &[u16]) -> Result<(&[u16], Self), crate::DecodeError> {
67        let nested_data = data
68            .get(usize::from(<Self as crate::Group>::LEN)..)
69            .unwrap_or(&[]);
70        let (nested_data, repeating) = Repeating::parse_multiple(nested_data)?;
71        Ok((
72            nested_data,
73            Self {
74                rq_seq: Self::RQ_SEQ.from_data(data)?,
75                sts: Self::STS.from_data(data)?,
76                ts: Self::TS.from_data(data)?,
77                ms: Self::MS.from_data(data)?,
78                seq: Self::SEQ.from_data(data)?,
79                alm: Self::ALM.from_data(data)?,
80                alg: Self::ALG.from_data(data)?,
81                n: Self::N.from_data(data)?,
82                repeating,
83            },
84        ))
85    }
86}
87/// Status
88///
89/// Status of last write operation
90#[derive(Copy, Clone, Debug, Eq, PartialEq)]
91#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
92pub enum Sts {
93    #[allow(missing_docs)]
94    Success,
95    /// Detail: The signature was not valid
96    Ds,
97    /// Detail: One or more registers were not writable by this role
98    Acl,
99    /// Detail: Offset out of range or missing from multi-register value
100    Off,
101    /// Detail: Value is out of acceptable range
102    Val,
103    /// Raw enum value not defined by the SunSpec model.
104    Invalid(u16),
105}
106impl crate::EnumValue for Sts {
107    type Repr = u16;
108    const INVALID: Self::Repr = 65535;
109    fn from_repr(value: Self::Repr) -> Self {
110        match value {
111            0 => Self::Success,
112            1 => Self::Ds,
113            2 => Self::Acl,
114            3 => Self::Off,
115            4 => Self::Val,
116            value => Self::Invalid(value),
117        }
118    }
119    fn to_repr(self) -> Self::Repr {
120        match self {
121            Self::Success => 0,
122            Self::Ds => 1,
123            Self::Acl => 2,
124            Self::Off => 3,
125            Self::Val => 4,
126            Self::Invalid(value) => value,
127        }
128    }
129}
130impl crate::FixedSize for Sts {
131    const SIZE: u16 = 1u16;
132    const INVALID: Self = Self::Invalid(65535);
133    fn is_invalid(&self) -> bool {
134        matches!(self, Self::Invalid(_))
135    }
136}
137/// Alarm
138///
139/// Bitmask alarm code
140#[derive(Copy, Clone, Debug, Eq, PartialEq)]
141#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
142pub enum Alm {
143    #[allow(missing_docs)]
144    None,
145    /// Detail: Tampered
146    Alm,
147    /// Raw enum value not defined by the SunSpec model.
148    Invalid(u16),
149}
150impl crate::EnumValue for Alm {
151    type Repr = u16;
152    const INVALID: Self::Repr = 65535;
153    fn from_repr(value: Self::Repr) -> Self {
154        match value {
155            0 => Self::None,
156            1 => Self::Alm,
157            value => Self::Invalid(value),
158        }
159    }
160    fn to_repr(self) -> Self::Repr {
161        match self {
162            Self::None => 0,
163            Self::Alm => 1,
164            Self::Invalid(value) => value,
165        }
166    }
167}
168impl crate::FixedSize for Alm {
169    const SIZE: u16 = 1u16;
170    const INVALID: Self = Self::Invalid(65535);
171    fn is_invalid(&self) -> bool {
172        matches!(self, Self::Invalid(_))
173    }
174}
175/// Algorithm
176///
177/// Algorithm used to compute the digital signature
178///
179/// Detail: For future proof
180#[derive(Copy, Clone, Debug, Eq, PartialEq)]
181#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
182pub enum Alg {
183    /// Detail: For test purposes only
184    None,
185    #[allow(missing_docs)]
186    AesGmac64,
187    #[allow(missing_docs)]
188    Ecc256,
189    /// Raw enum value not defined by the SunSpec model.
190    Invalid(u16),
191}
192impl crate::EnumValue for Alg {
193    type Repr = u16;
194    const INVALID: Self::Repr = 65535;
195    fn from_repr(value: Self::Repr) -> Self {
196        match value {
197            0 => Self::None,
198            1 => Self::AesGmac64,
199            2 => Self::Ecc256,
200            value => Self::Invalid(value),
201        }
202    }
203    fn to_repr(self) -> Self::Repr {
204        match self {
205            Self::None => 0,
206            Self::AesGmac64 => 1,
207            Self::Ecc256 => 2,
208            Self::Invalid(value) => value,
209        }
210    }
211}
212impl crate::FixedSize for Alg {
213    const SIZE: u16 = 1u16;
214    const INVALID: Self = Self::Invalid(65535);
215    fn is_invalid(&self) -> bool {
216        matches!(self, Self::Invalid(_))
217    }
218}
219#[allow(missing_docs)]
220#[derive(Debug)]
221#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
222pub struct Repeating {
223    /// DS
224    ///
225    /// Digital Signature
226    pub ds: u16,
227}
228#[allow(missing_docs)]
229impl Repeating {
230    pub const DS: crate::Point<Self, u16> = crate::Point::new(0, 1, true);
231}
232impl crate::Group for Repeating {
233    const LEN: u16 = 1;
234}
235impl Repeating {
236    fn parse_group(data: &[u16]) -> Result<(&[u16], Self), crate::DecodeError> {
237        let nested_data = data
238            .get(usize::from(<Self as crate::Group>::LEN)..)
239            .unwrap_or(&[]);
240        Ok((
241            nested_data,
242            Self {
243                ds: Self::DS.from_data(data)?,
244            },
245        ))
246    }
247    fn parse_multiple(data: &[u16]) -> Result<(&[u16], Vec<Self>), crate::DecodeError> {
248        let group_len = usize::from(<Repeating as crate::Group>::LEN);
249        if group_len == 0 {
250            return Ok((data, Vec::new()));
251        }
252        if data.len() % group_len != 0 {
253            return Err(crate::DecodeError::OutOfBounds);
254        }
255        let group_count = data.len() / group_len;
256        let (data, groups) =
257            (0..group_count).try_fold((data, Vec::new()), |(data, mut groups), _| {
258                let (data, group) = Repeating::parse_group(data)?;
259                groups.push(group);
260                Ok::<_, crate::DecodeError>((data, groups))
261            })?;
262        Ok((data, groups))
263    }
264}
265impl crate::Model for Model7 {
266    const ID: u16 = 7;
267    fn addr(models: &crate::Models) -> crate::ModelAddr<Self> {
268        models.m7
269    }
270    fn parse(data: &[u16]) -> Result<Self, crate::ParseError<Self>> {
271        let (_, model) = Self::parse_group(data)?;
272        Ok(model)
273    }
274}