Skip to main content

matter_clusters/gen/
ota_software_update_requestor.rs

1//! OtaSoftwareUpdateRequestor cluster (0x002A).
2//! @generated by `cargo xtask codegen` — do not edit.
3
4#![allow(
5    clippy::all,
6    clippy::pedantic,
7    dead_code,
8    unreachable_pub,
9    unused_imports
10)]
11
12use crate::datatypes::SemanticTagStruct;
13use crate::error::ClusterError;
14use crate::types::Nullable;
15use matter_codec::{ContainerKind, Element, Tag, TlvReader, TlvWriter, Value};
16
17/// Cluster ID.
18pub const CLUSTER_ID: u32 = 0x002A;
19/// Cluster revision.
20pub const CLUSTER_REVISION: u16 = 1;
21
22/// Command IDs (requests and responses).
23pub mod command_id {
24    /// `AnnounceOtaProvider` (request).
25    pub const ANNOUNCE_OTA_PROVIDER: u32 = 0x00;
26}
27
28/// Attribute IDs (cluster-specific).
29pub mod attribute_id {
30    /// `DefaultOtaProviders`.
31    pub const DEFAULT_OTA_PROVIDERS: u32 = 0x0000;
32    /// `UpdatePossible`.
33    pub const UPDATE_POSSIBLE: u32 = 0x0001;
34    /// `UpdateState`.
35    pub const UPDATE_STATE: u32 = 0x0002;
36    /// `UpdateStateProgress`.
37    pub const UPDATE_STATE_PROGRESS: u32 = 0x0003;
38}
39
40/// `AnnouncementReasonEnum` (enum8).
41#[derive(Copy, Clone, Debug, PartialEq, Eq)]
42pub enum AnnouncementReasonEnum {
43    /// SimpleAnnouncement = 0.
44    SimpleAnnouncement,
45    /// UpdateAvailable = 1.
46    UpdateAvailable,
47    /// UrgentUpdateAvailable = 2.
48    UrgentUpdateAvailable,
49    /// A value not known to this codegen revision.
50    Unknown(u8),
51}
52
53impl AnnouncementReasonEnum {
54    /// Decode from its raw discriminant (unknown → `Unknown`).
55    #[must_use]
56    pub fn from_raw(v: u8) -> Self {
57        match v {
58            0 => Self::SimpleAnnouncement,
59            1 => Self::UpdateAvailable,
60            2 => Self::UrgentUpdateAvailable,
61            other => Self::Unknown(other),
62        }
63    }
64    /// The raw discriminant.
65    #[must_use]
66    pub fn to_raw(self) -> u8 {
67        match self {
68            Self::SimpleAnnouncement => 0,
69            Self::UpdateAvailable => 1,
70            Self::UrgentUpdateAvailable => 2,
71            Self::Unknown(v) => v,
72        }
73    }
74}
75
76/// `ChangeReasonEnum` (enum8).
77#[derive(Copy, Clone, Debug, PartialEq, Eq)]
78pub enum ChangeReasonEnum {
79    /// Unknown = 0.
80    Unknown,
81    /// Success = 1.
82    Success,
83    /// Failure = 2.
84    Failure,
85    /// TimeOut = 3.
86    TimeOut,
87    /// DelayByProvider = 4.
88    DelayByProvider,
89    /// A value not known to this codegen revision.
90    Unrecognized(u8),
91}
92
93impl ChangeReasonEnum {
94    /// Decode from its raw discriminant (unknown → `Unrecognized`).
95    #[must_use]
96    pub fn from_raw(v: u8) -> Self {
97        match v {
98            0 => Self::Unknown,
99            1 => Self::Success,
100            2 => Self::Failure,
101            3 => Self::TimeOut,
102            4 => Self::DelayByProvider,
103            other => Self::Unrecognized(other),
104        }
105    }
106    /// The raw discriminant.
107    #[must_use]
108    pub fn to_raw(self) -> u8 {
109        match self {
110            Self::Unknown => 0,
111            Self::Success => 1,
112            Self::Failure => 2,
113            Self::TimeOut => 3,
114            Self::DelayByProvider => 4,
115            Self::Unrecognized(v) => v,
116        }
117    }
118}
119
120/// `ProviderLocation` struct.
121#[derive(Clone, Debug, PartialEq)]
122#[non_exhaustive]
123pub struct ProviderLocation {
124    /// Field ProviderNodeId (tag 1).
125    pub provider_node_id: u64,
126    /// Field Endpoint (tag 2).
127    pub endpoint: u16,
128    /// Field FabricIndex (tag 254).
129    pub fabric_index: u8,
130}
131
132/// `UpdateStateEnum` (enum8).
133#[derive(Copy, Clone, Debug, PartialEq, Eq)]
134pub enum UpdateStateEnum {
135    /// Unknown = 0.
136    Unknown,
137    /// Idle = 1.
138    Idle,
139    /// Querying = 2.
140    Querying,
141    /// DelayedOnQuery = 3.
142    DelayedOnQuery,
143    /// Downloading = 4.
144    Downloading,
145    /// Applying = 5.
146    Applying,
147    /// DelayedOnApply = 6.
148    DelayedOnApply,
149    /// RollingBack = 7.
150    RollingBack,
151    /// DelayedOnUserConsent = 8.
152    DelayedOnUserConsent,
153    /// A value not known to this codegen revision.
154    Unrecognized(u8),
155}
156
157impl UpdateStateEnum {
158    /// Decode from its raw discriminant (unknown → `Unrecognized`).
159    #[must_use]
160    pub fn from_raw(v: u8) -> Self {
161        match v {
162            0 => Self::Unknown,
163            1 => Self::Idle,
164            2 => Self::Querying,
165            3 => Self::DelayedOnQuery,
166            4 => Self::Downloading,
167            5 => Self::Applying,
168            6 => Self::DelayedOnApply,
169            7 => Self::RollingBack,
170            8 => Self::DelayedOnUserConsent,
171            other => Self::Unrecognized(other),
172        }
173    }
174    /// The raw discriminant.
175    #[must_use]
176    pub fn to_raw(self) -> u8 {
177        match self {
178            Self::Unknown => 0,
179            Self::Idle => 1,
180            Self::Querying => 2,
181            Self::DelayedOnQuery => 3,
182            Self::Downloading => 4,
183            Self::Applying => 5,
184            Self::DelayedOnApply => 6,
185            Self::RollingBack => 7,
186            Self::DelayedOnUserConsent => 8,
187            Self::Unrecognized(v) => v,
188        }
189    }
190}
191
192impl ProviderLocation {
193    /// Decode the fields of an already-opened anonymous structure
194    /// (reader positioned after the struct start; consumes to its end).
195    ///
196    /// # Errors
197    /// Returns [`ClusterError`] on a malformed structure or missing required field.
198    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
199        let mut f_provider_node_id: Option<u64> = None;
200        let mut f_endpoint: Option<u16> = None;
201        let mut f_fabric_index: Option<u8> = None;
202        loop {
203            match r.next()? {
204                Some(Element::ContainerEnd) => break,
205                Some(Element::Scalar {
206                    tag: Tag::Context(1),
207                    value: Value::Uint(v),
208                }) => {
209                    f_provider_node_id = Some(
210                        u64::try_from(v)
211                            .map_err(|_| ClusterError::InvalidLength("ProviderNodeId"))?,
212                    )
213                }
214                Some(Element::Scalar {
215                    tag: Tag::Context(2),
216                    value: Value::Uint(v),
217                }) => {
218                    f_endpoint = Some(
219                        u16::try_from(v).map_err(|_| ClusterError::InvalidLength("Endpoint"))?,
220                    )
221                }
222                Some(Element::Scalar {
223                    tag: Tag::Context(254),
224                    value: Value::Uint(v),
225                }) => {
226                    f_fabric_index = Some(
227                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
228                    )
229                }
230                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
231                Some(Element::ContainerStart { .. }) => r.skip_container()?,
232                Some(_) => {} // unknown/future scalar — skip
233            }
234        }
235        Ok(Self {
236            provider_node_id: f_provider_node_id
237                .ok_or(ClusterError::MissingField("ProviderNodeId"))?,
238            endpoint: f_endpoint.ok_or(ClusterError::MissingField("Endpoint"))?,
239            fabric_index: f_fabric_index.ok_or(ClusterError::MissingField("FabricIndex"))?,
240        })
241    }
242    /// Decode from a standalone anonymous TLV structure.
243    ///
244    /// # Errors
245    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
246    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
247        let mut r = TlvReader::new(tlv);
248        match r.next()? {
249            Some(Element::ContainerStart {
250                kind: ContainerKind::Structure,
251                ..
252            }) => {}
253            _ => {
254                return Err(ClusterError::UnexpectedType {
255                    context: "ProviderLocation",
256                })
257            }
258        }
259        Self::decode_from(&mut r)
260    }
261    /// Write this struct's fields into an already-open container.
262    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
263    pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
264        w.put_uint(Tag::Context(1), u64::from(self.provider_node_id))
265            .expect("infallible: vec writer");
266        w.put_uint(Tag::Context(2), u64::from(self.endpoint))
267            .expect("infallible: vec writer");
268        w.put_uint(Tag::Context(254), u64::from(self.fabric_index))
269            .expect("infallible: vec writer");
270    }
271    /// Encode as a standalone anonymous TLV structure.
272    #[must_use]
273    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
274    pub fn encode(&self) -> Vec<u8> {
275        let mut buf = Vec::new();
276        let mut w = TlvWriter::new(&mut buf);
277        w.start_structure(Tag::Anonymous)
278            .expect("infallible: vec writer");
279        self.write_fields(&mut w);
280        w.end_container().expect("infallible: vec writer");
281        buf
282    }
283}
284
285/// Decode the `DefaultOtaProviders` attribute value.
286///
287/// # Errors
288/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
289pub fn decode_default_ota_providers(tlv: &[u8]) -> Result<Vec<ProviderLocation>, ClusterError> {
290    let mut r = TlvReader::new(tlv);
291    match r.next()? {
292        Some(Element::ContainerStart {
293            kind: ContainerKind::Array,
294            ..
295        }) => {}
296        _ => {
297            return Err(ClusterError::UnexpectedType {
298                context: "DefaultOtaProviders",
299            })
300        }
301    }
302    let r = &mut r;
303    let mut out = Vec::new();
304    loop {
305        match r.next()? {
306            Some(Element::ContainerEnd) => break,
307            Some(Element::ContainerStart {
308                kind: ContainerKind::Structure,
309                ..
310            }) => {
311                out.push(ProviderLocation::decode_from(r)?);
312            }
313            None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
314            Some(Element::ContainerStart { .. }) => r.skip_container()?,
315            Some(_) => {} // skip unknown scalar
316        }
317    }
318    Ok(out)
319}
320
321/// Decode the `UpdatePossible` attribute value.
322///
323/// # Errors
324/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
325pub fn decode_update_possible(tlv: &[u8]) -> Result<bool, ClusterError> {
326    let mut r = TlvReader::new(tlv);
327    match r.next()? {
328        Some(Element::Scalar {
329            value: Value::Bool(v),
330            ..
331        }) => Ok(v),
332        _ => Err(ClusterError::UnexpectedType {
333            context: "UpdatePossible",
334        }),
335    }
336}
337
338/// Decode the `UpdateState` attribute value.
339///
340/// # Errors
341/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
342pub fn decode_update_state(tlv: &[u8]) -> Result<UpdateStateEnum, ClusterError> {
343    let mut r = TlvReader::new(tlv);
344    match r.next()? {
345        Some(Element::Scalar {
346            value: Value::Uint(v),
347            ..
348        }) => Ok(UpdateStateEnum::from_raw(
349            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("UpdateState"))?,
350        )),
351        _ => Err(ClusterError::UnexpectedType {
352            context: "UpdateState",
353        }),
354    }
355}
356
357/// Decode the `UpdateStateProgress` attribute value.
358///
359/// # Errors
360/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
361pub fn decode_update_state_progress(tlv: &[u8]) -> Result<Nullable<u8>, ClusterError> {
362    let mut r = TlvReader::new(tlv);
363    match r.next()? {
364        Some(Element::Scalar {
365            value: Value::Null, ..
366        }) => Ok(Nullable::Null),
367        Some(Element::Scalar {
368            value: Value::Uint(v),
369            ..
370        }) => Ok(Nullable::Value(u8::try_from(v).map_err(|_| {
371            ClusterError::InvalidLength("UpdateStateProgress")
372        })?)),
373        _ => Err(ClusterError::UnexpectedType {
374            context: "UpdateStateProgress",
375        }),
376    }
377}
378
379/// Encode the `AnnounceOtaProvider` command request payload.
380#[must_use]
381#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
382pub fn encode_announce_ota_provider(
383    provider_node_id: u64,
384    vendor_id: u16,
385    announcement_reason: AnnouncementReasonEnum,
386    metadata_for_node: Option<Vec<u8>>,
387    endpoint: u16,
388) -> Vec<u8> {
389    let mut buf = Vec::new();
390    let mut w = TlvWriter::new(&mut buf);
391    w.start_structure(Tag::Anonymous)
392        .expect("infallible: vec writer");
393    w.put_uint(Tag::Context(0), u64::from(provider_node_id))
394        .expect("infallible: vec writer");
395    w.put_uint(Tag::Context(1), u64::from(vendor_id))
396        .expect("infallible: vec writer");
397    w.put_uint(Tag::Context(2), u64::from(announcement_reason.to_raw()))
398        .expect("infallible: vec writer");
399    if let Some(metadata_for_node) = metadata_for_node {
400        w.put_bytes(Tag::Context(3), &metadata_for_node)
401            .expect("infallible: vec writer");
402    }
403    w.put_uint(Tag::Context(4), u64::from(endpoint))
404        .expect("infallible: vec writer");
405    w.end_container().expect("infallible: vec writer");
406    buf
407}