Skip to main content

matter_clusters/gen/
door_lock.rs

1//! DoorLock cluster (0x0101).
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 = 0x0101;
19/// Cluster revision.
20pub const CLUSTER_REVISION: u16 = 10;
21
22/// Command IDs (requests and responses).
23pub mod command_id {
24    /// `LockDoor` (request).
25    pub const LOCK_DOOR: u32 = 0x00;
26    /// `UnlockDoor` (request).
27    pub const UNLOCK_DOOR: u32 = 0x01;
28    /// `UnlockWithTimeout` (request).
29    pub const UNLOCK_WITH_TIMEOUT: u32 = 0x03;
30    /// `SetWeekDaySchedule` (request).
31    pub const SET_WEEK_DAY_SCHEDULE: u32 = 0x0B;
32    /// `GetWeekDaySchedule` (request).
33    pub const GET_WEEK_DAY_SCHEDULE: u32 = 0x0C;
34    /// `GetWeekDayScheduleResponse` (response).
35    pub const GET_WEEK_DAY_SCHEDULE_RESPONSE: u32 = 0x0C;
36    /// `ClearWeekDaySchedule` (request).
37    pub const CLEAR_WEEK_DAY_SCHEDULE: u32 = 0x0D;
38    /// `SetYearDaySchedule` (request).
39    pub const SET_YEAR_DAY_SCHEDULE: u32 = 0x0E;
40    /// `GetYearDaySchedule` (request).
41    pub const GET_YEAR_DAY_SCHEDULE: u32 = 0x0F;
42    /// `GetYearDayScheduleResponse` (response).
43    pub const GET_YEAR_DAY_SCHEDULE_RESPONSE: u32 = 0x0F;
44    /// `ClearYearDaySchedule` (request).
45    pub const CLEAR_YEAR_DAY_SCHEDULE: u32 = 0x10;
46    /// `SetHolidaySchedule` (request).
47    pub const SET_HOLIDAY_SCHEDULE: u32 = 0x11;
48    /// `GetHolidaySchedule` (request).
49    pub const GET_HOLIDAY_SCHEDULE: u32 = 0x12;
50    /// `GetHolidayScheduleResponse` (response).
51    pub const GET_HOLIDAY_SCHEDULE_RESPONSE: u32 = 0x12;
52    /// `ClearHolidaySchedule` (request).
53    pub const CLEAR_HOLIDAY_SCHEDULE: u32 = 0x13;
54    /// `SetUser` (request).
55    pub const SET_USER: u32 = 0x1A;
56    /// `GetUser` (request).
57    pub const GET_USER: u32 = 0x1B;
58    /// `GetUserResponse` (response).
59    pub const GET_USER_RESPONSE: u32 = 0x1C;
60    /// `ClearUser` (request).
61    pub const CLEAR_USER: u32 = 0x1D;
62    /// `SetCredential` (request).
63    pub const SET_CREDENTIAL: u32 = 0x22;
64    /// `SetCredentialResponse` (response).
65    pub const SET_CREDENTIAL_RESPONSE: u32 = 0x23;
66    /// `GetCredentialStatus` (request).
67    pub const GET_CREDENTIAL_STATUS: u32 = 0x24;
68    /// `GetCredentialStatusResponse` (response).
69    pub const GET_CREDENTIAL_STATUS_RESPONSE: u32 = 0x25;
70    /// `ClearCredential` (request).
71    pub const CLEAR_CREDENTIAL: u32 = 0x26;
72    /// `UnboltDoor` (request).
73    pub const UNBOLT_DOOR: u32 = 0x27;
74}
75
76/// Attribute IDs (cluster-specific).
77pub mod attribute_id {
78    /// `LockState`.
79    pub const LOCK_STATE: u32 = 0x0000;
80    /// `LockType`.
81    pub const LOCK_TYPE: u32 = 0x0001;
82    /// `ActuatorEnabled`.
83    pub const ACTUATOR_ENABLED: u32 = 0x0002;
84    /// `DoorState`.
85    pub const DOOR_STATE: u32 = 0x0003;
86    /// `DoorOpenEvents`.
87    pub const DOOR_OPEN_EVENTS: u32 = 0x0004;
88    /// `DoorClosedEvents`.
89    pub const DOOR_CLOSED_EVENTS: u32 = 0x0005;
90    /// `OpenPeriod`.
91    pub const OPEN_PERIOD: u32 = 0x0006;
92    /// `NumberOfTotalUsersSupported`.
93    pub const NUMBER_OF_TOTAL_USERS_SUPPORTED: u32 = 0x0011;
94    /// `NumberOfPinUsersSupported`.
95    pub const NUMBER_OF_PIN_USERS_SUPPORTED: u32 = 0x0012;
96    /// `NumberOfRfidUsersSupported`.
97    pub const NUMBER_OF_RFID_USERS_SUPPORTED: u32 = 0x0013;
98    /// `NumberOfWeekDaySchedulesSupportedPerUser`.
99    pub const NUMBER_OF_WEEK_DAY_SCHEDULES_SUPPORTED_PER_USER: u32 = 0x0014;
100    /// `NumberOfYearDaySchedulesSupportedPerUser`.
101    pub const NUMBER_OF_YEAR_DAY_SCHEDULES_SUPPORTED_PER_USER: u32 = 0x0015;
102    /// `NumberOfHolidaySchedulesSupported`.
103    pub const NUMBER_OF_HOLIDAY_SCHEDULES_SUPPORTED: u32 = 0x0016;
104    /// `MaxPinCodeLength`.
105    pub const MAX_PIN_CODE_LENGTH: u32 = 0x0017;
106    /// `MinPinCodeLength`.
107    pub const MIN_PIN_CODE_LENGTH: u32 = 0x0018;
108    /// `MaxRfidCodeLength`.
109    pub const MAX_RFID_CODE_LENGTH: u32 = 0x0019;
110    /// `MinRfidCodeLength`.
111    pub const MIN_RFID_CODE_LENGTH: u32 = 0x001A;
112    /// `CredentialRulesSupport`.
113    pub const CREDENTIAL_RULES_SUPPORT: u32 = 0x001B;
114    /// `NumberOfCredentialsSupportedPerUser`.
115    pub const NUMBER_OF_CREDENTIALS_SUPPORTED_PER_USER: u32 = 0x001C;
116    /// `Language`.
117    pub const LANGUAGE: u32 = 0x0021;
118    /// `LedSettings`.
119    pub const LED_SETTINGS: u32 = 0x0022;
120    /// `AutoRelockTime`.
121    pub const AUTO_RELOCK_TIME: u32 = 0x0023;
122    /// `SoundVolume`.
123    pub const SOUND_VOLUME: u32 = 0x0024;
124    /// `OperatingMode`.
125    pub const OPERATING_MODE: u32 = 0x0025;
126    /// `SupportedOperatingModes`.
127    pub const SUPPORTED_OPERATING_MODES: u32 = 0x0026;
128    /// `DefaultConfigurationRegister`.
129    pub const DEFAULT_CONFIGURATION_REGISTER: u32 = 0x0027;
130    /// `EnableLocalProgramming`.
131    pub const ENABLE_LOCAL_PROGRAMMING: u32 = 0x0028;
132    /// `EnableOneTouchLocking`.
133    pub const ENABLE_ONE_TOUCH_LOCKING: u32 = 0x0029;
134    /// `EnableInsideStatusLed`.
135    pub const ENABLE_INSIDE_STATUS_LED: u32 = 0x002A;
136    /// `EnablePrivacyModeButton`.
137    pub const ENABLE_PRIVACY_MODE_BUTTON: u32 = 0x002B;
138    /// `LocalProgrammingFeatures`.
139    pub const LOCAL_PROGRAMMING_FEATURES: u32 = 0x002C;
140    /// `WrongCodeEntryLimit`.
141    pub const WRONG_CODE_ENTRY_LIMIT: u32 = 0x0030;
142    /// `UserCodeTemporaryDisableTime`.
143    pub const USER_CODE_TEMPORARY_DISABLE_TIME: u32 = 0x0031;
144    /// `SendPinOverTheAir`.
145    pub const SEND_PIN_OVER_THE_AIR: u32 = 0x0032;
146    /// `RequirePinForRemoteOperation`.
147    pub const REQUIRE_PIN_FOR_REMOTE_OPERATION: u32 = 0x0033;
148    /// `ExpiringUserTimeout`.
149    pub const EXPIRING_USER_TIMEOUT: u32 = 0x0035;
150}
151
152bitflags::bitflags! {
153    /// `DoorLock` feature bits (FeatureMap).
154    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
155    pub struct Feature: u32 {
156        /// PinCredential (PIN).
157        const PIN = 1 << 0;
158        /// RfidCredential (RID).
159        const RID = 1 << 1;
160        /// FingerCredentials (FGP).
161        const FGP = 1 << 2;
162        /// WeekDayAccessSchedules (WDSCH).
163        const WDSCH = 1 << 4;
164        /// DoorPositionSensor (DPS).
165        const DPS = 1 << 5;
166        /// FaceCredentials (FACE).
167        const FACE = 1 << 6;
168        /// CredentialOverTheAirAccess (COTA).
169        const COTA = 1 << 7;
170        /// User (USR).
171        const USR = 1 << 8;
172        /// YearDayAccessSchedules (YDSCH).
173        const YDSCH = 1 << 10;
174        /// HolidaySchedules (HDSCH).
175        const HDSCH = 1 << 11;
176        /// Unbolting (UBOLT).
177        const UBOLT = 1 << 12;
178        /// AliroProvisioning (ALIRO).
179        const ALIRO = 1 << 13;
180        /// AliroBleuwb (ALBU).
181        const ALBU = 1 << 14;
182    }
183}
184
185/// `AlarmCodeEnum` (enum8).
186#[derive(Copy, Clone, Debug, PartialEq, Eq)]
187pub enum AlarmCodeEnum {
188    /// LockJammed = 0.
189    LockJammed,
190    /// LockFactoryReset = 1.
191    LockFactoryReset,
192    /// LockRadioPowerCycled = 3.
193    LockRadioPowerCycled,
194    /// WrongCodeEntryLimit = 4.
195    WrongCodeEntryLimit,
196    /// FrontEsceutcheonRemoved = 5.
197    FrontEsceutcheonRemoved,
198    /// DoorForcedOpen = 6.
199    DoorForcedOpen,
200    /// DoorAjar = 7.
201    DoorAjar,
202    /// ForcedUser = 8.
203    ForcedUser,
204    /// A value not known to this codegen revision.
205    Unknown(u8),
206}
207
208impl AlarmCodeEnum {
209    /// Decode from its raw discriminant (unknown → `Unknown`).
210    #[must_use]
211    pub fn from_raw(v: u8) -> Self {
212        match v {
213            0 => Self::LockJammed,
214            1 => Self::LockFactoryReset,
215            3 => Self::LockRadioPowerCycled,
216            4 => Self::WrongCodeEntryLimit,
217            5 => Self::FrontEsceutcheonRemoved,
218            6 => Self::DoorForcedOpen,
219            7 => Self::DoorAjar,
220            8 => Self::ForcedUser,
221            other => Self::Unknown(other),
222        }
223    }
224    /// The raw discriminant.
225    #[must_use]
226    pub fn to_raw(self) -> u8 {
227        match self {
228            Self::LockJammed => 0,
229            Self::LockFactoryReset => 1,
230            Self::LockRadioPowerCycled => 3,
231            Self::WrongCodeEntryLimit => 4,
232            Self::FrontEsceutcheonRemoved => 5,
233            Self::DoorForcedOpen => 6,
234            Self::DoorAjar => 7,
235            Self::ForcedUser => 8,
236            Self::Unknown(v) => v,
237        }
238    }
239}
240
241bitflags::bitflags! {
242    /// `AlarmMaskBitmap` (map16).
243    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
244    pub struct AlarmMaskBitmap: u16 {
245        /// LockJammed.
246        const LOCK_JAMMED = 1 << 0;
247        /// LockFactoryReset.
248        const LOCK_FACTORY_RESET = 1 << 1;
249        /// LockRadioPowerCycled.
250        const LOCK_RADIO_POWER_CYCLED = 1 << 3;
251        /// WrongCodeEntryLimit.
252        const WRONG_CODE_ENTRY_LIMIT = 1 << 4;
253        /// FrontEscutcheonRemoved.
254        const FRONT_ESCUTCHEON_REMOVED = 1 << 5;
255        /// DoorForcedOpen.
256        const DOOR_FORCED_OPEN = 1 << 6;
257    }
258}
259
260bitflags::bitflags! {
261    /// `ConfigurationRegisterBitmap` (map16).
262    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
263    pub struct ConfigurationRegisterBitmap: u16 {
264        /// LocalProgramming.
265        const LOCAL_PROGRAMMING = 1 << 0;
266        /// KeypadInterface.
267        const KEYPAD_INTERFACE = 1 << 1;
268        /// RemoteInterface.
269        const REMOTE_INTERFACE = 1 << 2;
270        /// SoundVolume.
271        const SOUND_VOLUME = 1 << 5;
272        /// AutoRelockTime.
273        const AUTO_RELOCK_TIME = 1 << 6;
274        /// LedSettings.
275        const LED_SETTINGS = 1 << 7;
276    }
277}
278
279/// `CredentialRuleEnum` (enum8).
280#[derive(Copy, Clone, Debug, PartialEq, Eq)]
281pub enum CredentialRuleEnum {
282    /// Single = 0.
283    Single,
284    /// Dual = 1.
285    Dual,
286    /// Tri = 2.
287    Tri,
288    /// A value not known to this codegen revision.
289    Unknown(u8),
290}
291
292impl CredentialRuleEnum {
293    /// Decode from its raw discriminant (unknown → `Unknown`).
294    #[must_use]
295    pub fn from_raw(v: u8) -> Self {
296        match v {
297            0 => Self::Single,
298            1 => Self::Dual,
299            2 => Self::Tri,
300            other => Self::Unknown(other),
301        }
302    }
303    /// The raw discriminant.
304    #[must_use]
305    pub fn to_raw(self) -> u8 {
306        match self {
307            Self::Single => 0,
308            Self::Dual => 1,
309            Self::Tri => 2,
310            Self::Unknown(v) => v,
311        }
312    }
313}
314
315bitflags::bitflags! {
316    /// `CredentialRulesBitmap` (map8).
317    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
318    pub struct CredentialRulesBitmap: u8 {
319        /// Single.
320        const SINGLE = 1 << 0;
321        /// Dual.
322        const DUAL = 1 << 1;
323        /// Tri.
324        const TRI = 1 << 2;
325    }
326}
327
328/// `CredentialStruct` struct.
329#[derive(Clone, Debug, PartialEq)]
330pub struct CredentialStruct {
331    /// Field CredentialType (tag 0).
332    pub credential_type: CredentialTypeEnum,
333    /// Field CredentialIndex (tag 1).
334    pub credential_index: u16,
335}
336
337/// `CredentialTypeEnum` (enum8).
338#[derive(Copy, Clone, Debug, PartialEq, Eq)]
339pub enum CredentialTypeEnum {
340    /// ProgrammingPin = 0.
341    ProgrammingPin,
342    /// Pin = 1.
343    Pin,
344    /// Rfid = 2.
345    Rfid,
346    /// Fingerprint = 3.
347    Fingerprint,
348    /// FingerVein = 4.
349    FingerVein,
350    /// Face = 5.
351    Face,
352    /// AliroCredentialIssuerKey = 6.
353    AliroCredentialIssuerKey,
354    /// AliroEvictableEndpointKey = 7.
355    AliroEvictableEndpointKey,
356    /// AliroNonEvictableEndpointKey = 8.
357    AliroNonEvictableEndpointKey,
358    /// A value not known to this codegen revision.
359    Unknown(u8),
360}
361
362impl CredentialTypeEnum {
363    /// Decode from its raw discriminant (unknown → `Unknown`).
364    #[must_use]
365    pub fn from_raw(v: u8) -> Self {
366        match v {
367            0 => Self::ProgrammingPin,
368            1 => Self::Pin,
369            2 => Self::Rfid,
370            3 => Self::Fingerprint,
371            4 => Self::FingerVein,
372            5 => Self::Face,
373            6 => Self::AliroCredentialIssuerKey,
374            7 => Self::AliroEvictableEndpointKey,
375            8 => Self::AliroNonEvictableEndpointKey,
376            other => Self::Unknown(other),
377        }
378    }
379    /// The raw discriminant.
380    #[must_use]
381    pub fn to_raw(self) -> u8 {
382        match self {
383            Self::ProgrammingPin => 0,
384            Self::Pin => 1,
385            Self::Rfid => 2,
386            Self::Fingerprint => 3,
387            Self::FingerVein => 4,
388            Self::Face => 5,
389            Self::AliroCredentialIssuerKey => 6,
390            Self::AliroEvictableEndpointKey => 7,
391            Self::AliroNonEvictableEndpointKey => 8,
392            Self::Unknown(v) => v,
393        }
394    }
395}
396
397/// `DataOperationTypeEnum` (enum8).
398#[derive(Copy, Clone, Debug, PartialEq, Eq)]
399pub enum DataOperationTypeEnum {
400    /// Add = 0.
401    Add,
402    /// Clear = 1.
403    Clear,
404    /// Modify = 2.
405    Modify,
406    /// A value not known to this codegen revision.
407    Unknown(u8),
408}
409
410impl DataOperationTypeEnum {
411    /// Decode from its raw discriminant (unknown → `Unknown`).
412    #[must_use]
413    pub fn from_raw(v: u8) -> Self {
414        match v {
415            0 => Self::Add,
416            1 => Self::Clear,
417            2 => Self::Modify,
418            other => Self::Unknown(other),
419        }
420    }
421    /// The raw discriminant.
422    #[must_use]
423    pub fn to_raw(self) -> u8 {
424        match self {
425            Self::Add => 0,
426            Self::Clear => 1,
427            Self::Modify => 2,
428            Self::Unknown(v) => v,
429        }
430    }
431}
432
433bitflags::bitflags! {
434    /// `DaysMaskBitmap` (map8).
435    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
436    pub struct DaysMaskBitmap: u8 {
437        /// Sunday.
438        const SUNDAY = 1 << 0;
439        /// Monday.
440        const MONDAY = 1 << 1;
441        /// Tuesday.
442        const TUESDAY = 1 << 2;
443        /// Wednesday.
444        const WEDNESDAY = 1 << 3;
445        /// Thursday.
446        const THURSDAY = 1 << 4;
447        /// Friday.
448        const FRIDAY = 1 << 5;
449        /// Saturday.
450        const SATURDAY = 1 << 6;
451    }
452}
453
454/// `DoorStateEnum` (enum8).
455#[derive(Copy, Clone, Debug, PartialEq, Eq)]
456pub enum DoorStateEnum {
457    /// DoorOpen = 0.
458    DoorOpen,
459    /// DoorClosed = 1.
460    DoorClosed,
461    /// DoorJammed = 2.
462    DoorJammed,
463    /// DoorForcedOpen = 3.
464    DoorForcedOpen,
465    /// DoorUnspecifiedError = 4.
466    DoorUnspecifiedError,
467    /// DoorAjar = 5.
468    DoorAjar,
469    /// A value not known to this codegen revision.
470    Unknown(u8),
471}
472
473impl DoorStateEnum {
474    /// Decode from its raw discriminant (unknown → `Unknown`).
475    #[must_use]
476    pub fn from_raw(v: u8) -> Self {
477        match v {
478            0 => Self::DoorOpen,
479            1 => Self::DoorClosed,
480            2 => Self::DoorJammed,
481            3 => Self::DoorForcedOpen,
482            4 => Self::DoorUnspecifiedError,
483            5 => Self::DoorAjar,
484            other => Self::Unknown(other),
485        }
486    }
487    /// The raw discriminant.
488    #[must_use]
489    pub fn to_raw(self) -> u8 {
490        match self {
491            Self::DoorOpen => 0,
492            Self::DoorClosed => 1,
493            Self::DoorJammed => 2,
494            Self::DoorForcedOpen => 3,
495            Self::DoorUnspecifiedError => 4,
496            Self::DoorAjar => 5,
497            Self::Unknown(v) => v,
498        }
499    }
500}
501
502/// `EventTypeEnum` (enum8).
503#[derive(Copy, Clone, Debug, PartialEq, Eq)]
504pub enum EventTypeEnum {
505    /// Operation = 0.
506    Operation,
507    /// Programming = 1.
508    Programming,
509    /// Alarm = 2.
510    Alarm,
511    /// A value not known to this codegen revision.
512    Unknown(u8),
513}
514
515impl EventTypeEnum {
516    /// Decode from its raw discriminant (unknown → `Unknown`).
517    #[must_use]
518    pub fn from_raw(v: u8) -> Self {
519        match v {
520            0 => Self::Operation,
521            1 => Self::Programming,
522            2 => Self::Alarm,
523            other => Self::Unknown(other),
524        }
525    }
526    /// The raw discriminant.
527    #[must_use]
528    pub fn to_raw(self) -> u8 {
529        match self {
530            Self::Operation => 0,
531            Self::Programming => 1,
532            Self::Alarm => 2,
533            Self::Unknown(v) => v,
534        }
535    }
536}
537
538/// `LEDSettingEnum` (enum8).
539#[derive(Copy, Clone, Debug, PartialEq, Eq)]
540pub enum LEDSettingEnum {
541    /// NoLedSignal = 0.
542    NoLedSignal,
543    /// NoLedSignalAccessAllowed = 1.
544    NoLedSignalAccessAllowed,
545    /// LedSignalAll = 2.
546    LedSignalAll,
547    /// A value not known to this codegen revision.
548    Unknown(u8),
549}
550
551impl LEDSettingEnum {
552    /// Decode from its raw discriminant (unknown → `Unknown`).
553    #[must_use]
554    pub fn from_raw(v: u8) -> Self {
555        match v {
556            0 => Self::NoLedSignal,
557            1 => Self::NoLedSignalAccessAllowed,
558            2 => Self::LedSignalAll,
559            other => Self::Unknown(other),
560        }
561    }
562    /// The raw discriminant.
563    #[must_use]
564    pub fn to_raw(self) -> u8 {
565        match self {
566            Self::NoLedSignal => 0,
567            Self::NoLedSignalAccessAllowed => 1,
568            Self::LedSignalAll => 2,
569            Self::Unknown(v) => v,
570        }
571    }
572}
573
574bitflags::bitflags! {
575    /// `LocalProgrammingFeaturesBitmap` (map8).
576    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
577    pub struct LocalProgrammingFeaturesBitmap: u8 {
578        /// AddUsersCredentialsSchedules.
579        const ADD_USERS_CREDENTIALS_SCHEDULES = 1 << 0;
580        /// ModifyUsersCredentialsSchedules.
581        const MODIFY_USERS_CREDENTIALS_SCHEDULES = 1 << 1;
582        /// ClearUsersCredentialsSchedules.
583        const CLEAR_USERS_CREDENTIALS_SCHEDULES = 1 << 2;
584        /// AdjustSettings.
585        const ADJUST_SETTINGS = 1 << 3;
586    }
587}
588
589/// `LockDataTypeEnum` (enum8).
590#[derive(Copy, Clone, Debug, PartialEq, Eq)]
591pub enum LockDataTypeEnum {
592    /// Unspecified = 0.
593    Unspecified,
594    /// ProgrammingCode = 1.
595    ProgrammingCode,
596    /// UserIndex = 2.
597    UserIndex,
598    /// WeekDaySchedule = 3.
599    WeekDaySchedule,
600    /// YearDaySchedule = 4.
601    YearDaySchedule,
602    /// HolidaySchedule = 5.
603    HolidaySchedule,
604    /// Pin = 6.
605    Pin,
606    /// Rfid = 7.
607    Rfid,
608    /// Fingerprint = 8.
609    Fingerprint,
610    /// FingerVein = 9.
611    FingerVein,
612    /// Face = 10.
613    Face,
614    /// AliroCredentialIssuerKey = 11.
615    AliroCredentialIssuerKey,
616    /// AliroEvictableEndpointKey = 12.
617    AliroEvictableEndpointKey,
618    /// AliroNonEvictableEndpointKey = 13.
619    AliroNonEvictableEndpointKey,
620    /// A value not known to this codegen revision.
621    Unknown(u8),
622}
623
624impl LockDataTypeEnum {
625    /// Decode from its raw discriminant (unknown → `Unknown`).
626    #[must_use]
627    pub fn from_raw(v: u8) -> Self {
628        match v {
629            0 => Self::Unspecified,
630            1 => Self::ProgrammingCode,
631            2 => Self::UserIndex,
632            3 => Self::WeekDaySchedule,
633            4 => Self::YearDaySchedule,
634            5 => Self::HolidaySchedule,
635            6 => Self::Pin,
636            7 => Self::Rfid,
637            8 => Self::Fingerprint,
638            9 => Self::FingerVein,
639            10 => Self::Face,
640            11 => Self::AliroCredentialIssuerKey,
641            12 => Self::AliroEvictableEndpointKey,
642            13 => Self::AliroNonEvictableEndpointKey,
643            other => Self::Unknown(other),
644        }
645    }
646    /// The raw discriminant.
647    #[must_use]
648    pub fn to_raw(self) -> u8 {
649        match self {
650            Self::Unspecified => 0,
651            Self::ProgrammingCode => 1,
652            Self::UserIndex => 2,
653            Self::WeekDaySchedule => 3,
654            Self::YearDaySchedule => 4,
655            Self::HolidaySchedule => 5,
656            Self::Pin => 6,
657            Self::Rfid => 7,
658            Self::Fingerprint => 8,
659            Self::FingerVein => 9,
660            Self::Face => 10,
661            Self::AliroCredentialIssuerKey => 11,
662            Self::AliroEvictableEndpointKey => 12,
663            Self::AliroNonEvictableEndpointKey => 13,
664            Self::Unknown(v) => v,
665        }
666    }
667}
668
669/// `LockOperationTypeEnum` (enum8).
670#[derive(Copy, Clone, Debug, PartialEq, Eq)]
671pub enum LockOperationTypeEnum {
672    /// Lock = 0.
673    Lock,
674    /// Unlock = 1.
675    Unlock,
676    /// NonAccessUserEvent = 2.
677    NonAccessUserEvent,
678    /// ForcedUserEvent = 3.
679    ForcedUserEvent,
680    /// Unlatch = 4.
681    Unlatch,
682    /// A value not known to this codegen revision.
683    Unknown(u8),
684}
685
686impl LockOperationTypeEnum {
687    /// Decode from its raw discriminant (unknown → `Unknown`).
688    #[must_use]
689    pub fn from_raw(v: u8) -> Self {
690        match v {
691            0 => Self::Lock,
692            1 => Self::Unlock,
693            2 => Self::NonAccessUserEvent,
694            3 => Self::ForcedUserEvent,
695            4 => Self::Unlatch,
696            other => Self::Unknown(other),
697        }
698    }
699    /// The raw discriminant.
700    #[must_use]
701    pub fn to_raw(self) -> u8 {
702        match self {
703            Self::Lock => 0,
704            Self::Unlock => 1,
705            Self::NonAccessUserEvent => 2,
706            Self::ForcedUserEvent => 3,
707            Self::Unlatch => 4,
708            Self::Unknown(v) => v,
709        }
710    }
711}
712
713/// `LockStateEnum` (enum8).
714#[derive(Copy, Clone, Debug, PartialEq, Eq)]
715pub enum LockStateEnum {
716    /// NotFullyLocked = 0.
717    NotFullyLocked,
718    /// Locked = 1.
719    Locked,
720    /// Unlocked = 2.
721    Unlocked,
722    /// Unlatched = 3.
723    Unlatched,
724    /// A value not known to this codegen revision.
725    Unknown(u8),
726}
727
728impl LockStateEnum {
729    /// Decode from its raw discriminant (unknown → `Unknown`).
730    #[must_use]
731    pub fn from_raw(v: u8) -> Self {
732        match v {
733            0 => Self::NotFullyLocked,
734            1 => Self::Locked,
735            2 => Self::Unlocked,
736            3 => Self::Unlatched,
737            other => Self::Unknown(other),
738        }
739    }
740    /// The raw discriminant.
741    #[must_use]
742    pub fn to_raw(self) -> u8 {
743        match self {
744            Self::NotFullyLocked => 0,
745            Self::Locked => 1,
746            Self::Unlocked => 2,
747            Self::Unlatched => 3,
748            Self::Unknown(v) => v,
749        }
750    }
751}
752
753/// `LockTypeEnum` (enum8).
754#[derive(Copy, Clone, Debug, PartialEq, Eq)]
755pub enum LockTypeEnum {
756    /// DeadBolt = 0.
757    DeadBolt,
758    /// Magnetic = 1.
759    Magnetic,
760    /// Other = 2.
761    Other,
762    /// Mortise = 3.
763    Mortise,
764    /// Rim = 4.
765    Rim,
766    /// LatchBolt = 5.
767    LatchBolt,
768    /// CylindricalLock = 6.
769    CylindricalLock,
770    /// TubularLock = 7.
771    TubularLock,
772    /// InterconnectedLock = 8.
773    InterconnectedLock,
774    /// DeadLatch = 9.
775    DeadLatch,
776    /// DoorFurniture = 10.
777    DoorFurniture,
778    /// Eurocylinder = 11.
779    Eurocylinder,
780    /// A value not known to this codegen revision.
781    Unknown(u8),
782}
783
784impl LockTypeEnum {
785    /// Decode from its raw discriminant (unknown → `Unknown`).
786    #[must_use]
787    pub fn from_raw(v: u8) -> Self {
788        match v {
789            0 => Self::DeadBolt,
790            1 => Self::Magnetic,
791            2 => Self::Other,
792            3 => Self::Mortise,
793            4 => Self::Rim,
794            5 => Self::LatchBolt,
795            6 => Self::CylindricalLock,
796            7 => Self::TubularLock,
797            8 => Self::InterconnectedLock,
798            9 => Self::DeadLatch,
799            10 => Self::DoorFurniture,
800            11 => Self::Eurocylinder,
801            other => Self::Unknown(other),
802        }
803    }
804    /// The raw discriminant.
805    #[must_use]
806    pub fn to_raw(self) -> u8 {
807        match self {
808            Self::DeadBolt => 0,
809            Self::Magnetic => 1,
810            Self::Other => 2,
811            Self::Mortise => 3,
812            Self::Rim => 4,
813            Self::LatchBolt => 5,
814            Self::CylindricalLock => 6,
815            Self::TubularLock => 7,
816            Self::InterconnectedLock => 8,
817            Self::DeadLatch => 9,
818            Self::DoorFurniture => 10,
819            Self::Eurocylinder => 11,
820            Self::Unknown(v) => v,
821        }
822    }
823}
824
825/// `OperatingModeEnum` (enum8).
826#[derive(Copy, Clone, Debug, PartialEq, Eq)]
827pub enum OperatingModeEnum {
828    /// Normal = 0.
829    Normal,
830    /// Vacation = 1.
831    Vacation,
832    /// Privacy = 2.
833    Privacy,
834    /// NoRemoteLockUnlock = 3.
835    NoRemoteLockUnlock,
836    /// Passage = 4.
837    Passage,
838    /// A value not known to this codegen revision.
839    Unknown(u8),
840}
841
842impl OperatingModeEnum {
843    /// Decode from its raw discriminant (unknown → `Unknown`).
844    #[must_use]
845    pub fn from_raw(v: u8) -> Self {
846        match v {
847            0 => Self::Normal,
848            1 => Self::Vacation,
849            2 => Self::Privacy,
850            3 => Self::NoRemoteLockUnlock,
851            4 => Self::Passage,
852            other => Self::Unknown(other),
853        }
854    }
855    /// The raw discriminant.
856    #[must_use]
857    pub fn to_raw(self) -> u8 {
858        match self {
859            Self::Normal => 0,
860            Self::Vacation => 1,
861            Self::Privacy => 2,
862            Self::NoRemoteLockUnlock => 3,
863            Self::Passage => 4,
864            Self::Unknown(v) => v,
865        }
866    }
867}
868
869bitflags::bitflags! {
870    /// `OperatingModesBitmap` (map16).
871    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
872    pub struct OperatingModesBitmap: u16 {
873        /// Normal.
874        const NORMAL = 1 << 0;
875        /// Vacation.
876        const VACATION = 1 << 1;
877        /// Privacy.
878        const PRIVACY = 1 << 2;
879        /// NoRemoteLockUnlock.
880        const NO_REMOTE_LOCK_UNLOCK = 1 << 3;
881        /// Passage.
882        const PASSAGE = 1 << 4;
883    }
884}
885
886/// `OperationErrorEnum` (enum8).
887#[derive(Copy, Clone, Debug, PartialEq, Eq)]
888pub enum OperationErrorEnum {
889    /// Unspecified = 0.
890    Unspecified,
891    /// InvalidCredential = 1.
892    InvalidCredential,
893    /// DisabledUserDenied = 2.
894    DisabledUserDenied,
895    /// Restricted = 3.
896    Restricted,
897    /// InsufficientBattery = 4.
898    InsufficientBattery,
899    /// A value not known to this codegen revision.
900    Unknown(u8),
901}
902
903impl OperationErrorEnum {
904    /// Decode from its raw discriminant (unknown → `Unknown`).
905    #[must_use]
906    pub fn from_raw(v: u8) -> Self {
907        match v {
908            0 => Self::Unspecified,
909            1 => Self::InvalidCredential,
910            2 => Self::DisabledUserDenied,
911            3 => Self::Restricted,
912            4 => Self::InsufficientBattery,
913            other => Self::Unknown(other),
914        }
915    }
916    /// The raw discriminant.
917    #[must_use]
918    pub fn to_raw(self) -> u8 {
919        match self {
920            Self::Unspecified => 0,
921            Self::InvalidCredential => 1,
922            Self::DisabledUserDenied => 2,
923            Self::Restricted => 3,
924            Self::InsufficientBattery => 4,
925            Self::Unknown(v) => v,
926        }
927    }
928}
929
930/// `OperationSourceEnum` (enum8).
931#[derive(Copy, Clone, Debug, PartialEq, Eq)]
932pub enum OperationSourceEnum {
933    /// Unspecified = 0.
934    Unspecified,
935    /// Manual = 1.
936    Manual,
937    /// ProprietaryRemote = 2.
938    ProprietaryRemote,
939    /// Keypad = 3.
940    Keypad,
941    /// Auto = 4.
942    Auto,
943    /// Button = 5.
944    Button,
945    /// Schedule = 6.
946    Schedule,
947    /// Remote = 7.
948    Remote,
949    /// Rfid = 8.
950    Rfid,
951    /// Biometric = 9.
952    Biometric,
953    /// Aliro = 10.
954    Aliro,
955    /// A value not known to this codegen revision.
956    Unknown(u8),
957}
958
959impl OperationSourceEnum {
960    /// Decode from its raw discriminant (unknown → `Unknown`).
961    #[must_use]
962    pub fn from_raw(v: u8) -> Self {
963        match v {
964            0 => Self::Unspecified,
965            1 => Self::Manual,
966            2 => Self::ProprietaryRemote,
967            3 => Self::Keypad,
968            4 => Self::Auto,
969            5 => Self::Button,
970            6 => Self::Schedule,
971            7 => Self::Remote,
972            8 => Self::Rfid,
973            9 => Self::Biometric,
974            10 => Self::Aliro,
975            other => Self::Unknown(other),
976        }
977    }
978    /// The raw discriminant.
979    #[must_use]
980    pub fn to_raw(self) -> u8 {
981        match self {
982            Self::Unspecified => 0,
983            Self::Manual => 1,
984            Self::ProprietaryRemote => 2,
985            Self::Keypad => 3,
986            Self::Auto => 4,
987            Self::Button => 5,
988            Self::Schedule => 6,
989            Self::Remote => 7,
990            Self::Rfid => 8,
991            Self::Biometric => 9,
992            Self::Aliro => 10,
993            Self::Unknown(v) => v,
994        }
995    }
996}
997
998/// `SoundVolumeEnum` (enum8).
999#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1000pub enum SoundVolumeEnum {
1001    /// Silent = 0.
1002    Silent,
1003    /// Low = 1.
1004    Low,
1005    /// High = 2.
1006    High,
1007    /// Medium = 3.
1008    Medium,
1009    /// A value not known to this codegen revision.
1010    Unknown(u8),
1011}
1012
1013impl SoundVolumeEnum {
1014    /// Decode from its raw discriminant (unknown → `Unknown`).
1015    #[must_use]
1016    pub fn from_raw(v: u8) -> Self {
1017        match v {
1018            0 => Self::Silent,
1019            1 => Self::Low,
1020            2 => Self::High,
1021            3 => Self::Medium,
1022            other => Self::Unknown(other),
1023        }
1024    }
1025    /// The raw discriminant.
1026    #[must_use]
1027    pub fn to_raw(self) -> u8 {
1028        match self {
1029            Self::Silent => 0,
1030            Self::Low => 1,
1031            Self::High => 2,
1032            Self::Medium => 3,
1033            Self::Unknown(v) => v,
1034        }
1035    }
1036}
1037
1038/// `StatusCodeEnum` (enum8).
1039#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1040pub enum StatusCodeEnum {
1041    /// Duplicate = 2.
1042    Duplicate,
1043    /// Occupied = 3.
1044    Occupied,
1045    /// A value not known to this codegen revision.
1046    Unknown(u8),
1047}
1048
1049impl StatusCodeEnum {
1050    /// Decode from its raw discriminant (unknown → `Unknown`).
1051    #[must_use]
1052    pub fn from_raw(v: u8) -> Self {
1053        match v {
1054            2 => Self::Duplicate,
1055            3 => Self::Occupied,
1056            other => Self::Unknown(other),
1057        }
1058    }
1059    /// The raw discriminant.
1060    #[must_use]
1061    pub fn to_raw(self) -> u8 {
1062        match self {
1063            Self::Duplicate => 2,
1064            Self::Occupied => 3,
1065            Self::Unknown(v) => v,
1066        }
1067    }
1068}
1069
1070/// `UserStatusEnum` (enum8).
1071#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1072pub enum UserStatusEnum {
1073    /// Available = 0.
1074    Available,
1075    /// OccupiedEnabled = 1.
1076    OccupiedEnabled,
1077    /// OccupiedDisabled = 3.
1078    OccupiedDisabled,
1079    /// A value not known to this codegen revision.
1080    Unknown(u8),
1081}
1082
1083impl UserStatusEnum {
1084    /// Decode from its raw discriminant (unknown → `Unknown`).
1085    #[must_use]
1086    pub fn from_raw(v: u8) -> Self {
1087        match v {
1088            0 => Self::Available,
1089            1 => Self::OccupiedEnabled,
1090            3 => Self::OccupiedDisabled,
1091            other => Self::Unknown(other),
1092        }
1093    }
1094    /// The raw discriminant.
1095    #[must_use]
1096    pub fn to_raw(self) -> u8 {
1097        match self {
1098            Self::Available => 0,
1099            Self::OccupiedEnabled => 1,
1100            Self::OccupiedDisabled => 3,
1101            Self::Unknown(v) => v,
1102        }
1103    }
1104}
1105
1106/// `UserTypeEnum` (enum8).
1107#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1108pub enum UserTypeEnum {
1109    /// UnrestrictedUser = 0.
1110    UnrestrictedUser,
1111    /// YearDayScheduleUser = 1.
1112    YearDayScheduleUser,
1113    /// WeekDayScheduleUser = 2.
1114    WeekDayScheduleUser,
1115    /// ProgrammingUser = 3.
1116    ProgrammingUser,
1117    /// NonAccessUser = 4.
1118    NonAccessUser,
1119    /// ForcedUser = 5.
1120    ForcedUser,
1121    /// DisposableUser = 6.
1122    DisposableUser,
1123    /// ExpiringUser = 7.
1124    ExpiringUser,
1125    /// ScheduleRestrictedUser = 8.
1126    ScheduleRestrictedUser,
1127    /// RemoteOnlyUser = 9.
1128    RemoteOnlyUser,
1129    /// A value not known to this codegen revision.
1130    Unknown(u8),
1131}
1132
1133impl UserTypeEnum {
1134    /// Decode from its raw discriminant (unknown → `Unknown`).
1135    #[must_use]
1136    pub fn from_raw(v: u8) -> Self {
1137        match v {
1138            0 => Self::UnrestrictedUser,
1139            1 => Self::YearDayScheduleUser,
1140            2 => Self::WeekDayScheduleUser,
1141            3 => Self::ProgrammingUser,
1142            4 => Self::NonAccessUser,
1143            5 => Self::ForcedUser,
1144            6 => Self::DisposableUser,
1145            7 => Self::ExpiringUser,
1146            8 => Self::ScheduleRestrictedUser,
1147            9 => Self::RemoteOnlyUser,
1148            other => Self::Unknown(other),
1149        }
1150    }
1151    /// The raw discriminant.
1152    #[must_use]
1153    pub fn to_raw(self) -> u8 {
1154        match self {
1155            Self::UnrestrictedUser => 0,
1156            Self::YearDayScheduleUser => 1,
1157            Self::WeekDayScheduleUser => 2,
1158            Self::ProgrammingUser => 3,
1159            Self::NonAccessUser => 4,
1160            Self::ForcedUser => 5,
1161            Self::DisposableUser => 6,
1162            Self::ExpiringUser => 7,
1163            Self::ScheduleRestrictedUser => 8,
1164            Self::RemoteOnlyUser => 9,
1165            Self::Unknown(v) => v,
1166        }
1167    }
1168}
1169
1170impl CredentialStruct {
1171    /// Decode the fields of an already-opened anonymous structure
1172    /// (reader positioned after the struct start; consumes to its end).
1173    ///
1174    /// # Errors
1175    /// Returns [`ClusterError`] on a malformed structure or missing required field.
1176    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
1177        let mut f_credential_type: Option<CredentialTypeEnum> = None;
1178        let mut f_credential_index: Option<u16> = None;
1179        loop {
1180            match r.next()? {
1181                Some(Element::ContainerEnd) => break,
1182                Some(Element::Scalar {
1183                    tag: Tag::Context(0),
1184                    value: Value::Uint(v),
1185                }) => {
1186                    f_credential_type = Some(CredentialTypeEnum::from_raw(
1187                        u8::try_from(v)
1188                            .map_err(|_| ClusterError::InvalidLength("CredentialType"))?,
1189                    ))
1190                }
1191                Some(Element::Scalar {
1192                    tag: Tag::Context(1),
1193                    value: Value::Uint(v),
1194                }) => {
1195                    f_credential_index = Some(
1196                        u16::try_from(v)
1197                            .map_err(|_| ClusterError::InvalidLength("CredentialIndex"))?,
1198                    )
1199                }
1200                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
1201                Some(Element::ContainerStart { .. }) => r.skip_container()?,
1202                Some(_) => {} // unknown/future scalar — skip
1203            }
1204        }
1205        Ok(Self {
1206            credential_type: f_credential_type
1207                .ok_or(ClusterError::MissingField("CredentialType"))?,
1208            credential_index: f_credential_index
1209                .ok_or(ClusterError::MissingField("CredentialIndex"))?,
1210        })
1211    }
1212    /// Decode from a standalone anonymous TLV structure.
1213    ///
1214    /// # Errors
1215    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
1216    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
1217        let mut r = TlvReader::new(tlv);
1218        match r.next()? {
1219            Some(Element::ContainerStart {
1220                kind: ContainerKind::Structure,
1221                ..
1222            }) => {}
1223            _ => {
1224                return Err(ClusterError::UnexpectedType {
1225                    context: "CredentialStruct",
1226                })
1227            }
1228        }
1229        Self::decode_from(&mut r)
1230    }
1231    /// Write this struct's fields into an already-open container.
1232    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
1233    pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
1234        w.put_uint(Tag::Context(0), u64::from(self.credential_type.to_raw()))
1235            .expect("infallible: vec writer");
1236        w.put_uint(Tag::Context(1), u64::from(self.credential_index))
1237            .expect("infallible: vec writer");
1238    }
1239    /// Encode as a standalone anonymous TLV structure.
1240    #[must_use]
1241    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
1242    pub fn encode(&self) -> Vec<u8> {
1243        let mut buf = Vec::new();
1244        let mut w = TlvWriter::new(&mut buf);
1245        w.start_structure(Tag::Anonymous)
1246            .expect("infallible: vec writer");
1247        self.write_fields(&mut w);
1248        w.end_container().expect("infallible: vec writer");
1249        buf
1250    }
1251}
1252
1253/// Decode the `LockState` attribute value.
1254///
1255/// # Errors
1256/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1257pub fn decode_lock_state(tlv: &[u8]) -> Result<Nullable<LockStateEnum>, ClusterError> {
1258    let mut r = TlvReader::new(tlv);
1259    match r.next()? {
1260        Some(Element::Scalar {
1261            value: Value::Null, ..
1262        }) => Ok(Nullable::Null),
1263        Some(Element::Scalar {
1264            value: Value::Uint(v),
1265            ..
1266        }) => Ok(Nullable::Value(LockStateEnum::from_raw(
1267            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("LockState"))?,
1268        ))),
1269        _ => Err(ClusterError::UnexpectedType {
1270            context: "LockState",
1271        }),
1272    }
1273}
1274
1275/// Decode the `LockType` attribute value.
1276///
1277/// # Errors
1278/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1279pub fn decode_lock_type(tlv: &[u8]) -> Result<LockTypeEnum, ClusterError> {
1280    let mut r = TlvReader::new(tlv);
1281    match r.next()? {
1282        Some(Element::Scalar {
1283            value: Value::Uint(v),
1284            ..
1285        }) => Ok(LockTypeEnum::from_raw(
1286            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("LockType"))?,
1287        )),
1288        _ => Err(ClusterError::UnexpectedType {
1289            context: "LockType",
1290        }),
1291    }
1292}
1293
1294/// Decode the `ActuatorEnabled` attribute value.
1295///
1296/// # Errors
1297/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1298pub fn decode_actuator_enabled(tlv: &[u8]) -> Result<bool, ClusterError> {
1299    let mut r = TlvReader::new(tlv);
1300    match r.next()? {
1301        Some(Element::Scalar {
1302            value: Value::Bool(v),
1303            ..
1304        }) => Ok(v),
1305        _ => Err(ClusterError::UnexpectedType {
1306            context: "ActuatorEnabled",
1307        }),
1308    }
1309}
1310
1311/// Decode the `DoorState` attribute value.
1312///
1313/// # Errors
1314/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1315pub fn decode_door_state(tlv: &[u8]) -> Result<Nullable<DoorStateEnum>, ClusterError> {
1316    let mut r = TlvReader::new(tlv);
1317    match r.next()? {
1318        Some(Element::Scalar {
1319            value: Value::Null, ..
1320        }) => Ok(Nullable::Null),
1321        Some(Element::Scalar {
1322            value: Value::Uint(v),
1323            ..
1324        }) => Ok(Nullable::Value(DoorStateEnum::from_raw(
1325            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("DoorState"))?,
1326        ))),
1327        _ => Err(ClusterError::UnexpectedType {
1328            context: "DoorState",
1329        }),
1330    }
1331}
1332
1333/// Decode the `DoorOpenEvents` attribute value.
1334///
1335/// # Errors
1336/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1337pub fn decode_door_open_events(tlv: &[u8]) -> Result<u32, ClusterError> {
1338    let mut r = TlvReader::new(tlv);
1339    match r.next()? {
1340        Some(Element::Scalar {
1341            value: Value::Uint(v),
1342            ..
1343        }) => Ok(u32::try_from(v).map_err(|_| ClusterError::InvalidLength("DoorOpenEvents"))?),
1344        _ => Err(ClusterError::UnexpectedType {
1345            context: "DoorOpenEvents",
1346        }),
1347    }
1348}
1349
1350/// Encode the `DoorOpenEvents` attribute value as a standalone TLV element.
1351#[must_use]
1352#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1353pub fn encode_door_open_events(value: u32) -> Vec<u8> {
1354    let mut buf = Vec::new();
1355    let mut w = TlvWriter::new(&mut buf);
1356    w.put_uint(Tag::Anonymous, u64::from(value))
1357        .expect("infallible: vec writer");
1358    buf
1359}
1360
1361/// Decode the `DoorClosedEvents` attribute value.
1362///
1363/// # Errors
1364/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1365pub fn decode_door_closed_events(tlv: &[u8]) -> Result<u32, ClusterError> {
1366    let mut r = TlvReader::new(tlv);
1367    match r.next()? {
1368        Some(Element::Scalar {
1369            value: Value::Uint(v),
1370            ..
1371        }) => Ok(u32::try_from(v).map_err(|_| ClusterError::InvalidLength("DoorClosedEvents"))?),
1372        _ => Err(ClusterError::UnexpectedType {
1373            context: "DoorClosedEvents",
1374        }),
1375    }
1376}
1377
1378/// Encode the `DoorClosedEvents` attribute value as a standalone TLV element.
1379#[must_use]
1380#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1381pub fn encode_door_closed_events(value: u32) -> Vec<u8> {
1382    let mut buf = Vec::new();
1383    let mut w = TlvWriter::new(&mut buf);
1384    w.put_uint(Tag::Anonymous, u64::from(value))
1385        .expect("infallible: vec writer");
1386    buf
1387}
1388
1389/// Decode the `OpenPeriod` attribute value.
1390///
1391/// # Errors
1392/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1393pub fn decode_open_period(tlv: &[u8]) -> Result<u16, ClusterError> {
1394    let mut r = TlvReader::new(tlv);
1395    match r.next()? {
1396        Some(Element::Scalar {
1397            value: Value::Uint(v),
1398            ..
1399        }) => Ok(u16::try_from(v).map_err(|_| ClusterError::InvalidLength("OpenPeriod"))?),
1400        _ => Err(ClusterError::UnexpectedType {
1401            context: "OpenPeriod",
1402        }),
1403    }
1404}
1405
1406/// Encode the `OpenPeriod` attribute value as a standalone TLV element.
1407#[must_use]
1408#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1409pub fn encode_open_period(value: u16) -> Vec<u8> {
1410    let mut buf = Vec::new();
1411    let mut w = TlvWriter::new(&mut buf);
1412    w.put_uint(Tag::Anonymous, u64::from(value))
1413        .expect("infallible: vec writer");
1414    buf
1415}
1416
1417/// Decode the `NumberOfTotalUsersSupported` attribute value.
1418///
1419/// # Errors
1420/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1421pub fn decode_number_of_total_users_supported(tlv: &[u8]) -> Result<u16, ClusterError> {
1422    let mut r = TlvReader::new(tlv);
1423    match r.next()? {
1424        Some(Element::Scalar {
1425            value: Value::Uint(v),
1426            ..
1427        }) => Ok(u16::try_from(v)
1428            .map_err(|_| ClusterError::InvalidLength("NumberOfTotalUsersSupported"))?),
1429        _ => Err(ClusterError::UnexpectedType {
1430            context: "NumberOfTotalUsersSupported",
1431        }),
1432    }
1433}
1434
1435/// Decode the `NumberOfPinUsersSupported` attribute value.
1436///
1437/// # Errors
1438/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1439pub fn decode_number_of_pin_users_supported(tlv: &[u8]) -> Result<u16, ClusterError> {
1440    let mut r = TlvReader::new(tlv);
1441    match r.next()? {
1442        Some(Element::Scalar {
1443            value: Value::Uint(v),
1444            ..
1445        }) => Ok(u16::try_from(v)
1446            .map_err(|_| ClusterError::InvalidLength("NumberOfPinUsersSupported"))?),
1447        _ => Err(ClusterError::UnexpectedType {
1448            context: "NumberOfPinUsersSupported",
1449        }),
1450    }
1451}
1452
1453/// Decode the `NumberOfRfidUsersSupported` attribute value.
1454///
1455/// # Errors
1456/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1457pub fn decode_number_of_rfid_users_supported(tlv: &[u8]) -> Result<u16, ClusterError> {
1458    let mut r = TlvReader::new(tlv);
1459    match r.next()? {
1460        Some(Element::Scalar {
1461            value: Value::Uint(v),
1462            ..
1463        }) => Ok(u16::try_from(v)
1464            .map_err(|_| ClusterError::InvalidLength("NumberOfRfidUsersSupported"))?),
1465        _ => Err(ClusterError::UnexpectedType {
1466            context: "NumberOfRfidUsersSupported",
1467        }),
1468    }
1469}
1470
1471/// Decode the `NumberOfWeekDaySchedulesSupportedPerUser` attribute value.
1472///
1473/// # Errors
1474/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1475pub fn decode_number_of_week_day_schedules_supported_per_user(
1476    tlv: &[u8],
1477) -> Result<u8, ClusterError> {
1478    let mut r = TlvReader::new(tlv);
1479    match r.next()? {
1480        Some(Element::Scalar {
1481            value: Value::Uint(v),
1482            ..
1483        }) => Ok(u8::try_from(v).map_err(|_| {
1484            ClusterError::InvalidLength("NumberOfWeekDaySchedulesSupportedPerUser")
1485        })?),
1486        _ => Err(ClusterError::UnexpectedType {
1487            context: "NumberOfWeekDaySchedulesSupportedPerUser",
1488        }),
1489    }
1490}
1491
1492/// Decode the `NumberOfYearDaySchedulesSupportedPerUser` attribute value.
1493///
1494/// # Errors
1495/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1496pub fn decode_number_of_year_day_schedules_supported_per_user(
1497    tlv: &[u8],
1498) -> Result<u8, ClusterError> {
1499    let mut r = TlvReader::new(tlv);
1500    match r.next()? {
1501        Some(Element::Scalar {
1502            value: Value::Uint(v),
1503            ..
1504        }) => Ok(u8::try_from(v).map_err(|_| {
1505            ClusterError::InvalidLength("NumberOfYearDaySchedulesSupportedPerUser")
1506        })?),
1507        _ => Err(ClusterError::UnexpectedType {
1508            context: "NumberOfYearDaySchedulesSupportedPerUser",
1509        }),
1510    }
1511}
1512
1513/// Decode the `NumberOfHolidaySchedulesSupported` attribute value.
1514///
1515/// # Errors
1516/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1517pub fn decode_number_of_holiday_schedules_supported(tlv: &[u8]) -> Result<u8, ClusterError> {
1518    let mut r = TlvReader::new(tlv);
1519    match r.next()? {
1520        Some(Element::Scalar {
1521            value: Value::Uint(v),
1522            ..
1523        }) => Ok(u8::try_from(v)
1524            .map_err(|_| ClusterError::InvalidLength("NumberOfHolidaySchedulesSupported"))?),
1525        _ => Err(ClusterError::UnexpectedType {
1526            context: "NumberOfHolidaySchedulesSupported",
1527        }),
1528    }
1529}
1530
1531/// Decode the `MaxPinCodeLength` attribute value.
1532///
1533/// # Errors
1534/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1535pub fn decode_max_pin_code_length(tlv: &[u8]) -> Result<u8, ClusterError> {
1536    let mut r = TlvReader::new(tlv);
1537    match r.next()? {
1538        Some(Element::Scalar {
1539            value: Value::Uint(v),
1540            ..
1541        }) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("MaxPinCodeLength"))?),
1542        _ => Err(ClusterError::UnexpectedType {
1543            context: "MaxPinCodeLength",
1544        }),
1545    }
1546}
1547
1548/// Decode the `MinPinCodeLength` attribute value.
1549///
1550/// # Errors
1551/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1552pub fn decode_min_pin_code_length(tlv: &[u8]) -> Result<u8, ClusterError> {
1553    let mut r = TlvReader::new(tlv);
1554    match r.next()? {
1555        Some(Element::Scalar {
1556            value: Value::Uint(v),
1557            ..
1558        }) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("MinPinCodeLength"))?),
1559        _ => Err(ClusterError::UnexpectedType {
1560            context: "MinPinCodeLength",
1561        }),
1562    }
1563}
1564
1565/// Decode the `MaxRfidCodeLength` attribute value.
1566///
1567/// # Errors
1568/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1569pub fn decode_max_rfid_code_length(tlv: &[u8]) -> Result<u8, ClusterError> {
1570    let mut r = TlvReader::new(tlv);
1571    match r.next()? {
1572        Some(Element::Scalar {
1573            value: Value::Uint(v),
1574            ..
1575        }) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("MaxRfidCodeLength"))?),
1576        _ => Err(ClusterError::UnexpectedType {
1577            context: "MaxRfidCodeLength",
1578        }),
1579    }
1580}
1581
1582/// Decode the `MinRfidCodeLength` attribute value.
1583///
1584/// # Errors
1585/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1586pub fn decode_min_rfid_code_length(tlv: &[u8]) -> Result<u8, ClusterError> {
1587    let mut r = TlvReader::new(tlv);
1588    match r.next()? {
1589        Some(Element::Scalar {
1590            value: Value::Uint(v),
1591            ..
1592        }) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("MinRfidCodeLength"))?),
1593        _ => Err(ClusterError::UnexpectedType {
1594            context: "MinRfidCodeLength",
1595        }),
1596    }
1597}
1598
1599/// Decode the `CredentialRulesSupport` attribute value.
1600///
1601/// # Errors
1602/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1603pub fn decode_credential_rules_support(tlv: &[u8]) -> Result<CredentialRulesBitmap, ClusterError> {
1604    let mut r = TlvReader::new(tlv);
1605    match r.next()? {
1606        Some(Element::Scalar {
1607            value: Value::Uint(v),
1608            ..
1609        }) => Ok(CredentialRulesBitmap::from_bits_retain(
1610            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("CredentialRulesSupport"))?,
1611        )),
1612        _ => Err(ClusterError::UnexpectedType {
1613            context: "CredentialRulesSupport",
1614        }),
1615    }
1616}
1617
1618/// Decode the `NumberOfCredentialsSupportedPerUser` attribute value.
1619///
1620/// # Errors
1621/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1622pub fn decode_number_of_credentials_supported_per_user(tlv: &[u8]) -> Result<u8, ClusterError> {
1623    let mut r = TlvReader::new(tlv);
1624    match r.next()? {
1625        Some(Element::Scalar {
1626            value: Value::Uint(v),
1627            ..
1628        }) => Ok(u8::try_from(v)
1629            .map_err(|_| ClusterError::InvalidLength("NumberOfCredentialsSupportedPerUser"))?),
1630        _ => Err(ClusterError::UnexpectedType {
1631            context: "NumberOfCredentialsSupportedPerUser",
1632        }),
1633    }
1634}
1635
1636/// Decode the `Language` attribute value.
1637///
1638/// # Errors
1639/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1640pub fn decode_language(tlv: &[u8]) -> Result<String, ClusterError> {
1641    let mut r = TlvReader::new(tlv);
1642    match r.next()? {
1643        Some(Element::Scalar {
1644            value: Value::Utf8(v),
1645            ..
1646        }) => Ok(v),
1647        _ => Err(ClusterError::UnexpectedType {
1648            context: "Language",
1649        }),
1650    }
1651}
1652
1653/// Encode the `Language` attribute value as a standalone TLV element.
1654#[must_use]
1655#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1656pub fn encode_language(value: &String) -> Vec<u8> {
1657    let mut buf = Vec::new();
1658    let mut w = TlvWriter::new(&mut buf);
1659    w.put_utf8(Tag::Anonymous, &value)
1660        .expect("infallible: vec writer");
1661    buf
1662}
1663
1664/// Decode the `LedSettings` attribute value.
1665///
1666/// # Errors
1667/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1668pub fn decode_led_settings(tlv: &[u8]) -> Result<LEDSettingEnum, ClusterError> {
1669    let mut r = TlvReader::new(tlv);
1670    match r.next()? {
1671        Some(Element::Scalar {
1672            value: Value::Uint(v),
1673            ..
1674        }) => Ok(LEDSettingEnum::from_raw(
1675            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("LedSettings"))?,
1676        )),
1677        _ => Err(ClusterError::UnexpectedType {
1678            context: "LedSettings",
1679        }),
1680    }
1681}
1682
1683/// Encode the `LedSettings` attribute value as a standalone TLV element.
1684#[must_use]
1685#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1686pub fn encode_led_settings(value: LEDSettingEnum) -> Vec<u8> {
1687    let mut buf = Vec::new();
1688    let mut w = TlvWriter::new(&mut buf);
1689    w.put_uint(Tag::Anonymous, u64::from(value.to_raw()))
1690        .expect("infallible: vec writer");
1691    buf
1692}
1693
1694/// Decode the `AutoRelockTime` attribute value.
1695///
1696/// # Errors
1697/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1698pub fn decode_auto_relock_time(tlv: &[u8]) -> Result<u32, ClusterError> {
1699    let mut r = TlvReader::new(tlv);
1700    match r.next()? {
1701        Some(Element::Scalar {
1702            value: Value::Uint(v),
1703            ..
1704        }) => Ok(u32::try_from(v).map_err(|_| ClusterError::InvalidLength("AutoRelockTime"))?),
1705        _ => Err(ClusterError::UnexpectedType {
1706            context: "AutoRelockTime",
1707        }),
1708    }
1709}
1710
1711/// Encode the `AutoRelockTime` attribute value as a standalone TLV element.
1712#[must_use]
1713#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1714pub fn encode_auto_relock_time(value: u32) -> Vec<u8> {
1715    let mut buf = Vec::new();
1716    let mut w = TlvWriter::new(&mut buf);
1717    w.put_uint(Tag::Anonymous, u64::from(value))
1718        .expect("infallible: vec writer");
1719    buf
1720}
1721
1722/// Decode the `SoundVolume` attribute value.
1723///
1724/// # Errors
1725/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1726pub fn decode_sound_volume(tlv: &[u8]) -> Result<SoundVolumeEnum, ClusterError> {
1727    let mut r = TlvReader::new(tlv);
1728    match r.next()? {
1729        Some(Element::Scalar {
1730            value: Value::Uint(v),
1731            ..
1732        }) => Ok(SoundVolumeEnum::from_raw(
1733            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("SoundVolume"))?,
1734        )),
1735        _ => Err(ClusterError::UnexpectedType {
1736            context: "SoundVolume",
1737        }),
1738    }
1739}
1740
1741/// Encode the `SoundVolume` attribute value as a standalone TLV element.
1742#[must_use]
1743#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1744pub fn encode_sound_volume(value: SoundVolumeEnum) -> Vec<u8> {
1745    let mut buf = Vec::new();
1746    let mut w = TlvWriter::new(&mut buf);
1747    w.put_uint(Tag::Anonymous, u64::from(value.to_raw()))
1748        .expect("infallible: vec writer");
1749    buf
1750}
1751
1752/// Decode the `OperatingMode` attribute value.
1753///
1754/// # Errors
1755/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1756pub fn decode_operating_mode(tlv: &[u8]) -> Result<OperatingModeEnum, ClusterError> {
1757    let mut r = TlvReader::new(tlv);
1758    match r.next()? {
1759        Some(Element::Scalar {
1760            value: Value::Uint(v),
1761            ..
1762        }) => Ok(OperatingModeEnum::from_raw(
1763            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("OperatingMode"))?,
1764        )),
1765        _ => Err(ClusterError::UnexpectedType {
1766            context: "OperatingMode",
1767        }),
1768    }
1769}
1770
1771/// Encode the `OperatingMode` attribute value as a standalone TLV element.
1772#[must_use]
1773#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1774pub fn encode_operating_mode(value: OperatingModeEnum) -> Vec<u8> {
1775    let mut buf = Vec::new();
1776    let mut w = TlvWriter::new(&mut buf);
1777    w.put_uint(Tag::Anonymous, u64::from(value.to_raw()))
1778        .expect("infallible: vec writer");
1779    buf
1780}
1781
1782/// Decode the `SupportedOperatingModes` attribute value.
1783///
1784/// # Errors
1785/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1786pub fn decode_supported_operating_modes(tlv: &[u8]) -> Result<OperatingModesBitmap, ClusterError> {
1787    let mut r = TlvReader::new(tlv);
1788    match r.next()? {
1789        Some(Element::Scalar {
1790            value: Value::Uint(v),
1791            ..
1792        }) => Ok(OperatingModesBitmap::from_bits_retain(
1793            u16::try_from(v).map_err(|_| ClusterError::InvalidLength("SupportedOperatingModes"))?,
1794        )),
1795        _ => Err(ClusterError::UnexpectedType {
1796            context: "SupportedOperatingModes",
1797        }),
1798    }
1799}
1800
1801/// Decode the `DefaultConfigurationRegister` attribute value.
1802///
1803/// # Errors
1804/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1805pub fn decode_default_configuration_register(
1806    tlv: &[u8],
1807) -> Result<ConfigurationRegisterBitmap, ClusterError> {
1808    let mut r = TlvReader::new(tlv);
1809    match r.next()? {
1810        Some(Element::Scalar {
1811            value: Value::Uint(v),
1812            ..
1813        }) => Ok(ConfigurationRegisterBitmap::from_bits_retain(
1814            u16::try_from(v)
1815                .map_err(|_| ClusterError::InvalidLength("DefaultConfigurationRegister"))?,
1816        )),
1817        _ => Err(ClusterError::UnexpectedType {
1818            context: "DefaultConfigurationRegister",
1819        }),
1820    }
1821}
1822
1823/// Decode the `EnableLocalProgramming` attribute value.
1824///
1825/// # Errors
1826/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1827pub fn decode_enable_local_programming(tlv: &[u8]) -> Result<bool, ClusterError> {
1828    let mut r = TlvReader::new(tlv);
1829    match r.next()? {
1830        Some(Element::Scalar {
1831            value: Value::Bool(v),
1832            ..
1833        }) => Ok(v),
1834        _ => Err(ClusterError::UnexpectedType {
1835            context: "EnableLocalProgramming",
1836        }),
1837    }
1838}
1839
1840/// Encode the `EnableLocalProgramming` attribute value as a standalone TLV element.
1841#[must_use]
1842#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1843pub fn encode_enable_local_programming(value: bool) -> Vec<u8> {
1844    let mut buf = Vec::new();
1845    let mut w = TlvWriter::new(&mut buf);
1846    w.put_bool(Tag::Anonymous, value)
1847        .expect("infallible: vec writer");
1848    buf
1849}
1850
1851/// Decode the `EnableOneTouchLocking` attribute value.
1852///
1853/// # Errors
1854/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1855pub fn decode_enable_one_touch_locking(tlv: &[u8]) -> Result<bool, ClusterError> {
1856    let mut r = TlvReader::new(tlv);
1857    match r.next()? {
1858        Some(Element::Scalar {
1859            value: Value::Bool(v),
1860            ..
1861        }) => Ok(v),
1862        _ => Err(ClusterError::UnexpectedType {
1863            context: "EnableOneTouchLocking",
1864        }),
1865    }
1866}
1867
1868/// Encode the `EnableOneTouchLocking` attribute value as a standalone TLV element.
1869#[must_use]
1870#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1871pub fn encode_enable_one_touch_locking(value: bool) -> Vec<u8> {
1872    let mut buf = Vec::new();
1873    let mut w = TlvWriter::new(&mut buf);
1874    w.put_bool(Tag::Anonymous, value)
1875        .expect("infallible: vec writer");
1876    buf
1877}
1878
1879/// Decode the `EnableInsideStatusLed` attribute value.
1880///
1881/// # Errors
1882/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1883pub fn decode_enable_inside_status_led(tlv: &[u8]) -> Result<bool, ClusterError> {
1884    let mut r = TlvReader::new(tlv);
1885    match r.next()? {
1886        Some(Element::Scalar {
1887            value: Value::Bool(v),
1888            ..
1889        }) => Ok(v),
1890        _ => Err(ClusterError::UnexpectedType {
1891            context: "EnableInsideStatusLed",
1892        }),
1893    }
1894}
1895
1896/// Encode the `EnableInsideStatusLed` attribute value as a standalone TLV element.
1897#[must_use]
1898#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1899pub fn encode_enable_inside_status_led(value: bool) -> Vec<u8> {
1900    let mut buf = Vec::new();
1901    let mut w = TlvWriter::new(&mut buf);
1902    w.put_bool(Tag::Anonymous, value)
1903        .expect("infallible: vec writer");
1904    buf
1905}
1906
1907/// Decode the `EnablePrivacyModeButton` attribute value.
1908///
1909/// # Errors
1910/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1911pub fn decode_enable_privacy_mode_button(tlv: &[u8]) -> Result<bool, ClusterError> {
1912    let mut r = TlvReader::new(tlv);
1913    match r.next()? {
1914        Some(Element::Scalar {
1915            value: Value::Bool(v),
1916            ..
1917        }) => Ok(v),
1918        _ => Err(ClusterError::UnexpectedType {
1919            context: "EnablePrivacyModeButton",
1920        }),
1921    }
1922}
1923
1924/// Encode the `EnablePrivacyModeButton` attribute value as a standalone TLV element.
1925#[must_use]
1926#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1927pub fn encode_enable_privacy_mode_button(value: bool) -> Vec<u8> {
1928    let mut buf = Vec::new();
1929    let mut w = TlvWriter::new(&mut buf);
1930    w.put_bool(Tag::Anonymous, value)
1931        .expect("infallible: vec writer");
1932    buf
1933}
1934
1935/// Decode the `LocalProgrammingFeatures` attribute value.
1936///
1937/// # Errors
1938/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1939pub fn decode_local_programming_features(
1940    tlv: &[u8],
1941) -> Result<LocalProgrammingFeaturesBitmap, ClusterError> {
1942    let mut r = TlvReader::new(tlv);
1943    match r.next()? {
1944        Some(Element::Scalar {
1945            value: Value::Uint(v),
1946            ..
1947        }) => Ok(LocalProgrammingFeaturesBitmap::from_bits_retain(
1948            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("LocalProgrammingFeatures"))?,
1949        )),
1950        _ => Err(ClusterError::UnexpectedType {
1951            context: "LocalProgrammingFeatures",
1952        }),
1953    }
1954}
1955
1956/// Encode the `LocalProgrammingFeatures` attribute value as a standalone TLV element.
1957#[must_use]
1958#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1959pub fn encode_local_programming_features(value: LocalProgrammingFeaturesBitmap) -> Vec<u8> {
1960    let mut buf = Vec::new();
1961    let mut w = TlvWriter::new(&mut buf);
1962    w.put_uint(Tag::Anonymous, u64::from(value.bits()))
1963        .expect("infallible: vec writer");
1964    buf
1965}
1966
1967/// Decode the `WrongCodeEntryLimit` attribute value.
1968///
1969/// # Errors
1970/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1971pub fn decode_wrong_code_entry_limit(tlv: &[u8]) -> Result<u8, ClusterError> {
1972    let mut r = TlvReader::new(tlv);
1973    match r.next()? {
1974        Some(Element::Scalar {
1975            value: Value::Uint(v),
1976            ..
1977        }) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("WrongCodeEntryLimit"))?),
1978        _ => Err(ClusterError::UnexpectedType {
1979            context: "WrongCodeEntryLimit",
1980        }),
1981    }
1982}
1983
1984/// Encode the `WrongCodeEntryLimit` attribute value as a standalone TLV element.
1985#[must_use]
1986#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1987pub fn encode_wrong_code_entry_limit(value: u8) -> Vec<u8> {
1988    let mut buf = Vec::new();
1989    let mut w = TlvWriter::new(&mut buf);
1990    w.put_uint(Tag::Anonymous, u64::from(value))
1991        .expect("infallible: vec writer");
1992    buf
1993}
1994
1995/// Decode the `UserCodeTemporaryDisableTime` attribute value.
1996///
1997/// # Errors
1998/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1999pub fn decode_user_code_temporary_disable_time(tlv: &[u8]) -> Result<u8, ClusterError> {
2000    let mut r = TlvReader::new(tlv);
2001    match r.next()? {
2002        Some(Element::Scalar {
2003            value: Value::Uint(v),
2004            ..
2005        }) => Ok(u8::try_from(v)
2006            .map_err(|_| ClusterError::InvalidLength("UserCodeTemporaryDisableTime"))?),
2007        _ => Err(ClusterError::UnexpectedType {
2008            context: "UserCodeTemporaryDisableTime",
2009        }),
2010    }
2011}
2012
2013/// Encode the `UserCodeTemporaryDisableTime` attribute value as a standalone TLV element.
2014#[must_use]
2015#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2016pub fn encode_user_code_temporary_disable_time(value: u8) -> Vec<u8> {
2017    let mut buf = Vec::new();
2018    let mut w = TlvWriter::new(&mut buf);
2019    w.put_uint(Tag::Anonymous, u64::from(value))
2020        .expect("infallible: vec writer");
2021    buf
2022}
2023
2024/// Decode the `SendPinOverTheAir` attribute value.
2025///
2026/// # Errors
2027/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2028pub fn decode_send_pin_over_the_air(tlv: &[u8]) -> Result<bool, ClusterError> {
2029    let mut r = TlvReader::new(tlv);
2030    match r.next()? {
2031        Some(Element::Scalar {
2032            value: Value::Bool(v),
2033            ..
2034        }) => Ok(v),
2035        _ => Err(ClusterError::UnexpectedType {
2036            context: "SendPinOverTheAir",
2037        }),
2038    }
2039}
2040
2041/// Encode the `SendPinOverTheAir` attribute value as a standalone TLV element.
2042#[must_use]
2043#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2044pub fn encode_send_pin_over_the_air(value: bool) -> Vec<u8> {
2045    let mut buf = Vec::new();
2046    let mut w = TlvWriter::new(&mut buf);
2047    w.put_bool(Tag::Anonymous, value)
2048        .expect("infallible: vec writer");
2049    buf
2050}
2051
2052/// Decode the `RequirePinForRemoteOperation` attribute value.
2053///
2054/// # Errors
2055/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2056pub fn decode_require_pin_for_remote_operation(tlv: &[u8]) -> Result<bool, ClusterError> {
2057    let mut r = TlvReader::new(tlv);
2058    match r.next()? {
2059        Some(Element::Scalar {
2060            value: Value::Bool(v),
2061            ..
2062        }) => Ok(v),
2063        _ => Err(ClusterError::UnexpectedType {
2064            context: "RequirePinForRemoteOperation",
2065        }),
2066    }
2067}
2068
2069/// Encode the `RequirePinForRemoteOperation` attribute value as a standalone TLV element.
2070#[must_use]
2071#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2072pub fn encode_require_pin_for_remote_operation(value: bool) -> Vec<u8> {
2073    let mut buf = Vec::new();
2074    let mut w = TlvWriter::new(&mut buf);
2075    w.put_bool(Tag::Anonymous, value)
2076        .expect("infallible: vec writer");
2077    buf
2078}
2079
2080/// Decode the `ExpiringUserTimeout` attribute value.
2081///
2082/// # Errors
2083/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2084pub fn decode_expiring_user_timeout(tlv: &[u8]) -> Result<u16, ClusterError> {
2085    let mut r = TlvReader::new(tlv);
2086    match r.next()? {
2087        Some(Element::Scalar {
2088            value: Value::Uint(v),
2089            ..
2090        }) => Ok(u16::try_from(v).map_err(|_| ClusterError::InvalidLength("ExpiringUserTimeout"))?),
2091        _ => Err(ClusterError::UnexpectedType {
2092            context: "ExpiringUserTimeout",
2093        }),
2094    }
2095}
2096
2097/// Encode the `ExpiringUserTimeout` attribute value as a standalone TLV element.
2098#[must_use]
2099#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2100pub fn encode_expiring_user_timeout(value: u16) -> Vec<u8> {
2101    let mut buf = Vec::new();
2102    let mut w = TlvWriter::new(&mut buf);
2103    w.put_uint(Tag::Anonymous, u64::from(value))
2104        .expect("infallible: vec writer");
2105    buf
2106}
2107
2108/// Encode the `LockDoor` command request payload.
2109#[must_use]
2110#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2111pub fn encode_lock_door(pin_code: Option<Vec<u8>>) -> Vec<u8> {
2112    let mut buf = Vec::new();
2113    let mut w = TlvWriter::new(&mut buf);
2114    w.start_structure(Tag::Anonymous)
2115        .expect("infallible: vec writer");
2116    if let Some(pin_code) = pin_code {
2117        w.put_bytes(Tag::Context(0), &pin_code)
2118            .expect("infallible: vec writer");
2119    }
2120    w.end_container().expect("infallible: vec writer");
2121    buf
2122}
2123
2124/// Encode the `UnlockDoor` command request payload.
2125#[must_use]
2126#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2127pub fn encode_unlock_door(pin_code: Option<Vec<u8>>) -> Vec<u8> {
2128    let mut buf = Vec::new();
2129    let mut w = TlvWriter::new(&mut buf);
2130    w.start_structure(Tag::Anonymous)
2131        .expect("infallible: vec writer");
2132    if let Some(pin_code) = pin_code {
2133        w.put_bytes(Tag::Context(0), &pin_code)
2134            .expect("infallible: vec writer");
2135    }
2136    w.end_container().expect("infallible: vec writer");
2137    buf
2138}
2139
2140/// Encode the `UnlockWithTimeout` command request payload.
2141#[must_use]
2142#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2143pub fn encode_unlock_with_timeout(timeout: u16, pin_code: Option<Vec<u8>>) -> Vec<u8> {
2144    let mut buf = Vec::new();
2145    let mut w = TlvWriter::new(&mut buf);
2146    w.start_structure(Tag::Anonymous)
2147        .expect("infallible: vec writer");
2148    w.put_uint(Tag::Context(0), u64::from(timeout))
2149        .expect("infallible: vec writer");
2150    if let Some(pin_code) = pin_code {
2151        w.put_bytes(Tag::Context(1), &pin_code)
2152            .expect("infallible: vec writer");
2153    }
2154    w.end_container().expect("infallible: vec writer");
2155    buf
2156}
2157
2158/// Encode the `SetWeekDaySchedule` command request payload.
2159#[must_use]
2160#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2161pub fn encode_set_week_day_schedule(
2162    week_day_index: u8,
2163    user_index: u16,
2164    days_mask: DaysMaskBitmap,
2165    start_hour: u8,
2166    start_minute: u8,
2167    end_hour: u8,
2168    end_minute: u8,
2169) -> Vec<u8> {
2170    let mut buf = Vec::new();
2171    let mut w = TlvWriter::new(&mut buf);
2172    w.start_structure(Tag::Anonymous)
2173        .expect("infallible: vec writer");
2174    w.put_uint(Tag::Context(0), u64::from(week_day_index))
2175        .expect("infallible: vec writer");
2176    w.put_uint(Tag::Context(1), u64::from(user_index))
2177        .expect("infallible: vec writer");
2178    w.put_uint(Tag::Context(2), u64::from(days_mask.bits()))
2179        .expect("infallible: vec writer");
2180    w.put_uint(Tag::Context(3), u64::from(start_hour))
2181        .expect("infallible: vec writer");
2182    w.put_uint(Tag::Context(4), u64::from(start_minute))
2183        .expect("infallible: vec writer");
2184    w.put_uint(Tag::Context(5), u64::from(end_hour))
2185        .expect("infallible: vec writer");
2186    w.put_uint(Tag::Context(6), u64::from(end_minute))
2187        .expect("infallible: vec writer");
2188    w.end_container().expect("infallible: vec writer");
2189    buf
2190}
2191
2192/// Encode the `GetWeekDaySchedule` command request payload.
2193#[must_use]
2194#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2195pub fn encode_get_week_day_schedule(week_day_index: u8, user_index: u16) -> Vec<u8> {
2196    let mut buf = Vec::new();
2197    let mut w = TlvWriter::new(&mut buf);
2198    w.start_structure(Tag::Anonymous)
2199        .expect("infallible: vec writer");
2200    w.put_uint(Tag::Context(0), u64::from(week_day_index))
2201        .expect("infallible: vec writer");
2202    w.put_uint(Tag::Context(1), u64::from(user_index))
2203        .expect("infallible: vec writer");
2204    w.end_container().expect("infallible: vec writer");
2205    buf
2206}
2207
2208/// Decoded `GetWeekDayScheduleResponse` payload.
2209#[derive(Clone, Debug, PartialEq)]
2210#[non_exhaustive]
2211pub struct GetWeekDayScheduleResponse {
2212    /// Field WeekDayIndex (tag 0).
2213    pub week_day_index: u8,
2214    /// Field UserIndex (tag 1).
2215    pub user_index: u16,
2216    /// Field Status (tag 2).
2217    pub status: u8,
2218    /// Field DaysMask (tag 3).
2219    pub days_mask: Option<DaysMaskBitmap>,
2220    /// Field StartHour (tag 4).
2221    pub start_hour: Option<u8>,
2222    /// Field StartMinute (tag 5).
2223    pub start_minute: Option<u8>,
2224    /// Field EndHour (tag 6).
2225    pub end_hour: Option<u8>,
2226    /// Field EndMinute (tag 7).
2227    pub end_minute: Option<u8>,
2228}
2229
2230impl GetWeekDayScheduleResponse {
2231    /// Decode the fields of an already-opened anonymous structure
2232    /// (reader positioned after the struct start; consumes to its end).
2233    ///
2234    /// # Errors
2235    /// Returns [`ClusterError`] on a malformed structure or missing required field.
2236    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
2237        let mut f_week_day_index: Option<u8> = None;
2238        let mut f_user_index: Option<u16> = None;
2239        let mut f_status: Option<u8> = None;
2240        let mut f_days_mask: Option<DaysMaskBitmap> = None;
2241        let mut f_start_hour: Option<u8> = None;
2242        let mut f_start_minute: Option<u8> = None;
2243        let mut f_end_hour: Option<u8> = None;
2244        let mut f_end_minute: Option<u8> = None;
2245        loop {
2246            match r.next()? {
2247                Some(Element::ContainerEnd) => break,
2248                Some(Element::Scalar {
2249                    tag: Tag::Context(0),
2250                    value: Value::Uint(v),
2251                }) => {
2252                    f_week_day_index = Some(
2253                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("WeekDayIndex"))?,
2254                    )
2255                }
2256                Some(Element::Scalar {
2257                    tag: Tag::Context(1),
2258                    value: Value::Uint(v),
2259                }) => {
2260                    f_user_index = Some(
2261                        u16::try_from(v).map_err(|_| ClusterError::InvalidLength("UserIndex"))?,
2262                    )
2263                }
2264                Some(Element::Scalar {
2265                    tag: Tag::Context(2),
2266                    value: Value::Uint(v),
2267                }) => {
2268                    f_status =
2269                        Some(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("Status"))?)
2270                }
2271                Some(Element::Scalar {
2272                    tag: Tag::Context(3),
2273                    value: Value::Uint(v),
2274                }) => {
2275                    f_days_mask = Some(DaysMaskBitmap::from_bits_retain(
2276                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("DaysMask"))?,
2277                    ))
2278                }
2279                Some(Element::Scalar {
2280                    tag: Tag::Context(4),
2281                    value: Value::Uint(v),
2282                }) => {
2283                    f_start_hour = Some(
2284                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("StartHour"))?,
2285                    )
2286                }
2287                Some(Element::Scalar {
2288                    tag: Tag::Context(5),
2289                    value: Value::Uint(v),
2290                }) => {
2291                    f_start_minute = Some(
2292                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("StartMinute"))?,
2293                    )
2294                }
2295                Some(Element::Scalar {
2296                    tag: Tag::Context(6),
2297                    value: Value::Uint(v),
2298                }) => {
2299                    f_end_hour =
2300                        Some(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("EndHour"))?)
2301                }
2302                Some(Element::Scalar {
2303                    tag: Tag::Context(7),
2304                    value: Value::Uint(v),
2305                }) => {
2306                    f_end_minute = Some(
2307                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("EndMinute"))?,
2308                    )
2309                }
2310                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
2311                Some(Element::ContainerStart { .. }) => r.skip_container()?,
2312                Some(_) => {} // unknown/future scalar — skip
2313            }
2314        }
2315        Ok(Self {
2316            week_day_index: f_week_day_index.ok_or(ClusterError::MissingField("WeekDayIndex"))?,
2317            user_index: f_user_index.ok_or(ClusterError::MissingField("UserIndex"))?,
2318            status: f_status.ok_or(ClusterError::MissingField("Status"))?,
2319            days_mask: f_days_mask,
2320            start_hour: f_start_hour,
2321            start_minute: f_start_minute,
2322            end_hour: f_end_hour,
2323            end_minute: f_end_minute,
2324        })
2325    }
2326    /// Decode from a standalone anonymous TLV structure.
2327    ///
2328    /// # Errors
2329    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
2330    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
2331        let mut r = TlvReader::new(tlv);
2332        match r.next()? {
2333            Some(Element::ContainerStart {
2334                kind: ContainerKind::Structure,
2335                ..
2336            }) => {}
2337            _ => {
2338                return Err(ClusterError::UnexpectedType {
2339                    context: "GetWeekDayScheduleResponse",
2340                })
2341            }
2342        }
2343        Self::decode_from(&mut r)
2344    }
2345}
2346
2347/// Encode the `ClearWeekDaySchedule` command request payload.
2348#[must_use]
2349#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2350pub fn encode_clear_week_day_schedule(week_day_index: u8, user_index: u16) -> Vec<u8> {
2351    let mut buf = Vec::new();
2352    let mut w = TlvWriter::new(&mut buf);
2353    w.start_structure(Tag::Anonymous)
2354        .expect("infallible: vec writer");
2355    w.put_uint(Tag::Context(0), u64::from(week_day_index))
2356        .expect("infallible: vec writer");
2357    w.put_uint(Tag::Context(1), u64::from(user_index))
2358        .expect("infallible: vec writer");
2359    w.end_container().expect("infallible: vec writer");
2360    buf
2361}
2362
2363/// Encode the `SetYearDaySchedule` command request payload.
2364#[must_use]
2365#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2366pub fn encode_set_year_day_schedule(
2367    year_day_index: u8,
2368    user_index: u16,
2369    local_start_time: u32,
2370    local_end_time: u32,
2371) -> Vec<u8> {
2372    let mut buf = Vec::new();
2373    let mut w = TlvWriter::new(&mut buf);
2374    w.start_structure(Tag::Anonymous)
2375        .expect("infallible: vec writer");
2376    w.put_uint(Tag::Context(0), u64::from(year_day_index))
2377        .expect("infallible: vec writer");
2378    w.put_uint(Tag::Context(1), u64::from(user_index))
2379        .expect("infallible: vec writer");
2380    w.put_uint(Tag::Context(2), u64::from(local_start_time))
2381        .expect("infallible: vec writer");
2382    w.put_uint(Tag::Context(3), u64::from(local_end_time))
2383        .expect("infallible: vec writer");
2384    w.end_container().expect("infallible: vec writer");
2385    buf
2386}
2387
2388/// Encode the `GetYearDaySchedule` command request payload.
2389#[must_use]
2390#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2391pub fn encode_get_year_day_schedule(year_day_index: u8, user_index: u16) -> Vec<u8> {
2392    let mut buf = Vec::new();
2393    let mut w = TlvWriter::new(&mut buf);
2394    w.start_structure(Tag::Anonymous)
2395        .expect("infallible: vec writer");
2396    w.put_uint(Tag::Context(0), u64::from(year_day_index))
2397        .expect("infallible: vec writer");
2398    w.put_uint(Tag::Context(1), u64::from(user_index))
2399        .expect("infallible: vec writer");
2400    w.end_container().expect("infallible: vec writer");
2401    buf
2402}
2403
2404/// Decoded `GetYearDayScheduleResponse` payload.
2405#[derive(Clone, Debug, PartialEq)]
2406#[non_exhaustive]
2407pub struct GetYearDayScheduleResponse {
2408    /// Field YearDayIndex (tag 0).
2409    pub year_day_index: u8,
2410    /// Field UserIndex (tag 1).
2411    pub user_index: u16,
2412    /// Field Status (tag 2).
2413    pub status: u8,
2414    /// Field LocalStartTime (tag 3).
2415    pub local_start_time: Option<u32>,
2416    /// Field LocalEndTime (tag 4).
2417    pub local_end_time: Option<u32>,
2418}
2419
2420impl GetYearDayScheduleResponse {
2421    /// Decode the fields of an already-opened anonymous structure
2422    /// (reader positioned after the struct start; consumes to its end).
2423    ///
2424    /// # Errors
2425    /// Returns [`ClusterError`] on a malformed structure or missing required field.
2426    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
2427        let mut f_year_day_index: Option<u8> = None;
2428        let mut f_user_index: Option<u16> = None;
2429        let mut f_status: Option<u8> = None;
2430        let mut f_local_start_time: Option<u32> = None;
2431        let mut f_local_end_time: Option<u32> = None;
2432        loop {
2433            match r.next()? {
2434                Some(Element::ContainerEnd) => break,
2435                Some(Element::Scalar {
2436                    tag: Tag::Context(0),
2437                    value: Value::Uint(v),
2438                }) => {
2439                    f_year_day_index = Some(
2440                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("YearDayIndex"))?,
2441                    )
2442                }
2443                Some(Element::Scalar {
2444                    tag: Tag::Context(1),
2445                    value: Value::Uint(v),
2446                }) => {
2447                    f_user_index = Some(
2448                        u16::try_from(v).map_err(|_| ClusterError::InvalidLength("UserIndex"))?,
2449                    )
2450                }
2451                Some(Element::Scalar {
2452                    tag: Tag::Context(2),
2453                    value: Value::Uint(v),
2454                }) => {
2455                    f_status =
2456                        Some(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("Status"))?)
2457                }
2458                Some(Element::Scalar {
2459                    tag: Tag::Context(3),
2460                    value: Value::Uint(v),
2461                }) => {
2462                    f_local_start_time = Some(
2463                        u32::try_from(v)
2464                            .map_err(|_| ClusterError::InvalidLength("LocalStartTime"))?,
2465                    )
2466                }
2467                Some(Element::Scalar {
2468                    tag: Tag::Context(4),
2469                    value: Value::Uint(v),
2470                }) => {
2471                    f_local_end_time = Some(
2472                        u32::try_from(v)
2473                            .map_err(|_| ClusterError::InvalidLength("LocalEndTime"))?,
2474                    )
2475                }
2476                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
2477                Some(Element::ContainerStart { .. }) => r.skip_container()?,
2478                Some(_) => {} // unknown/future scalar — skip
2479            }
2480        }
2481        Ok(Self {
2482            year_day_index: f_year_day_index.ok_or(ClusterError::MissingField("YearDayIndex"))?,
2483            user_index: f_user_index.ok_or(ClusterError::MissingField("UserIndex"))?,
2484            status: f_status.ok_or(ClusterError::MissingField("Status"))?,
2485            local_start_time: f_local_start_time,
2486            local_end_time: f_local_end_time,
2487        })
2488    }
2489    /// Decode from a standalone anonymous TLV structure.
2490    ///
2491    /// # Errors
2492    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
2493    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
2494        let mut r = TlvReader::new(tlv);
2495        match r.next()? {
2496            Some(Element::ContainerStart {
2497                kind: ContainerKind::Structure,
2498                ..
2499            }) => {}
2500            _ => {
2501                return Err(ClusterError::UnexpectedType {
2502                    context: "GetYearDayScheduleResponse",
2503                })
2504            }
2505        }
2506        Self::decode_from(&mut r)
2507    }
2508}
2509
2510/// Encode the `ClearYearDaySchedule` command request payload.
2511#[must_use]
2512#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2513pub fn encode_clear_year_day_schedule(year_day_index: u8, user_index: u16) -> Vec<u8> {
2514    let mut buf = Vec::new();
2515    let mut w = TlvWriter::new(&mut buf);
2516    w.start_structure(Tag::Anonymous)
2517        .expect("infallible: vec writer");
2518    w.put_uint(Tag::Context(0), u64::from(year_day_index))
2519        .expect("infallible: vec writer");
2520    w.put_uint(Tag::Context(1), u64::from(user_index))
2521        .expect("infallible: vec writer");
2522    w.end_container().expect("infallible: vec writer");
2523    buf
2524}
2525
2526/// Encode the `SetHolidaySchedule` command request payload.
2527#[must_use]
2528#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2529pub fn encode_set_holiday_schedule(
2530    holiday_index: u8,
2531    local_start_time: u32,
2532    local_end_time: u32,
2533    operating_mode: OperatingModeEnum,
2534) -> Vec<u8> {
2535    let mut buf = Vec::new();
2536    let mut w = TlvWriter::new(&mut buf);
2537    w.start_structure(Tag::Anonymous)
2538        .expect("infallible: vec writer");
2539    w.put_uint(Tag::Context(0), u64::from(holiday_index))
2540        .expect("infallible: vec writer");
2541    w.put_uint(Tag::Context(1), u64::from(local_start_time))
2542        .expect("infallible: vec writer");
2543    w.put_uint(Tag::Context(2), u64::from(local_end_time))
2544        .expect("infallible: vec writer");
2545    w.put_uint(Tag::Context(3), u64::from(operating_mode.to_raw()))
2546        .expect("infallible: vec writer");
2547    w.end_container().expect("infallible: vec writer");
2548    buf
2549}
2550
2551/// Encode the `GetHolidaySchedule` command request payload.
2552#[must_use]
2553#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2554pub fn encode_get_holiday_schedule(holiday_index: u8) -> Vec<u8> {
2555    let mut buf = Vec::new();
2556    let mut w = TlvWriter::new(&mut buf);
2557    w.start_structure(Tag::Anonymous)
2558        .expect("infallible: vec writer");
2559    w.put_uint(Tag::Context(0), u64::from(holiday_index))
2560        .expect("infallible: vec writer");
2561    w.end_container().expect("infallible: vec writer");
2562    buf
2563}
2564
2565/// Decoded `GetHolidayScheduleResponse` payload.
2566#[derive(Clone, Debug, PartialEq)]
2567#[non_exhaustive]
2568pub struct GetHolidayScheduleResponse {
2569    /// Field HolidayIndex (tag 0).
2570    pub holiday_index: u8,
2571    /// Field Status (tag 1).
2572    pub status: u8,
2573    /// Field LocalStartTime (tag 2).
2574    pub local_start_time: Option<Nullable<u32>>,
2575    /// Field LocalEndTime (tag 3).
2576    pub local_end_time: Option<Nullable<u32>>,
2577    /// Field OperatingMode (tag 4).
2578    pub operating_mode: Option<Nullable<OperatingModeEnum>>,
2579}
2580
2581impl GetHolidayScheduleResponse {
2582    /// Decode the fields of an already-opened anonymous structure
2583    /// (reader positioned after the struct start; consumes to its end).
2584    ///
2585    /// # Errors
2586    /// Returns [`ClusterError`] on a malformed structure or missing required field.
2587    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
2588        let mut f_holiday_index: Option<u8> = None;
2589        let mut f_status: Option<u8> = None;
2590        let mut f_local_start_time: Option<Nullable<u32>> = None;
2591        let mut f_local_end_time: Option<Nullable<u32>> = None;
2592        let mut f_operating_mode: Option<Nullable<OperatingModeEnum>> = None;
2593        loop {
2594            match r.next()? {
2595                Some(Element::ContainerEnd) => break,
2596                Some(Element::Scalar {
2597                    tag: Tag::Context(0),
2598                    value: Value::Uint(v),
2599                }) => {
2600                    f_holiday_index = Some(
2601                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("HolidayIndex"))?,
2602                    )
2603                }
2604                Some(Element::Scalar {
2605                    tag: Tag::Context(1),
2606                    value: Value::Uint(v),
2607                }) => {
2608                    f_status =
2609                        Some(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("Status"))?)
2610                }
2611                Some(Element::Scalar {
2612                    tag: Tag::Context(2),
2613                    value: Value::Null,
2614                }) => f_local_start_time = Some(Nullable::Null),
2615                Some(Element::Scalar {
2616                    tag: Tag::Context(2),
2617                    value: Value::Uint(v),
2618                }) => {
2619                    f_local_start_time =
2620                        Some(Nullable::Value(u32::try_from(v).map_err(|_| {
2621                            ClusterError::InvalidLength("LocalStartTime")
2622                        })?))
2623                }
2624                Some(Element::Scalar {
2625                    tag: Tag::Context(3),
2626                    value: Value::Null,
2627                }) => f_local_end_time = Some(Nullable::Null),
2628                Some(Element::Scalar {
2629                    tag: Tag::Context(3),
2630                    value: Value::Uint(v),
2631                }) => {
2632                    f_local_end_time = Some(Nullable::Value(
2633                        u32::try_from(v)
2634                            .map_err(|_| ClusterError::InvalidLength("LocalEndTime"))?,
2635                    ))
2636                }
2637                Some(Element::Scalar {
2638                    tag: Tag::Context(4),
2639                    value: Value::Null,
2640                }) => f_operating_mode = Some(Nullable::Null),
2641                Some(Element::Scalar {
2642                    tag: Tag::Context(4),
2643                    value: Value::Uint(v),
2644                }) => {
2645                    f_operating_mode = Some(Nullable::Value(OperatingModeEnum::from_raw(
2646                        u8::try_from(v)
2647                            .map_err(|_| ClusterError::InvalidLength("OperatingMode"))?,
2648                    )))
2649                }
2650                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
2651                Some(Element::ContainerStart { .. }) => r.skip_container()?,
2652                Some(_) => {} // unknown/future scalar — skip
2653            }
2654        }
2655        Ok(Self {
2656            holiday_index: f_holiday_index.ok_or(ClusterError::MissingField("HolidayIndex"))?,
2657            status: f_status.ok_or(ClusterError::MissingField("Status"))?,
2658            local_start_time: f_local_start_time,
2659            local_end_time: f_local_end_time,
2660            operating_mode: f_operating_mode,
2661        })
2662    }
2663    /// Decode from a standalone anonymous TLV structure.
2664    ///
2665    /// # Errors
2666    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
2667    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
2668        let mut r = TlvReader::new(tlv);
2669        match r.next()? {
2670            Some(Element::ContainerStart {
2671                kind: ContainerKind::Structure,
2672                ..
2673            }) => {}
2674            _ => {
2675                return Err(ClusterError::UnexpectedType {
2676                    context: "GetHolidayScheduleResponse",
2677                })
2678            }
2679        }
2680        Self::decode_from(&mut r)
2681    }
2682}
2683
2684/// Encode the `ClearHolidaySchedule` command request payload.
2685#[must_use]
2686#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2687pub fn encode_clear_holiday_schedule(holiday_index: u8) -> Vec<u8> {
2688    let mut buf = Vec::new();
2689    let mut w = TlvWriter::new(&mut buf);
2690    w.start_structure(Tag::Anonymous)
2691        .expect("infallible: vec writer");
2692    w.put_uint(Tag::Context(0), u64::from(holiday_index))
2693        .expect("infallible: vec writer");
2694    w.end_container().expect("infallible: vec writer");
2695    buf
2696}
2697
2698/// Encode the `SetUser` command request payload.
2699#[must_use]
2700#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2701pub fn encode_set_user(
2702    operation_type: DataOperationTypeEnum,
2703    user_index: u16,
2704    user_name: Nullable<String>,
2705    user_unique_id: Nullable<u32>,
2706    user_status: Nullable<UserStatusEnum>,
2707    user_type: Nullable<UserTypeEnum>,
2708    credential_rule: Nullable<CredentialRuleEnum>,
2709) -> Vec<u8> {
2710    let mut buf = Vec::new();
2711    let mut w = TlvWriter::new(&mut buf);
2712    w.start_structure(Tag::Anonymous)
2713        .expect("infallible: vec writer");
2714    w.put_uint(Tag::Context(0), u64::from(operation_type.to_raw()))
2715        .expect("infallible: vec writer");
2716    w.put_uint(Tag::Context(1), u64::from(user_index))
2717        .expect("infallible: vec writer");
2718    match user_name {
2719        Nullable::Null => w.put_null(Tag::Context(2)).expect("infallible: vec writer"),
2720        Nullable::Value(user_name) => {
2721            w.put_utf8(Tag::Context(2), &user_name)
2722                .expect("infallible: vec writer");
2723        }
2724    }
2725    match user_unique_id {
2726        Nullable::Null => w.put_null(Tag::Context(3)).expect("infallible: vec writer"),
2727        Nullable::Value(user_unique_id) => {
2728            w.put_uint(Tag::Context(3), u64::from(user_unique_id))
2729                .expect("infallible: vec writer");
2730        }
2731    }
2732    match user_status {
2733        Nullable::Null => w.put_null(Tag::Context(4)).expect("infallible: vec writer"),
2734        Nullable::Value(user_status) => {
2735            w.put_uint(Tag::Context(4), u64::from(user_status.to_raw()))
2736                .expect("infallible: vec writer");
2737        }
2738    }
2739    match user_type {
2740        Nullable::Null => w.put_null(Tag::Context(5)).expect("infallible: vec writer"),
2741        Nullable::Value(user_type) => {
2742            w.put_uint(Tag::Context(5), u64::from(user_type.to_raw()))
2743                .expect("infallible: vec writer");
2744        }
2745    }
2746    match credential_rule {
2747        Nullable::Null => w.put_null(Tag::Context(6)).expect("infallible: vec writer"),
2748        Nullable::Value(credential_rule) => {
2749            w.put_uint(Tag::Context(6), u64::from(credential_rule.to_raw()))
2750                .expect("infallible: vec writer");
2751        }
2752    }
2753    w.end_container().expect("infallible: vec writer");
2754    buf
2755}
2756
2757/// Encode the `GetUser` command request payload.
2758#[must_use]
2759#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2760pub fn encode_get_user(user_index: u16) -> Vec<u8> {
2761    let mut buf = Vec::new();
2762    let mut w = TlvWriter::new(&mut buf);
2763    w.start_structure(Tag::Anonymous)
2764        .expect("infallible: vec writer");
2765    w.put_uint(Tag::Context(0), u64::from(user_index))
2766        .expect("infallible: vec writer");
2767    w.end_container().expect("infallible: vec writer");
2768    buf
2769}
2770
2771/// Decoded `GetUserResponse` payload.
2772#[derive(Clone, Debug, PartialEq)]
2773#[non_exhaustive]
2774pub struct GetUserResponse {
2775    /// Field UserIndex (tag 0).
2776    pub user_index: u16,
2777    /// Field UserName (tag 1).
2778    pub user_name: Nullable<String>,
2779    /// Field UserUniqueId (tag 2).
2780    pub user_unique_id: Nullable<u32>,
2781    /// Field UserStatus (tag 3).
2782    pub user_status: Nullable<UserStatusEnum>,
2783    /// Field UserType (tag 4).
2784    pub user_type: Nullable<UserTypeEnum>,
2785    /// Field CredentialRule (tag 5).
2786    pub credential_rule: Nullable<CredentialRuleEnum>,
2787    /// Field Credentials (tag 6).
2788    pub credentials: Nullable<Vec<CredentialStruct>>,
2789    /// Field CreatorFabricIndex (tag 7).
2790    pub creator_fabric_index: Nullable<u8>,
2791    /// Field LastModifiedFabricIndex (tag 8).
2792    pub last_modified_fabric_index: Nullable<u8>,
2793    /// Field NextUserIndex (tag 9).
2794    pub next_user_index: Nullable<u16>,
2795}
2796
2797impl GetUserResponse {
2798    /// Decode the fields of an already-opened anonymous structure
2799    /// (reader positioned after the struct start; consumes to its end).
2800    ///
2801    /// # Errors
2802    /// Returns [`ClusterError`] on a malformed structure or missing required field.
2803    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
2804        let mut f_user_index: Option<u16> = None;
2805        let mut f_user_name: Option<Nullable<String>> = None;
2806        let mut f_user_unique_id: Option<Nullable<u32>> = None;
2807        let mut f_user_status: Option<Nullable<UserStatusEnum>> = None;
2808        let mut f_user_type: Option<Nullable<UserTypeEnum>> = None;
2809        let mut f_credential_rule: Option<Nullable<CredentialRuleEnum>> = None;
2810        let mut f_credentials: Option<Nullable<Vec<CredentialStruct>>> = None;
2811        let mut f_creator_fabric_index: Option<Nullable<u8>> = None;
2812        let mut f_last_modified_fabric_index: Option<Nullable<u8>> = None;
2813        let mut f_next_user_index: Option<Nullable<u16>> = None;
2814        loop {
2815            match r.next()? {
2816                Some(Element::ContainerEnd) => break,
2817                Some(Element::Scalar {
2818                    tag: Tag::Context(0),
2819                    value: Value::Uint(v),
2820                }) => {
2821                    f_user_index = Some(
2822                        u16::try_from(v).map_err(|_| ClusterError::InvalidLength("UserIndex"))?,
2823                    )
2824                }
2825                Some(Element::Scalar {
2826                    tag: Tag::Context(1),
2827                    value: Value::Null,
2828                }) => f_user_name = Some(Nullable::Null),
2829                Some(Element::Scalar {
2830                    tag: Tag::Context(1),
2831                    value: Value::Utf8(v),
2832                }) => f_user_name = Some(Nullable::Value(v)),
2833                Some(Element::Scalar {
2834                    tag: Tag::Context(2),
2835                    value: Value::Null,
2836                }) => f_user_unique_id = Some(Nullable::Null),
2837                Some(Element::Scalar {
2838                    tag: Tag::Context(2),
2839                    value: Value::Uint(v),
2840                }) => {
2841                    f_user_unique_id = Some(Nullable::Value(
2842                        u32::try_from(v)
2843                            .map_err(|_| ClusterError::InvalidLength("UserUniqueId"))?,
2844                    ))
2845                }
2846                Some(Element::Scalar {
2847                    tag: Tag::Context(3),
2848                    value: Value::Null,
2849                }) => f_user_status = Some(Nullable::Null),
2850                Some(Element::Scalar {
2851                    tag: Tag::Context(3),
2852                    value: Value::Uint(v),
2853                }) => {
2854                    f_user_status = Some(Nullable::Value(UserStatusEnum::from_raw(
2855                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("UserStatus"))?,
2856                    )))
2857                }
2858                Some(Element::Scalar {
2859                    tag: Tag::Context(4),
2860                    value: Value::Null,
2861                }) => f_user_type = Some(Nullable::Null),
2862                Some(Element::Scalar {
2863                    tag: Tag::Context(4),
2864                    value: Value::Uint(v),
2865                }) => {
2866                    f_user_type = Some(Nullable::Value(UserTypeEnum::from_raw(
2867                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("UserType"))?,
2868                    )))
2869                }
2870                Some(Element::Scalar {
2871                    tag: Tag::Context(5),
2872                    value: Value::Null,
2873                }) => f_credential_rule = Some(Nullable::Null),
2874                Some(Element::Scalar {
2875                    tag: Tag::Context(5),
2876                    value: Value::Uint(v),
2877                }) => {
2878                    f_credential_rule = Some(Nullable::Value(CredentialRuleEnum::from_raw(
2879                        u8::try_from(v)
2880                            .map_err(|_| ClusterError::InvalidLength("CredentialRule"))?,
2881                    )))
2882                }
2883                Some(Element::Scalar {
2884                    tag: Tag::Context(6),
2885                    value: Value::Null,
2886                }) => f_credentials = Some(Nullable::Null),
2887                Some(Element::ContainerStart {
2888                    tag: Tag::Context(6),
2889                    kind: ContainerKind::Array,
2890                }) => {
2891                    let mut out = Vec::new();
2892                    loop {
2893                        match r.next()? {
2894                            Some(Element::ContainerEnd) => break,
2895                            Some(Element::ContainerStart {
2896                                kind: ContainerKind::Structure,
2897                                ..
2898                            }) => {
2899                                out.push(CredentialStruct::decode_from(r)?);
2900                            }
2901                            None => {
2902                                return Err(ClusterError::Tlv(
2903                                    matter_codec::Error::UnclosedContainer,
2904                                ))
2905                            }
2906                            Some(Element::ContainerStart { .. }) => r.skip_container()?,
2907                            Some(_) => {} // skip unknown scalar
2908                        }
2909                    }
2910                    f_credentials = Some(Nullable::Value(out));
2911                }
2912                Some(Element::Scalar {
2913                    tag: Tag::Context(7),
2914                    value: Value::Null,
2915                }) => f_creator_fabric_index = Some(Nullable::Null),
2916                Some(Element::Scalar {
2917                    tag: Tag::Context(7),
2918                    value: Value::Uint(v),
2919                }) => {
2920                    f_creator_fabric_index =
2921                        Some(Nullable::Value(u8::try_from(v).map_err(|_| {
2922                            ClusterError::InvalidLength("CreatorFabricIndex")
2923                        })?))
2924                }
2925                Some(Element::Scalar {
2926                    tag: Tag::Context(8),
2927                    value: Value::Null,
2928                }) => f_last_modified_fabric_index = Some(Nullable::Null),
2929                Some(Element::Scalar {
2930                    tag: Tag::Context(8),
2931                    value: Value::Uint(v),
2932                }) => {
2933                    f_last_modified_fabric_index =
2934                        Some(Nullable::Value(u8::try_from(v).map_err(|_| {
2935                            ClusterError::InvalidLength("LastModifiedFabricIndex")
2936                        })?))
2937                }
2938                Some(Element::Scalar {
2939                    tag: Tag::Context(9),
2940                    value: Value::Null,
2941                }) => f_next_user_index = Some(Nullable::Null),
2942                Some(Element::Scalar {
2943                    tag: Tag::Context(9),
2944                    value: Value::Uint(v),
2945                }) => {
2946                    f_next_user_index = Some(Nullable::Value(
2947                        u16::try_from(v)
2948                            .map_err(|_| ClusterError::InvalidLength("NextUserIndex"))?,
2949                    ))
2950                }
2951                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
2952                Some(Element::ContainerStart { .. }) => r.skip_container()?,
2953                Some(_) => {} // unknown/future scalar — skip
2954            }
2955        }
2956        Ok(Self {
2957            user_index: f_user_index.ok_or(ClusterError::MissingField("UserIndex"))?,
2958            user_name: f_user_name.ok_or(ClusterError::MissingField("UserName"))?,
2959            user_unique_id: f_user_unique_id.ok_or(ClusterError::MissingField("UserUniqueId"))?,
2960            user_status: f_user_status.ok_or(ClusterError::MissingField("UserStatus"))?,
2961            user_type: f_user_type.ok_or(ClusterError::MissingField("UserType"))?,
2962            credential_rule: f_credential_rule
2963                .ok_or(ClusterError::MissingField("CredentialRule"))?,
2964            credentials: f_credentials.ok_or(ClusterError::MissingField("Credentials"))?,
2965            creator_fabric_index: f_creator_fabric_index
2966                .ok_or(ClusterError::MissingField("CreatorFabricIndex"))?,
2967            last_modified_fabric_index: f_last_modified_fabric_index
2968                .ok_or(ClusterError::MissingField("LastModifiedFabricIndex"))?,
2969            next_user_index: f_next_user_index
2970                .ok_or(ClusterError::MissingField("NextUserIndex"))?,
2971        })
2972    }
2973    /// Decode from a standalone anonymous TLV structure.
2974    ///
2975    /// # Errors
2976    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
2977    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
2978        let mut r = TlvReader::new(tlv);
2979        match r.next()? {
2980            Some(Element::ContainerStart {
2981                kind: ContainerKind::Structure,
2982                ..
2983            }) => {}
2984            _ => {
2985                return Err(ClusterError::UnexpectedType {
2986                    context: "GetUserResponse",
2987                })
2988            }
2989        }
2990        Self::decode_from(&mut r)
2991    }
2992}
2993
2994/// Encode the `ClearUser` command request payload.
2995#[must_use]
2996#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2997pub fn encode_clear_user(user_index: u16) -> Vec<u8> {
2998    let mut buf = Vec::new();
2999    let mut w = TlvWriter::new(&mut buf);
3000    w.start_structure(Tag::Anonymous)
3001        .expect("infallible: vec writer");
3002    w.put_uint(Tag::Context(0), u64::from(user_index))
3003        .expect("infallible: vec writer");
3004    w.end_container().expect("infallible: vec writer");
3005    buf
3006}
3007
3008/// Encode the `SetCredential` command request payload.
3009#[must_use]
3010#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
3011pub fn encode_set_credential(
3012    operation_type: DataOperationTypeEnum,
3013    credential: CredentialStruct,
3014    credential_data: &Vec<u8>,
3015    user_index: Nullable<u16>,
3016    user_status: Nullable<UserStatusEnum>,
3017    user_type: Nullable<UserTypeEnum>,
3018) -> Vec<u8> {
3019    let mut buf = Vec::new();
3020    let mut w = TlvWriter::new(&mut buf);
3021    w.start_structure(Tag::Anonymous)
3022        .expect("infallible: vec writer");
3023    w.put_uint(Tag::Context(0), u64::from(operation_type.to_raw()))
3024        .expect("infallible: vec writer");
3025    w.start_structure(Tag::Context(1))
3026        .expect("infallible: vec writer");
3027    credential.write_fields(&mut w);
3028    w.end_container().expect("infallible: vec writer");
3029    w.put_bytes(Tag::Context(2), &credential_data)
3030        .expect("infallible: vec writer");
3031    match user_index {
3032        Nullable::Null => w.put_null(Tag::Context(3)).expect("infallible: vec writer"),
3033        Nullable::Value(user_index) => {
3034            w.put_uint(Tag::Context(3), u64::from(user_index))
3035                .expect("infallible: vec writer");
3036        }
3037    }
3038    match user_status {
3039        Nullable::Null => w.put_null(Tag::Context(4)).expect("infallible: vec writer"),
3040        Nullable::Value(user_status) => {
3041            w.put_uint(Tag::Context(4), u64::from(user_status.to_raw()))
3042                .expect("infallible: vec writer");
3043        }
3044    }
3045    match user_type {
3046        Nullable::Null => w.put_null(Tag::Context(5)).expect("infallible: vec writer"),
3047        Nullable::Value(user_type) => {
3048            w.put_uint(Tag::Context(5), u64::from(user_type.to_raw()))
3049                .expect("infallible: vec writer");
3050        }
3051    }
3052    w.end_container().expect("infallible: vec writer");
3053    buf
3054}
3055
3056/// Decoded `SetCredentialResponse` payload.
3057#[derive(Clone, Debug, PartialEq)]
3058#[non_exhaustive]
3059pub struct SetCredentialResponse {
3060    /// Field Status (tag 0).
3061    pub status: u8,
3062    /// Field UserIndex (tag 1).
3063    pub user_index: Nullable<u16>,
3064    /// Field NextCredentialIndex (tag 2).
3065    pub next_credential_index: Option<Nullable<u16>>,
3066}
3067
3068impl SetCredentialResponse {
3069    /// Decode the fields of an already-opened anonymous structure
3070    /// (reader positioned after the struct start; consumes to its end).
3071    ///
3072    /// # Errors
3073    /// Returns [`ClusterError`] on a malformed structure or missing required field.
3074    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
3075        let mut f_status: Option<u8> = None;
3076        let mut f_user_index: Option<Nullable<u16>> = None;
3077        let mut f_next_credential_index: Option<Nullable<u16>> = None;
3078        loop {
3079            match r.next()? {
3080                Some(Element::ContainerEnd) => break,
3081                Some(Element::Scalar {
3082                    tag: Tag::Context(0),
3083                    value: Value::Uint(v),
3084                }) => {
3085                    f_status =
3086                        Some(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("Status"))?)
3087                }
3088                Some(Element::Scalar {
3089                    tag: Tag::Context(1),
3090                    value: Value::Null,
3091                }) => f_user_index = Some(Nullable::Null),
3092                Some(Element::Scalar {
3093                    tag: Tag::Context(1),
3094                    value: Value::Uint(v),
3095                }) => {
3096                    f_user_index = Some(Nullable::Value(
3097                        u16::try_from(v).map_err(|_| ClusterError::InvalidLength("UserIndex"))?,
3098                    ))
3099                }
3100                Some(Element::Scalar {
3101                    tag: Tag::Context(2),
3102                    value: Value::Null,
3103                }) => f_next_credential_index = Some(Nullable::Null),
3104                Some(Element::Scalar {
3105                    tag: Tag::Context(2),
3106                    value: Value::Uint(v),
3107                }) => {
3108                    f_next_credential_index =
3109                        Some(Nullable::Value(u16::try_from(v).map_err(|_| {
3110                            ClusterError::InvalidLength("NextCredentialIndex")
3111                        })?))
3112                }
3113                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
3114                Some(Element::ContainerStart { .. }) => r.skip_container()?,
3115                Some(_) => {} // unknown/future scalar — skip
3116            }
3117        }
3118        Ok(Self {
3119            status: f_status.ok_or(ClusterError::MissingField("Status"))?,
3120            user_index: f_user_index.ok_or(ClusterError::MissingField("UserIndex"))?,
3121            next_credential_index: f_next_credential_index,
3122        })
3123    }
3124    /// Decode from a standalone anonymous TLV structure.
3125    ///
3126    /// # Errors
3127    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
3128    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
3129        let mut r = TlvReader::new(tlv);
3130        match r.next()? {
3131            Some(Element::ContainerStart {
3132                kind: ContainerKind::Structure,
3133                ..
3134            }) => {}
3135            _ => {
3136                return Err(ClusterError::UnexpectedType {
3137                    context: "SetCredentialResponse",
3138                })
3139            }
3140        }
3141        Self::decode_from(&mut r)
3142    }
3143}
3144
3145/// Encode the `GetCredentialStatus` command request payload.
3146#[must_use]
3147#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
3148pub fn encode_get_credential_status(credential: CredentialStruct) -> Vec<u8> {
3149    let mut buf = Vec::new();
3150    let mut w = TlvWriter::new(&mut buf);
3151    w.start_structure(Tag::Anonymous)
3152        .expect("infallible: vec writer");
3153    w.start_structure(Tag::Context(0))
3154        .expect("infallible: vec writer");
3155    credential.write_fields(&mut w);
3156    w.end_container().expect("infallible: vec writer");
3157    w.end_container().expect("infallible: vec writer");
3158    buf
3159}
3160
3161/// Decoded `GetCredentialStatusResponse` payload.
3162#[derive(Clone, Debug, PartialEq)]
3163#[non_exhaustive]
3164pub struct GetCredentialStatusResponse {
3165    /// Field CredentialExists (tag 0).
3166    pub credential_exists: bool,
3167    /// Field UserIndex (tag 1).
3168    pub user_index: Nullable<u16>,
3169    /// Field CreatorFabricIndex (tag 2).
3170    pub creator_fabric_index: Nullable<u8>,
3171    /// Field LastModifiedFabricIndex (tag 3).
3172    pub last_modified_fabric_index: Nullable<u8>,
3173    /// Field NextCredentialIndex (tag 4).
3174    pub next_credential_index: Option<Nullable<u16>>,
3175    /// Field CredentialData (tag 5).
3176    pub credential_data: Option<Nullable<Vec<u8>>>,
3177}
3178
3179impl GetCredentialStatusResponse {
3180    /// Decode the fields of an already-opened anonymous structure
3181    /// (reader positioned after the struct start; consumes to its end).
3182    ///
3183    /// # Errors
3184    /// Returns [`ClusterError`] on a malformed structure or missing required field.
3185    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
3186        let mut f_credential_exists: Option<bool> = None;
3187        let mut f_user_index: Option<Nullable<u16>> = None;
3188        let mut f_creator_fabric_index: Option<Nullable<u8>> = None;
3189        let mut f_last_modified_fabric_index: Option<Nullable<u8>> = None;
3190        let mut f_next_credential_index: Option<Nullable<u16>> = None;
3191        let mut f_credential_data: Option<Nullable<Vec<u8>>> = None;
3192        loop {
3193            match r.next()? {
3194                Some(Element::ContainerEnd) => break,
3195                Some(Element::Scalar {
3196                    tag: Tag::Context(0),
3197                    value: Value::Bool(v),
3198                }) => f_credential_exists = Some(v),
3199                Some(Element::Scalar {
3200                    tag: Tag::Context(1),
3201                    value: Value::Null,
3202                }) => f_user_index = Some(Nullable::Null),
3203                Some(Element::Scalar {
3204                    tag: Tag::Context(1),
3205                    value: Value::Uint(v),
3206                }) => {
3207                    f_user_index = Some(Nullable::Value(
3208                        u16::try_from(v).map_err(|_| ClusterError::InvalidLength("UserIndex"))?,
3209                    ))
3210                }
3211                Some(Element::Scalar {
3212                    tag: Tag::Context(2),
3213                    value: Value::Null,
3214                }) => f_creator_fabric_index = Some(Nullable::Null),
3215                Some(Element::Scalar {
3216                    tag: Tag::Context(2),
3217                    value: Value::Uint(v),
3218                }) => {
3219                    f_creator_fabric_index =
3220                        Some(Nullable::Value(u8::try_from(v).map_err(|_| {
3221                            ClusterError::InvalidLength("CreatorFabricIndex")
3222                        })?))
3223                }
3224                Some(Element::Scalar {
3225                    tag: Tag::Context(3),
3226                    value: Value::Null,
3227                }) => f_last_modified_fabric_index = Some(Nullable::Null),
3228                Some(Element::Scalar {
3229                    tag: Tag::Context(3),
3230                    value: Value::Uint(v),
3231                }) => {
3232                    f_last_modified_fabric_index =
3233                        Some(Nullable::Value(u8::try_from(v).map_err(|_| {
3234                            ClusterError::InvalidLength("LastModifiedFabricIndex")
3235                        })?))
3236                }
3237                Some(Element::Scalar {
3238                    tag: Tag::Context(4),
3239                    value: Value::Null,
3240                }) => f_next_credential_index = Some(Nullable::Null),
3241                Some(Element::Scalar {
3242                    tag: Tag::Context(4),
3243                    value: Value::Uint(v),
3244                }) => {
3245                    f_next_credential_index =
3246                        Some(Nullable::Value(u16::try_from(v).map_err(|_| {
3247                            ClusterError::InvalidLength("NextCredentialIndex")
3248                        })?))
3249                }
3250                Some(Element::Scalar {
3251                    tag: Tag::Context(5),
3252                    value: Value::Null,
3253                }) => f_credential_data = Some(Nullable::Null),
3254                Some(Element::Scalar {
3255                    tag: Tag::Context(5),
3256                    value: Value::Bytes(v),
3257                }) => f_credential_data = Some(Nullable::Value(v)),
3258                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
3259                Some(Element::ContainerStart { .. }) => r.skip_container()?,
3260                Some(_) => {} // unknown/future scalar — skip
3261            }
3262        }
3263        Ok(Self {
3264            credential_exists: f_credential_exists
3265                .ok_or(ClusterError::MissingField("CredentialExists"))?,
3266            user_index: f_user_index.ok_or(ClusterError::MissingField("UserIndex"))?,
3267            creator_fabric_index: f_creator_fabric_index
3268                .ok_or(ClusterError::MissingField("CreatorFabricIndex"))?,
3269            last_modified_fabric_index: f_last_modified_fabric_index
3270                .ok_or(ClusterError::MissingField("LastModifiedFabricIndex"))?,
3271            next_credential_index: f_next_credential_index,
3272            credential_data: f_credential_data,
3273        })
3274    }
3275    /// Decode from a standalone anonymous TLV structure.
3276    ///
3277    /// # Errors
3278    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
3279    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
3280        let mut r = TlvReader::new(tlv);
3281        match r.next()? {
3282            Some(Element::ContainerStart {
3283                kind: ContainerKind::Structure,
3284                ..
3285            }) => {}
3286            _ => {
3287                return Err(ClusterError::UnexpectedType {
3288                    context: "GetCredentialStatusResponse",
3289                })
3290            }
3291        }
3292        Self::decode_from(&mut r)
3293    }
3294}
3295
3296/// Encode the `ClearCredential` command request payload.
3297#[must_use]
3298#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
3299pub fn encode_clear_credential(credential: Nullable<CredentialStruct>) -> Vec<u8> {
3300    let mut buf = Vec::new();
3301    let mut w = TlvWriter::new(&mut buf);
3302    w.start_structure(Tag::Anonymous)
3303        .expect("infallible: vec writer");
3304    match &credential {
3305        Nullable::Null => w.put_null(Tag::Context(0)).expect("infallible: vec writer"),
3306        Nullable::Value(credential) => {
3307            w.start_structure(Tag::Context(0))
3308                .expect("infallible: vec writer");
3309            credential.write_fields(&mut w);
3310            w.end_container().expect("infallible: vec writer");
3311        }
3312    }
3313    w.end_container().expect("infallible: vec writer");
3314    buf
3315}
3316
3317/// Encode the `UnboltDoor` command request payload.
3318#[must_use]
3319#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
3320pub fn encode_unbolt_door(pin_code: Option<Vec<u8>>) -> Vec<u8> {
3321    let mut buf = Vec::new();
3322    let mut w = TlvWriter::new(&mut buf);
3323    w.start_structure(Tag::Anonymous)
3324        .expect("infallible: vec writer");
3325    if let Some(pin_code) = pin_code {
3326        w.put_bytes(Tag::Context(0), &pin_code)
3327            .expect("infallible: vec writer");
3328    }
3329    w.end_container().expect("infallible: vec writer");
3330    buf
3331}