Skip to main content

matter_clusters/gen/
icd_management.rs

1//! IcdManagement cluster (0x0046).
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 = 0x0046;
19/// Cluster revision.
20pub const CLUSTER_REVISION: u16 = 3;
21
22/// Command IDs (requests and responses).
23pub mod command_id {
24    /// `RegisterClient` (request).
25    pub const REGISTER_CLIENT: u32 = 0x00;
26    /// `RegisterClientResponse` (response).
27    pub const REGISTER_CLIENT_RESPONSE: u32 = 0x01;
28    /// `UnregisterClient` (request).
29    pub const UNREGISTER_CLIENT: u32 = 0x02;
30    /// `StayActiveRequest` (request).
31    pub const STAY_ACTIVE_REQUEST: u32 = 0x03;
32    /// `StayActiveResponse` (response).
33    pub const STAY_ACTIVE_RESPONSE: u32 = 0x04;
34}
35
36/// Attribute IDs (cluster-specific).
37pub mod attribute_id {
38    /// `IdleModeDuration`.
39    pub const IDLE_MODE_DURATION: u32 = 0x0000;
40    /// `ActiveModeDuration`.
41    pub const ACTIVE_MODE_DURATION: u32 = 0x0001;
42    /// `ActiveModeThreshold`.
43    pub const ACTIVE_MODE_THRESHOLD: u32 = 0x0002;
44    /// `RegisteredClients`.
45    pub const REGISTERED_CLIENTS: u32 = 0x0003;
46    /// `IcdCounter`.
47    pub const ICD_COUNTER: u32 = 0x0004;
48    /// `ClientsSupportedPerFabric`.
49    pub const CLIENTS_SUPPORTED_PER_FABRIC: u32 = 0x0005;
50    /// `UserActiveModeTriggerHint`.
51    pub const USER_ACTIVE_MODE_TRIGGER_HINT: u32 = 0x0006;
52    /// `UserActiveModeTriggerInstruction`.
53    pub const USER_ACTIVE_MODE_TRIGGER_INSTRUCTION: u32 = 0x0007;
54    /// `OperatingMode`.
55    pub const OPERATING_MODE: u32 = 0x0008;
56    /// `MaximumCheckInBackoff`.
57    pub const MAXIMUM_CHECK_IN_BACKOFF: u32 = 0x0009;
58}
59
60bitflags::bitflags! {
61    /// `IcdManagement` feature bits (FeatureMap).
62    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
63    pub struct Feature: u32 {
64        /// CheckInProtocolSupport (CIP).
65        const CIP = 1 << 0;
66        /// UserActiveModeTrigger (UAT).
67        const UAT = 1 << 1;
68        /// LongIdleTimeSupport (LITS).
69        const LITS = 1 << 2;
70        /// DynamicSitLitSupport (DSLS).
71        const DSLS = 1 << 3;
72    }
73}
74
75/// `ClientTypeEnum` (enum8).
76#[derive(Copy, Clone, Debug, PartialEq, Eq)]
77pub enum ClientTypeEnum {
78    /// Permanent = 0.
79    Permanent,
80    /// Ephemeral = 1.
81    Ephemeral,
82    /// A value not known to this codegen revision.
83    Unknown(u8),
84}
85
86impl ClientTypeEnum {
87    /// Decode from its raw discriminant (unknown → `Unknown`).
88    #[must_use]
89    pub fn from_raw(v: u8) -> Self {
90        match v {
91            0 => Self::Permanent,
92            1 => Self::Ephemeral,
93            other => Self::Unknown(other),
94        }
95    }
96    /// The raw discriminant.
97    #[must_use]
98    pub fn to_raw(self) -> u8 {
99        match self {
100            Self::Permanent => 0,
101            Self::Ephemeral => 1,
102            Self::Unknown(v) => v,
103        }
104    }
105}
106
107/// `MonitoringRegistrationStruct` struct.
108#[derive(Clone, Debug, PartialEq)]
109#[non_exhaustive]
110pub struct MonitoringRegistrationStruct {
111    /// Field CheckInNodeId (tag 1).
112    pub check_in_node_id: u64,
113    /// Field MonitoredSubject (tag 2).
114    pub monitored_subject: u64,
115    /// Field ClientType (tag 4).
116    pub client_type: ClientTypeEnum,
117    /// Field FabricIndex (tag 254).
118    pub fabric_index: u8,
119}
120
121/// `OperatingModeEnum` (enum8).
122#[derive(Copy, Clone, Debug, PartialEq, Eq)]
123pub enum OperatingModeEnum {
124    /// Sit = 0.
125    Sit,
126    /// Lit = 1.
127    Lit,
128    /// A value not known to this codegen revision.
129    Unknown(u8),
130}
131
132impl OperatingModeEnum {
133    /// Decode from its raw discriminant (unknown → `Unknown`).
134    #[must_use]
135    pub fn from_raw(v: u8) -> Self {
136        match v {
137            0 => Self::Sit,
138            1 => Self::Lit,
139            other => Self::Unknown(other),
140        }
141    }
142    /// The raw discriminant.
143    #[must_use]
144    pub fn to_raw(self) -> u8 {
145        match self {
146            Self::Sit => 0,
147            Self::Lit => 1,
148            Self::Unknown(v) => v,
149        }
150    }
151}
152
153bitflags::bitflags! {
154    /// `UserActiveModeTriggerBitmap` (map32).
155    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
156    pub struct UserActiveModeTriggerBitmap: u32 {
157        /// PowerCycle.
158        const POWER_CYCLE = 1 << 0;
159        /// SettingsMenu.
160        const SETTINGS_MENU = 1 << 1;
161        /// CustomInstruction.
162        const CUSTOM_INSTRUCTION = 1 << 2;
163        /// DeviceManual.
164        const DEVICE_MANUAL = 1 << 3;
165        /// ActuateSensor.
166        const ACTUATE_SENSOR = 1 << 4;
167        /// ActuateSensorSeconds.
168        const ACTUATE_SENSOR_SECONDS = 1 << 5;
169        /// ActuateSensorTimes.
170        const ACTUATE_SENSOR_TIMES = 1 << 6;
171        /// ActuateSensorLightsBlink.
172        const ACTUATE_SENSOR_LIGHTS_BLINK = 1 << 7;
173        /// ResetButton.
174        const RESET_BUTTON = 1 << 8;
175        /// ResetButtonLightsBlink.
176        const RESET_BUTTON_LIGHTS_BLINK = 1 << 9;
177        /// ResetButtonSeconds.
178        const RESET_BUTTON_SECONDS = 1 << 10;
179        /// ResetButtonTimes.
180        const RESET_BUTTON_TIMES = 1 << 11;
181        /// SetupButton.
182        const SETUP_BUTTON = 1 << 12;
183        /// SetupButtonSeconds.
184        const SETUP_BUTTON_SECONDS = 1 << 13;
185        /// SetupButtonLightsBlink.
186        const SETUP_BUTTON_LIGHTS_BLINK = 1 << 14;
187        /// SetupButtonTimes.
188        const SETUP_BUTTON_TIMES = 1 << 15;
189        /// AppDefinedButton.
190        const APP_DEFINED_BUTTON = 1 << 16;
191    }
192}
193
194impl MonitoringRegistrationStruct {
195    /// Decode the fields of an already-opened anonymous structure
196    /// (reader positioned after the struct start; consumes to its end).
197    ///
198    /// # Errors
199    /// Returns [`ClusterError`] on a malformed structure or missing required field.
200    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
201        let mut f_check_in_node_id: Option<u64> = None;
202        let mut f_monitored_subject: Option<u64> = None;
203        let mut f_client_type: Option<ClientTypeEnum> = None;
204        let mut f_fabric_index: Option<u8> = None;
205        loop {
206            match r.next()? {
207                Some(Element::ContainerEnd) => break,
208                Some(Element::Scalar {
209                    tag: Tag::Context(1),
210                    value: Value::Uint(v),
211                }) => {
212                    f_check_in_node_id = Some(
213                        u64::try_from(v)
214                            .map_err(|_| ClusterError::InvalidLength("CheckInNodeId"))?,
215                    )
216                }
217                Some(Element::Scalar {
218                    tag: Tag::Context(2),
219                    value: Value::Uint(v),
220                }) => {
221                    f_monitored_subject = Some(
222                        u64::try_from(v)
223                            .map_err(|_| ClusterError::InvalidLength("MonitoredSubject"))?,
224                    )
225                }
226                Some(Element::Scalar {
227                    tag: Tag::Context(4),
228                    value: Value::Uint(v),
229                }) => {
230                    f_client_type = Some(ClientTypeEnum::from_raw(
231                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("ClientType"))?,
232                    ))
233                }
234                Some(Element::Scalar {
235                    tag: Tag::Context(254),
236                    value: Value::Uint(v),
237                }) => {
238                    f_fabric_index = Some(
239                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
240                    )
241                }
242                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
243                Some(Element::ContainerStart { .. }) => r.skip_container()?,
244                Some(_) => {} // unknown/future scalar — skip
245            }
246        }
247        Ok(Self {
248            check_in_node_id: f_check_in_node_id
249                .ok_or(ClusterError::MissingField("CheckInNodeId"))?,
250            monitored_subject: f_monitored_subject
251                .ok_or(ClusterError::MissingField("MonitoredSubject"))?,
252            client_type: f_client_type.ok_or(ClusterError::MissingField("ClientType"))?,
253            fabric_index: f_fabric_index.ok_or(ClusterError::MissingField("FabricIndex"))?,
254        })
255    }
256    /// Decode from a standalone anonymous TLV structure.
257    ///
258    /// # Errors
259    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
260    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
261        let mut r = TlvReader::new(tlv);
262        match r.next()? {
263            Some(Element::ContainerStart {
264                kind: ContainerKind::Structure,
265                ..
266            }) => {}
267            _ => {
268                return Err(ClusterError::UnexpectedType {
269                    context: "MonitoringRegistrationStruct",
270                })
271            }
272        }
273        Self::decode_from(&mut r)
274    }
275    /// Write this struct's fields into an already-open container.
276    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
277    pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
278        w.put_uint(Tag::Context(1), u64::from(self.check_in_node_id))
279            .expect("infallible: vec writer");
280        w.put_uint(Tag::Context(2), u64::from(self.monitored_subject))
281            .expect("infallible: vec writer");
282        w.put_uint(Tag::Context(4), u64::from(self.client_type.to_raw()))
283            .expect("infallible: vec writer");
284        w.put_uint(Tag::Context(254), u64::from(self.fabric_index))
285            .expect("infallible: vec writer");
286    }
287    /// Encode as a standalone anonymous TLV structure.
288    #[must_use]
289    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
290    pub fn encode(&self) -> Vec<u8> {
291        let mut buf = Vec::new();
292        let mut w = TlvWriter::new(&mut buf);
293        w.start_structure(Tag::Anonymous)
294            .expect("infallible: vec writer");
295        self.write_fields(&mut w);
296        w.end_container().expect("infallible: vec writer");
297        buf
298    }
299}
300
301/// Decode the `IdleModeDuration` attribute value.
302///
303/// # Errors
304/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
305pub fn decode_idle_mode_duration(tlv: &[u8]) -> Result<u32, ClusterError> {
306    let mut r = TlvReader::new(tlv);
307    match r.next()? {
308        Some(Element::Scalar {
309            value: Value::Uint(v),
310            ..
311        }) => Ok(u32::try_from(v).map_err(|_| ClusterError::InvalidLength("IdleModeDuration"))?),
312        _ => Err(ClusterError::UnexpectedType {
313            context: "IdleModeDuration",
314        }),
315    }
316}
317
318/// Decode the `ActiveModeDuration` attribute value.
319///
320/// # Errors
321/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
322pub fn decode_active_mode_duration(tlv: &[u8]) -> Result<u32, ClusterError> {
323    let mut r = TlvReader::new(tlv);
324    match r.next()? {
325        Some(Element::Scalar {
326            value: Value::Uint(v),
327            ..
328        }) => Ok(u32::try_from(v).map_err(|_| ClusterError::InvalidLength("ActiveModeDuration"))?),
329        _ => Err(ClusterError::UnexpectedType {
330            context: "ActiveModeDuration",
331        }),
332    }
333}
334
335/// Decode the `ActiveModeThreshold` attribute value.
336///
337/// # Errors
338/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
339pub fn decode_active_mode_threshold(tlv: &[u8]) -> Result<u16, ClusterError> {
340    let mut r = TlvReader::new(tlv);
341    match r.next()? {
342        Some(Element::Scalar {
343            value: Value::Uint(v),
344            ..
345        }) => Ok(u16::try_from(v).map_err(|_| ClusterError::InvalidLength("ActiveModeThreshold"))?),
346        _ => Err(ClusterError::UnexpectedType {
347            context: "ActiveModeThreshold",
348        }),
349    }
350}
351
352/// Decode the `RegisteredClients` attribute value.
353///
354/// # Errors
355/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
356pub fn decode_registered_clients(
357    tlv: &[u8],
358) -> Result<Vec<MonitoringRegistrationStruct>, ClusterError> {
359    let mut r = TlvReader::new(tlv);
360    match r.next()? {
361        Some(Element::ContainerStart {
362            kind: ContainerKind::Array,
363            ..
364        }) => {}
365        _ => {
366            return Err(ClusterError::UnexpectedType {
367                context: "RegisteredClients",
368            })
369        }
370    }
371    let r = &mut r;
372    let mut out = Vec::new();
373    loop {
374        match r.next()? {
375            Some(Element::ContainerEnd) => break,
376            Some(Element::ContainerStart {
377                kind: ContainerKind::Structure,
378                ..
379            }) => {
380                out.push(MonitoringRegistrationStruct::decode_from(r)?);
381            }
382            None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
383            Some(Element::ContainerStart { .. }) => r.skip_container()?,
384            Some(_) => {} // skip unknown scalar
385        }
386    }
387    Ok(out)
388}
389
390/// Decode the `IcdCounter` attribute value.
391///
392/// # Errors
393/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
394pub fn decode_icd_counter(tlv: &[u8]) -> Result<u32, ClusterError> {
395    let mut r = TlvReader::new(tlv);
396    match r.next()? {
397        Some(Element::Scalar {
398            value: Value::Uint(v),
399            ..
400        }) => Ok(u32::try_from(v).map_err(|_| ClusterError::InvalidLength("IcdCounter"))?),
401        _ => Err(ClusterError::UnexpectedType {
402            context: "IcdCounter",
403        }),
404    }
405}
406
407/// Decode the `ClientsSupportedPerFabric` attribute value.
408///
409/// # Errors
410/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
411pub fn decode_clients_supported_per_fabric(tlv: &[u8]) -> Result<u16, ClusterError> {
412    let mut r = TlvReader::new(tlv);
413    match r.next()? {
414        Some(Element::Scalar {
415            value: Value::Uint(v),
416            ..
417        }) => Ok(u16::try_from(v)
418            .map_err(|_| ClusterError::InvalidLength("ClientsSupportedPerFabric"))?),
419        _ => Err(ClusterError::UnexpectedType {
420            context: "ClientsSupportedPerFabric",
421        }),
422    }
423}
424
425/// Decode the `UserActiveModeTriggerHint` attribute value.
426///
427/// # Errors
428/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
429pub fn decode_user_active_mode_trigger_hint(
430    tlv: &[u8],
431) -> Result<UserActiveModeTriggerBitmap, ClusterError> {
432    let mut r = TlvReader::new(tlv);
433    match r.next()? {
434        Some(Element::Scalar {
435            value: Value::Uint(v),
436            ..
437        }) => Ok(UserActiveModeTriggerBitmap::from_bits_retain(
438            u32::try_from(v)
439                .map_err(|_| ClusterError::InvalidLength("UserActiveModeTriggerHint"))?,
440        )),
441        _ => Err(ClusterError::UnexpectedType {
442            context: "UserActiveModeTriggerHint",
443        }),
444    }
445}
446
447/// Decode the `UserActiveModeTriggerInstruction` attribute value.
448///
449/// # Errors
450/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
451pub fn decode_user_active_mode_trigger_instruction(tlv: &[u8]) -> Result<String, ClusterError> {
452    let mut r = TlvReader::new(tlv);
453    match r.next()? {
454        Some(Element::Scalar {
455            value: Value::Utf8(v),
456            ..
457        }) => Ok(v),
458        _ => Err(ClusterError::UnexpectedType {
459            context: "UserActiveModeTriggerInstruction",
460        }),
461    }
462}
463
464/// Decode the `OperatingMode` attribute value.
465///
466/// # Errors
467/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
468pub fn decode_operating_mode(tlv: &[u8]) -> Result<OperatingModeEnum, ClusterError> {
469    let mut r = TlvReader::new(tlv);
470    match r.next()? {
471        Some(Element::Scalar {
472            value: Value::Uint(v),
473            ..
474        }) => Ok(OperatingModeEnum::from_raw(
475            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("OperatingMode"))?,
476        )),
477        _ => Err(ClusterError::UnexpectedType {
478            context: "OperatingMode",
479        }),
480    }
481}
482
483/// Decode the `MaximumCheckInBackoff` attribute value.
484///
485/// # Errors
486/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
487pub fn decode_maximum_check_in_backoff(tlv: &[u8]) -> Result<u32, ClusterError> {
488    let mut r = TlvReader::new(tlv);
489    match r.next()? {
490        Some(Element::Scalar {
491            value: Value::Uint(v),
492            ..
493        }) => {
494            Ok(u32::try_from(v)
495                .map_err(|_| ClusterError::InvalidLength("MaximumCheckInBackoff"))?)
496        }
497        _ => Err(ClusterError::UnexpectedType {
498            context: "MaximumCheckInBackoff",
499        }),
500    }
501}
502
503/// Encode the `RegisterClient` command request payload.
504#[must_use]
505#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
506pub fn encode_register_client(
507    check_in_node_id: u64,
508    monitored_subject: u64,
509    key: &Vec<u8>,
510    verification_key: Option<Vec<u8>>,
511    client_type: ClientTypeEnum,
512) -> Vec<u8> {
513    let mut buf = Vec::new();
514    let mut w = TlvWriter::new(&mut buf);
515    w.start_structure(Tag::Anonymous)
516        .expect("infallible: vec writer");
517    w.put_uint(Tag::Context(0), u64::from(check_in_node_id))
518        .expect("infallible: vec writer");
519    w.put_uint(Tag::Context(1), u64::from(monitored_subject))
520        .expect("infallible: vec writer");
521    w.put_bytes(Tag::Context(2), &key)
522        .expect("infallible: vec writer");
523    if let Some(verification_key) = verification_key {
524        w.put_bytes(Tag::Context(3), &verification_key)
525            .expect("infallible: vec writer");
526    }
527    w.put_uint(Tag::Context(4), u64::from(client_type.to_raw()))
528        .expect("infallible: vec writer");
529    w.end_container().expect("infallible: vec writer");
530    buf
531}
532
533/// Decoded `RegisterClientResponse` payload.
534#[derive(Clone, Debug, PartialEq)]
535#[non_exhaustive]
536pub struct RegisterClientResponse {
537    /// Field IcdCounter (tag 0).
538    pub icd_counter: u32,
539}
540
541impl RegisterClientResponse {
542    /// Decode the fields of an already-opened anonymous structure
543    /// (reader positioned after the struct start; consumes to its end).
544    ///
545    /// # Errors
546    /// Returns [`ClusterError`] on a malformed structure or missing required field.
547    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
548        let mut f_icd_counter: Option<u32> = None;
549        loop {
550            match r.next()? {
551                Some(Element::ContainerEnd) => break,
552                Some(Element::Scalar {
553                    tag: Tag::Context(0),
554                    value: Value::Uint(v),
555                }) => {
556                    f_icd_counter = Some(
557                        u32::try_from(v).map_err(|_| ClusterError::InvalidLength("IcdCounter"))?,
558                    )
559                }
560                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
561                Some(Element::ContainerStart { .. }) => r.skip_container()?,
562                Some(_) => {} // unknown/future scalar — skip
563            }
564        }
565        Ok(Self {
566            icd_counter: f_icd_counter.ok_or(ClusterError::MissingField("IcdCounter"))?,
567        })
568    }
569    /// Decode from a standalone anonymous TLV structure.
570    ///
571    /// # Errors
572    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
573    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
574        let mut r = TlvReader::new(tlv);
575        match r.next()? {
576            Some(Element::ContainerStart {
577                kind: ContainerKind::Structure,
578                ..
579            }) => {}
580            _ => {
581                return Err(ClusterError::UnexpectedType {
582                    context: "RegisterClientResponse",
583                })
584            }
585        }
586        Self::decode_from(&mut r)
587    }
588}
589
590/// Encode the `UnregisterClient` command request payload.
591#[must_use]
592#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
593pub fn encode_unregister_client(
594    check_in_node_id: u64,
595    verification_key: Option<Vec<u8>>,
596) -> Vec<u8> {
597    let mut buf = Vec::new();
598    let mut w = TlvWriter::new(&mut buf);
599    w.start_structure(Tag::Anonymous)
600        .expect("infallible: vec writer");
601    w.put_uint(Tag::Context(0), u64::from(check_in_node_id))
602        .expect("infallible: vec writer");
603    if let Some(verification_key) = verification_key {
604        w.put_bytes(Tag::Context(1), &verification_key)
605            .expect("infallible: vec writer");
606    }
607    w.end_container().expect("infallible: vec writer");
608    buf
609}
610
611/// Encode the `StayActiveRequest` command request payload.
612#[must_use]
613#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
614pub fn encode_stay_active_request(stay_active_duration: u32) -> Vec<u8> {
615    let mut buf = Vec::new();
616    let mut w = TlvWriter::new(&mut buf);
617    w.start_structure(Tag::Anonymous)
618        .expect("infallible: vec writer");
619    w.put_uint(Tag::Context(0), u64::from(stay_active_duration))
620        .expect("infallible: vec writer");
621    w.end_container().expect("infallible: vec writer");
622    buf
623}
624
625/// Decoded `StayActiveResponse` payload.
626#[derive(Clone, Debug, PartialEq)]
627#[non_exhaustive]
628pub struct StayActiveResponse {
629    /// Field PromisedActiveDuration (tag 0).
630    pub promised_active_duration: u32,
631}
632
633impl StayActiveResponse {
634    /// Decode the fields of an already-opened anonymous structure
635    /// (reader positioned after the struct start; consumes to its end).
636    ///
637    /// # Errors
638    /// Returns [`ClusterError`] on a malformed structure or missing required field.
639    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
640        let mut f_promised_active_duration: Option<u32> = None;
641        loop {
642            match r.next()? {
643                Some(Element::ContainerEnd) => break,
644                Some(Element::Scalar {
645                    tag: Tag::Context(0),
646                    value: Value::Uint(v),
647                }) => {
648                    f_promised_active_duration = Some(
649                        u32::try_from(v)
650                            .map_err(|_| ClusterError::InvalidLength("PromisedActiveDuration"))?,
651                    )
652                }
653                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
654                Some(Element::ContainerStart { .. }) => r.skip_container()?,
655                Some(_) => {} // unknown/future scalar — skip
656            }
657        }
658        Ok(Self {
659            promised_active_duration: f_promised_active_duration
660                .ok_or(ClusterError::MissingField("PromisedActiveDuration"))?,
661        })
662    }
663    /// Decode from a standalone anonymous TLV structure.
664    ///
665    /// # Errors
666    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
667    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
668        let mut r = TlvReader::new(tlv);
669        match r.next()? {
670            Some(Element::ContainerStart {
671                kind: ContainerKind::Structure,
672                ..
673            }) => {}
674            _ => {
675                return Err(ClusterError::UnexpectedType {
676                    context: "StayActiveResponse",
677                })
678            }
679        }
680        Self::decode_from(&mut r)
681    }
682}