Skip to main content

matter_clusters/gen/
operational_credentials.rs

1//! OperationalCredentials cluster (0x003E).
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 = 0x003E;
19/// Cluster revision.
20pub const CLUSTER_REVISION: u16 = 2;
21
22/// Command IDs (requests and responses).
23pub mod command_id {
24    /// `AttestationRequest` (request).
25    pub const ATTESTATION_REQUEST: u32 = 0x00;
26    /// `AttestationResponse` (response).
27    pub const ATTESTATION_RESPONSE: u32 = 0x01;
28    /// `CertificateChainRequest` (request).
29    pub const CERTIFICATE_CHAIN_REQUEST: u32 = 0x02;
30    /// `CertificateChainResponse` (response).
31    pub const CERTIFICATE_CHAIN_RESPONSE: u32 = 0x03;
32    /// `CsrRequest` (request).
33    pub const CSR_REQUEST: u32 = 0x04;
34    /// `CsrResponse` (response).
35    pub const CSR_RESPONSE: u32 = 0x05;
36    /// `AddNoc` (request).
37    pub const ADD_NOC: u32 = 0x06;
38    /// `UpdateNoc` (request).
39    pub const UPDATE_NOC: u32 = 0x07;
40    /// `NocResponse` (response).
41    pub const NOC_RESPONSE: u32 = 0x08;
42    /// `UpdateFabricLabel` (request).
43    pub const UPDATE_FABRIC_LABEL: u32 = 0x09;
44    /// `RemoveFabric` (request).
45    pub const REMOVE_FABRIC: u32 = 0x0A;
46    /// `AddTrustedRootCertificate` (request).
47    pub const ADD_TRUSTED_ROOT_CERTIFICATE: u32 = 0x0B;
48    /// `SetVidVerificationStatement` (request).
49    pub const SET_VID_VERIFICATION_STATEMENT: u32 = 0x0C;
50    /// `SignVidVerificationRequest` (request).
51    pub const SIGN_VID_VERIFICATION_REQUEST: u32 = 0x0D;
52    /// `SignVidVerificationResponse` (response).
53    pub const SIGN_VID_VERIFICATION_RESPONSE: u32 = 0x0E;
54}
55
56/// Attribute IDs (cluster-specific).
57pub mod attribute_id {
58    /// `Nocs`.
59    pub const NOCS: u32 = 0x0000;
60    /// `Fabrics`.
61    pub const FABRICS: u32 = 0x0001;
62    /// `SupportedFabrics`.
63    pub const SUPPORTED_FABRICS: u32 = 0x0002;
64    /// `CommissionedFabrics`.
65    pub const COMMISSIONED_FABRICS: u32 = 0x0003;
66    /// `TrustedRootCertificates`.
67    pub const TRUSTED_ROOT_CERTIFICATES: u32 = 0x0004;
68    /// `CurrentFabricIndex`.
69    pub const CURRENT_FABRIC_INDEX: u32 = 0x0005;
70}
71
72/// `CertificateChainTypeEnum` (enum8).
73#[derive(Copy, Clone, Debug, PartialEq, Eq)]
74pub enum CertificateChainTypeEnum {
75    /// DacCertificate = 1.
76    DacCertificate,
77    /// PaiCertificate = 2.
78    PaiCertificate,
79    /// A value not known to this codegen revision.
80    Unknown(u8),
81}
82
83impl CertificateChainTypeEnum {
84    /// Decode from its raw discriminant (unknown → `Unknown`).
85    #[must_use]
86    pub fn from_raw(v: u8) -> Self {
87        match v {
88            1 => Self::DacCertificate,
89            2 => Self::PaiCertificate,
90            other => Self::Unknown(other),
91        }
92    }
93    /// The raw discriminant.
94    #[must_use]
95    pub fn to_raw(self) -> u8 {
96        match self {
97            Self::DacCertificate => 1,
98            Self::PaiCertificate => 2,
99            Self::Unknown(v) => v,
100        }
101    }
102}
103
104/// `FabricDescriptorStruct` struct.
105#[derive(Clone, Debug, PartialEq)]
106#[non_exhaustive]
107pub struct FabricDescriptorStruct {
108    /// Field RootPublicKey (tag 1).
109    pub root_public_key: Vec<u8>,
110    /// Field VendorId (tag 2).
111    pub vendor_id: u16,
112    /// Field FabricId (tag 3).
113    pub fabric_id: u64,
114    /// Field NodeId (tag 4).
115    pub node_id: u64,
116    /// Field Label (tag 5).
117    pub label: String,
118    /// Field VidVerificationStatement (tag 6).
119    pub vid_verification_statement: Option<Vec<u8>>,
120    /// Field FabricIndex (tag 254).
121    pub fabric_index: u8,
122}
123
124/// `NOCStruct` struct.
125#[derive(Clone, Debug, PartialEq)]
126#[non_exhaustive]
127pub struct NOCStruct {
128    /// Field Noc (tag 1).
129    pub noc: Vec<u8>,
130    /// Field Icac (tag 2).
131    pub icac: Nullable<Vec<u8>>,
132    /// Field Vvsc (tag 3).
133    pub vvsc: Option<Vec<u8>>,
134    /// Field FabricIndex (tag 254).
135    pub fabric_index: u8,
136}
137
138/// `NodeOperationalCertStatusEnum` (enum8).
139#[derive(Copy, Clone, Debug, PartialEq, Eq)]
140pub enum NodeOperationalCertStatusEnum {
141    /// Ok = 0.
142    Ok,
143    /// InvalidPublicKey = 1.
144    InvalidPublicKey,
145    /// InvalidNodeOpId = 2.
146    InvalidNodeOpId,
147    /// InvalidNoc = 3.
148    InvalidNoc,
149    /// MissingCsr = 4.
150    MissingCsr,
151    /// TableFull = 5.
152    TableFull,
153    /// InvalidAdminSubject = 6.
154    InvalidAdminSubject,
155    /// FabricConflict = 9.
156    FabricConflict,
157    /// LabelConflict = 10.
158    LabelConflict,
159    /// InvalidFabricIndex = 11.
160    InvalidFabricIndex,
161    /// A value not known to this codegen revision.
162    Unknown(u8),
163}
164
165impl NodeOperationalCertStatusEnum {
166    /// Decode from its raw discriminant (unknown → `Unknown`).
167    #[must_use]
168    pub fn from_raw(v: u8) -> Self {
169        match v {
170            0 => Self::Ok,
171            1 => Self::InvalidPublicKey,
172            2 => Self::InvalidNodeOpId,
173            3 => Self::InvalidNoc,
174            4 => Self::MissingCsr,
175            5 => Self::TableFull,
176            6 => Self::InvalidAdminSubject,
177            9 => Self::FabricConflict,
178            10 => Self::LabelConflict,
179            11 => Self::InvalidFabricIndex,
180            other => Self::Unknown(other),
181        }
182    }
183    /// The raw discriminant.
184    #[must_use]
185    pub fn to_raw(self) -> u8 {
186        match self {
187            Self::Ok => 0,
188            Self::InvalidPublicKey => 1,
189            Self::InvalidNodeOpId => 2,
190            Self::InvalidNoc => 3,
191            Self::MissingCsr => 4,
192            Self::TableFull => 5,
193            Self::InvalidAdminSubject => 6,
194            Self::FabricConflict => 9,
195            Self::LabelConflict => 10,
196            Self::InvalidFabricIndex => 11,
197            Self::Unknown(v) => v,
198        }
199    }
200}
201
202impl FabricDescriptorStruct {
203    /// Decode the fields of an already-opened anonymous structure
204    /// (reader positioned after the struct start; consumes to its end).
205    ///
206    /// # Errors
207    /// Returns [`ClusterError`] on a malformed structure or missing required field.
208    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
209        let mut f_root_public_key: Option<Vec<u8>> = None;
210        let mut f_vendor_id: Option<u16> = None;
211        let mut f_fabric_id: Option<u64> = None;
212        let mut f_node_id: Option<u64> = None;
213        let mut f_label: Option<String> = None;
214        let mut f_vid_verification_statement: Option<Vec<u8>> = None;
215        let mut f_fabric_index: Option<u8> = None;
216        loop {
217            match r.next()? {
218                Some(Element::ContainerEnd) => break,
219                Some(Element::Scalar {
220                    tag: Tag::Context(1),
221                    value: Value::Bytes(v),
222                }) => f_root_public_key = Some(v),
223                Some(Element::Scalar {
224                    tag: Tag::Context(2),
225                    value: Value::Uint(v),
226                }) => {
227                    f_vendor_id = Some(
228                        u16::try_from(v).map_err(|_| ClusterError::InvalidLength("VendorId"))?,
229                    )
230                }
231                Some(Element::Scalar {
232                    tag: Tag::Context(3),
233                    value: Value::Uint(v),
234                }) => {
235                    f_fabric_id = Some(
236                        u64::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricId"))?,
237                    )
238                }
239                Some(Element::Scalar {
240                    tag: Tag::Context(4),
241                    value: Value::Uint(v),
242                }) => {
243                    f_node_id =
244                        Some(u64::try_from(v).map_err(|_| ClusterError::InvalidLength("NodeId"))?)
245                }
246                Some(Element::Scalar {
247                    tag: Tag::Context(5),
248                    value: Value::Utf8(v),
249                }) => f_label = Some(v),
250                Some(Element::Scalar {
251                    tag: Tag::Context(6),
252                    value: Value::Bytes(v),
253                }) => f_vid_verification_statement = Some(v),
254                Some(Element::Scalar {
255                    tag: Tag::Context(254),
256                    value: Value::Uint(v),
257                }) => {
258                    f_fabric_index = Some(
259                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
260                    )
261                }
262                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
263                Some(Element::ContainerStart { .. }) => r.skip_container()?,
264                Some(_) => {} // unknown/future scalar — skip
265            }
266        }
267        Ok(Self {
268            root_public_key: f_root_public_key
269                .ok_or(ClusterError::MissingField("RootPublicKey"))?,
270            vendor_id: f_vendor_id.ok_or(ClusterError::MissingField("VendorId"))?,
271            fabric_id: f_fabric_id.ok_or(ClusterError::MissingField("FabricId"))?,
272            node_id: f_node_id.ok_or(ClusterError::MissingField("NodeId"))?,
273            label: f_label.ok_or(ClusterError::MissingField("Label"))?,
274            vid_verification_statement: f_vid_verification_statement,
275            fabric_index: f_fabric_index.ok_or(ClusterError::MissingField("FabricIndex"))?,
276        })
277    }
278    /// Decode from a standalone anonymous TLV structure.
279    ///
280    /// # Errors
281    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
282    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
283        let mut r = TlvReader::new(tlv);
284        match r.next()? {
285            Some(Element::ContainerStart {
286                kind: ContainerKind::Structure,
287                ..
288            }) => {}
289            _ => {
290                return Err(ClusterError::UnexpectedType {
291                    context: "FabricDescriptorStruct",
292                })
293            }
294        }
295        Self::decode_from(&mut r)
296    }
297    /// Write this struct's fields into an already-open container.
298    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
299    pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
300        w.put_bytes(Tag::Context(1), &self.root_public_key)
301            .expect("infallible: vec writer");
302        w.put_uint(Tag::Context(2), u64::from(self.vendor_id))
303            .expect("infallible: vec writer");
304        w.put_uint(Tag::Context(3), u64::from(self.fabric_id))
305            .expect("infallible: vec writer");
306        w.put_uint(Tag::Context(4), u64::from(self.node_id))
307            .expect("infallible: vec writer");
308        w.put_utf8(Tag::Context(5), &self.label)
309            .expect("infallible: vec writer");
310        if let Some(vid_verification_statement) = &self.vid_verification_statement {
311            w.put_bytes(Tag::Context(6), &*vid_verification_statement)
312                .expect("infallible: vec writer");
313        }
314        w.put_uint(Tag::Context(254), u64::from(self.fabric_index))
315            .expect("infallible: vec writer");
316    }
317    /// Encode as a standalone anonymous TLV structure.
318    #[must_use]
319    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
320    pub fn encode(&self) -> Vec<u8> {
321        let mut buf = Vec::new();
322        let mut w = TlvWriter::new(&mut buf);
323        w.start_structure(Tag::Anonymous)
324            .expect("infallible: vec writer");
325        self.write_fields(&mut w);
326        w.end_container().expect("infallible: vec writer");
327        buf
328    }
329}
330
331impl NOCStruct {
332    /// Decode the fields of an already-opened anonymous structure
333    /// (reader positioned after the struct start; consumes to its end).
334    ///
335    /// # Errors
336    /// Returns [`ClusterError`] on a malformed structure or missing required field.
337    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
338        let mut f_noc: Option<Vec<u8>> = None;
339        let mut f_icac: Option<Nullable<Vec<u8>>> = None;
340        let mut f_vvsc: Option<Vec<u8>> = None;
341        let mut f_fabric_index: Option<u8> = None;
342        loop {
343            match r.next()? {
344                Some(Element::ContainerEnd) => break,
345                Some(Element::Scalar {
346                    tag: Tag::Context(1),
347                    value: Value::Bytes(v),
348                }) => f_noc = Some(v),
349                Some(Element::Scalar {
350                    tag: Tag::Context(2),
351                    value: Value::Null,
352                }) => f_icac = Some(Nullable::Null),
353                Some(Element::Scalar {
354                    tag: Tag::Context(2),
355                    value: Value::Bytes(v),
356                }) => f_icac = Some(Nullable::Value(v)),
357                Some(Element::Scalar {
358                    tag: Tag::Context(3),
359                    value: Value::Bytes(v),
360                }) => f_vvsc = Some(v),
361                Some(Element::Scalar {
362                    tag: Tag::Context(254),
363                    value: Value::Uint(v),
364                }) => {
365                    f_fabric_index = Some(
366                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
367                    )
368                }
369                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
370                Some(Element::ContainerStart { .. }) => r.skip_container()?,
371                Some(_) => {} // unknown/future scalar — skip
372            }
373        }
374        Ok(Self {
375            noc: f_noc.ok_or(ClusterError::MissingField("Noc"))?,
376            icac: f_icac.ok_or(ClusterError::MissingField("Icac"))?,
377            vvsc: f_vvsc,
378            fabric_index: f_fabric_index.ok_or(ClusterError::MissingField("FabricIndex"))?,
379        })
380    }
381    /// Decode from a standalone anonymous TLV structure.
382    ///
383    /// # Errors
384    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
385    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
386        let mut r = TlvReader::new(tlv);
387        match r.next()? {
388            Some(Element::ContainerStart {
389                kind: ContainerKind::Structure,
390                ..
391            }) => {}
392            _ => {
393                return Err(ClusterError::UnexpectedType {
394                    context: "NOCStruct",
395                })
396            }
397        }
398        Self::decode_from(&mut r)
399    }
400    /// Write this struct's fields into an already-open container.
401    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
402    pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
403        w.put_bytes(Tag::Context(1), &self.noc)
404            .expect("infallible: vec writer");
405        match &self.icac {
406            Nullable::Null => w.put_null(Tag::Context(2)).expect("infallible: vec writer"),
407            Nullable::Value(icac) => {
408                w.put_bytes(Tag::Context(2), &*icac)
409                    .expect("infallible: vec writer");
410            }
411        }
412        if let Some(vvsc) = &self.vvsc {
413            w.put_bytes(Tag::Context(3), &*vvsc)
414                .expect("infallible: vec writer");
415        }
416        w.put_uint(Tag::Context(254), u64::from(self.fabric_index))
417            .expect("infallible: vec writer");
418    }
419    /// Encode as a standalone anonymous TLV structure.
420    #[must_use]
421    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
422    pub fn encode(&self) -> Vec<u8> {
423        let mut buf = Vec::new();
424        let mut w = TlvWriter::new(&mut buf);
425        w.start_structure(Tag::Anonymous)
426            .expect("infallible: vec writer");
427        self.write_fields(&mut w);
428        w.end_container().expect("infallible: vec writer");
429        buf
430    }
431}
432
433/// Decode the `Nocs` attribute value.
434///
435/// # Errors
436/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
437pub fn decode_nocs(tlv: &[u8]) -> Result<Vec<NOCStruct>, ClusterError> {
438    let mut r = TlvReader::new(tlv);
439    match r.next()? {
440        Some(Element::ContainerStart {
441            kind: ContainerKind::Array,
442            ..
443        }) => {}
444        _ => return Err(ClusterError::UnexpectedType { context: "Nocs" }),
445    }
446    let r = &mut r;
447    let mut out = Vec::new();
448    loop {
449        match r.next()? {
450            Some(Element::ContainerEnd) => break,
451            Some(Element::ContainerStart {
452                kind: ContainerKind::Structure,
453                ..
454            }) => {
455                out.push(NOCStruct::decode_from(r)?);
456            }
457            None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
458            Some(Element::ContainerStart { .. }) => r.skip_container()?,
459            Some(_) => {} // skip unknown scalar
460        }
461    }
462    Ok(out)
463}
464
465/// Decode the `Fabrics` attribute value.
466///
467/// # Errors
468/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
469pub fn decode_fabrics(tlv: &[u8]) -> Result<Vec<FabricDescriptorStruct>, ClusterError> {
470    let mut r = TlvReader::new(tlv);
471    match r.next()? {
472        Some(Element::ContainerStart {
473            kind: ContainerKind::Array,
474            ..
475        }) => {}
476        _ => return Err(ClusterError::UnexpectedType { context: "Fabrics" }),
477    }
478    let r = &mut r;
479    let mut out = Vec::new();
480    loop {
481        match r.next()? {
482            Some(Element::ContainerEnd) => break,
483            Some(Element::ContainerStart {
484                kind: ContainerKind::Structure,
485                ..
486            }) => {
487                out.push(FabricDescriptorStruct::decode_from(r)?);
488            }
489            None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
490            Some(Element::ContainerStart { .. }) => r.skip_container()?,
491            Some(_) => {} // skip unknown scalar
492        }
493    }
494    Ok(out)
495}
496
497/// Decode the `SupportedFabrics` attribute value.
498///
499/// # Errors
500/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
501pub fn decode_supported_fabrics(tlv: &[u8]) -> Result<u8, ClusterError> {
502    let mut r = TlvReader::new(tlv);
503    match r.next()? {
504        Some(Element::Scalar {
505            value: Value::Uint(v),
506            ..
507        }) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("SupportedFabrics"))?),
508        _ => Err(ClusterError::UnexpectedType {
509            context: "SupportedFabrics",
510        }),
511    }
512}
513
514/// Decode the `CommissionedFabrics` attribute value.
515///
516/// # Errors
517/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
518pub fn decode_commissioned_fabrics(tlv: &[u8]) -> Result<u8, ClusterError> {
519    let mut r = TlvReader::new(tlv);
520    match r.next()? {
521        Some(Element::Scalar {
522            value: Value::Uint(v),
523            ..
524        }) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("CommissionedFabrics"))?),
525        _ => Err(ClusterError::UnexpectedType {
526            context: "CommissionedFabrics",
527        }),
528    }
529}
530
531/// Decode the `TrustedRootCertificates` attribute value.
532///
533/// # Errors
534/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
535pub fn decode_trusted_root_certificates(tlv: &[u8]) -> Result<Vec<Vec<u8>>, ClusterError> {
536    let mut r = TlvReader::new(tlv);
537    match r.next()? {
538        Some(Element::ContainerStart {
539            kind: ContainerKind::Array,
540            ..
541        }) => {}
542        _ => {
543            return Err(ClusterError::UnexpectedType {
544                context: "TrustedRootCertificates",
545            })
546        }
547    }
548    let r = &mut r;
549    let mut out = Vec::new();
550    loop {
551        match r.next()? {
552            Some(Element::ContainerEnd) => break,
553            Some(Element::Scalar {
554                value: Value::Bytes(v),
555                ..
556            }) => out.push(v),
557            None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
558            Some(Element::ContainerStart { .. }) => r.skip_container()?,
559            Some(_) => {} // skip unknown scalar
560        }
561    }
562    Ok(out)
563}
564
565/// Decode the `CurrentFabricIndex` attribute value.
566///
567/// # Errors
568/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
569pub fn decode_current_fabric_index(tlv: &[u8]) -> Result<u8, ClusterError> {
570    let mut r = TlvReader::new(tlv);
571    match r.next()? {
572        Some(Element::Scalar {
573            value: Value::Uint(v),
574            ..
575        }) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("CurrentFabricIndex"))?),
576        _ => Err(ClusterError::UnexpectedType {
577            context: "CurrentFabricIndex",
578        }),
579    }
580}
581
582/// Encode the `AttestationRequest` command request payload.
583#[must_use]
584#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
585pub fn encode_attestation_request(attestation_nonce: &Vec<u8>) -> Vec<u8> {
586    let mut buf = Vec::new();
587    let mut w = TlvWriter::new(&mut buf);
588    w.start_structure(Tag::Anonymous)
589        .expect("infallible: vec writer");
590    w.put_bytes(Tag::Context(0), &attestation_nonce)
591        .expect("infallible: vec writer");
592    w.end_container().expect("infallible: vec writer");
593    buf
594}
595
596/// Decoded `AttestationResponse` payload.
597#[derive(Clone, Debug, PartialEq)]
598#[non_exhaustive]
599pub struct AttestationResponse {
600    /// Field AttestationElements (tag 0).
601    pub attestation_elements: Vec<u8>,
602    /// Field AttestationSignature (tag 1).
603    pub attestation_signature: Vec<u8>,
604}
605
606impl AttestationResponse {
607    /// Decode the fields of an already-opened anonymous structure
608    /// (reader positioned after the struct start; consumes to its end).
609    ///
610    /// # Errors
611    /// Returns [`ClusterError`] on a malformed structure or missing required field.
612    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
613        let mut f_attestation_elements: Option<Vec<u8>> = None;
614        let mut f_attestation_signature: Option<Vec<u8>> = None;
615        loop {
616            match r.next()? {
617                Some(Element::ContainerEnd) => break,
618                Some(Element::Scalar {
619                    tag: Tag::Context(0),
620                    value: Value::Bytes(v),
621                }) => f_attestation_elements = Some(v),
622                Some(Element::Scalar {
623                    tag: Tag::Context(1),
624                    value: Value::Bytes(v),
625                }) => f_attestation_signature = Some(v),
626                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
627                Some(Element::ContainerStart { .. }) => r.skip_container()?,
628                Some(_) => {} // unknown/future scalar — skip
629            }
630        }
631        Ok(Self {
632            attestation_elements: f_attestation_elements
633                .ok_or(ClusterError::MissingField("AttestationElements"))?,
634            attestation_signature: f_attestation_signature
635                .ok_or(ClusterError::MissingField("AttestationSignature"))?,
636        })
637    }
638    /// Decode from a standalone anonymous TLV structure.
639    ///
640    /// # Errors
641    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
642    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
643        let mut r = TlvReader::new(tlv);
644        match r.next()? {
645            Some(Element::ContainerStart {
646                kind: ContainerKind::Structure,
647                ..
648            }) => {}
649            _ => {
650                return Err(ClusterError::UnexpectedType {
651                    context: "AttestationResponse",
652                })
653            }
654        }
655        Self::decode_from(&mut r)
656    }
657}
658
659/// Encode the `CertificateChainRequest` command request payload.
660#[must_use]
661#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
662pub fn encode_certificate_chain_request(certificate_type: CertificateChainTypeEnum) -> Vec<u8> {
663    let mut buf = Vec::new();
664    let mut w = TlvWriter::new(&mut buf);
665    w.start_structure(Tag::Anonymous)
666        .expect("infallible: vec writer");
667    w.put_uint(Tag::Context(0), u64::from(certificate_type.to_raw()))
668        .expect("infallible: vec writer");
669    w.end_container().expect("infallible: vec writer");
670    buf
671}
672
673/// Decoded `CertificateChainResponse` payload.
674#[derive(Clone, Debug, PartialEq)]
675#[non_exhaustive]
676pub struct CertificateChainResponse {
677    /// Field Certificate (tag 0).
678    pub certificate: Vec<u8>,
679}
680
681impl CertificateChainResponse {
682    /// Decode the fields of an already-opened anonymous structure
683    /// (reader positioned after the struct start; consumes to its end).
684    ///
685    /// # Errors
686    /// Returns [`ClusterError`] on a malformed structure or missing required field.
687    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
688        let mut f_certificate: Option<Vec<u8>> = None;
689        loop {
690            match r.next()? {
691                Some(Element::ContainerEnd) => break,
692                Some(Element::Scalar {
693                    tag: Tag::Context(0),
694                    value: Value::Bytes(v),
695                }) => f_certificate = Some(v),
696                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
697                Some(Element::ContainerStart { .. }) => r.skip_container()?,
698                Some(_) => {} // unknown/future scalar — skip
699            }
700        }
701        Ok(Self {
702            certificate: f_certificate.ok_or(ClusterError::MissingField("Certificate"))?,
703        })
704    }
705    /// Decode from a standalone anonymous TLV structure.
706    ///
707    /// # Errors
708    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
709    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
710        let mut r = TlvReader::new(tlv);
711        match r.next()? {
712            Some(Element::ContainerStart {
713                kind: ContainerKind::Structure,
714                ..
715            }) => {}
716            _ => {
717                return Err(ClusterError::UnexpectedType {
718                    context: "CertificateChainResponse",
719                })
720            }
721        }
722        Self::decode_from(&mut r)
723    }
724}
725
726/// Encode the `CsrRequest` command request payload.
727#[must_use]
728#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
729pub fn encode_csr_request(csr_nonce: &Vec<u8>, is_for_update_noc: Option<bool>) -> Vec<u8> {
730    let mut buf = Vec::new();
731    let mut w = TlvWriter::new(&mut buf);
732    w.start_structure(Tag::Anonymous)
733        .expect("infallible: vec writer");
734    w.put_bytes(Tag::Context(0), &csr_nonce)
735        .expect("infallible: vec writer");
736    if let Some(is_for_update_noc) = is_for_update_noc {
737        w.put_bool(Tag::Context(1), is_for_update_noc)
738            .expect("infallible: vec writer");
739    }
740    w.end_container().expect("infallible: vec writer");
741    buf
742}
743
744/// Decoded `CsrResponse` payload.
745#[derive(Clone, Debug, PartialEq)]
746#[non_exhaustive]
747pub struct CsrResponse {
748    /// Field NocsrElements (tag 0).
749    pub nocsr_elements: Vec<u8>,
750    /// Field AttestationSignature (tag 1).
751    pub attestation_signature: Vec<u8>,
752}
753
754impl CsrResponse {
755    /// Decode the fields of an already-opened anonymous structure
756    /// (reader positioned after the struct start; consumes to its end).
757    ///
758    /// # Errors
759    /// Returns [`ClusterError`] on a malformed structure or missing required field.
760    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
761        let mut f_nocsr_elements: Option<Vec<u8>> = None;
762        let mut f_attestation_signature: Option<Vec<u8>> = None;
763        loop {
764            match r.next()? {
765                Some(Element::ContainerEnd) => break,
766                Some(Element::Scalar {
767                    tag: Tag::Context(0),
768                    value: Value::Bytes(v),
769                }) => f_nocsr_elements = Some(v),
770                Some(Element::Scalar {
771                    tag: Tag::Context(1),
772                    value: Value::Bytes(v),
773                }) => f_attestation_signature = Some(v),
774                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
775                Some(Element::ContainerStart { .. }) => r.skip_container()?,
776                Some(_) => {} // unknown/future scalar — skip
777            }
778        }
779        Ok(Self {
780            nocsr_elements: f_nocsr_elements.ok_or(ClusterError::MissingField("NocsrElements"))?,
781            attestation_signature: f_attestation_signature
782                .ok_or(ClusterError::MissingField("AttestationSignature"))?,
783        })
784    }
785    /// Decode from a standalone anonymous TLV structure.
786    ///
787    /// # Errors
788    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
789    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
790        let mut r = TlvReader::new(tlv);
791        match r.next()? {
792            Some(Element::ContainerStart {
793                kind: ContainerKind::Structure,
794                ..
795            }) => {}
796            _ => {
797                return Err(ClusterError::UnexpectedType {
798                    context: "CsrResponse",
799                })
800            }
801        }
802        Self::decode_from(&mut r)
803    }
804}
805
806/// Encode the `AddNoc` command request payload.
807#[must_use]
808#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
809pub fn encode_add_noc(
810    noc_value: &Vec<u8>,
811    icac_value: Option<Vec<u8>>,
812    ipk_value: &Vec<u8>,
813    case_admin_subject: u64,
814    admin_vendor_id: u16,
815) -> Vec<u8> {
816    let mut buf = Vec::new();
817    let mut w = TlvWriter::new(&mut buf);
818    w.start_structure(Tag::Anonymous)
819        .expect("infallible: vec writer");
820    w.put_bytes(Tag::Context(0), &noc_value)
821        .expect("infallible: vec writer");
822    if let Some(icac_value) = icac_value {
823        w.put_bytes(Tag::Context(1), &icac_value)
824            .expect("infallible: vec writer");
825    }
826    w.put_bytes(Tag::Context(2), &ipk_value)
827        .expect("infallible: vec writer");
828    w.put_uint(Tag::Context(3), u64::from(case_admin_subject))
829        .expect("infallible: vec writer");
830    w.put_uint(Tag::Context(4), u64::from(admin_vendor_id))
831        .expect("infallible: vec writer");
832    w.end_container().expect("infallible: vec writer");
833    buf
834}
835
836/// Encode the `UpdateNoc` command request payload.
837#[must_use]
838#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
839pub fn encode_update_noc(noc_value: &Vec<u8>, icac_value: Option<Vec<u8>>) -> Vec<u8> {
840    let mut buf = Vec::new();
841    let mut w = TlvWriter::new(&mut buf);
842    w.start_structure(Tag::Anonymous)
843        .expect("infallible: vec writer");
844    w.put_bytes(Tag::Context(0), &noc_value)
845        .expect("infallible: vec writer");
846    if let Some(icac_value) = icac_value {
847        w.put_bytes(Tag::Context(1), &icac_value)
848            .expect("infallible: vec writer");
849    }
850    w.end_container().expect("infallible: vec writer");
851    buf
852}
853
854/// Decoded `NocResponse` payload.
855#[derive(Clone, Debug, PartialEq)]
856#[non_exhaustive]
857pub struct NocResponse {
858    /// Field StatusCode (tag 0).
859    pub status_code: NodeOperationalCertStatusEnum,
860    /// Field FabricIndex (tag 1).
861    pub fabric_index: Option<u8>,
862    /// Field DebugText (tag 2).
863    pub debug_text: Option<String>,
864}
865
866impl NocResponse {
867    /// Decode the fields of an already-opened anonymous structure
868    /// (reader positioned after the struct start; consumes to its end).
869    ///
870    /// # Errors
871    /// Returns [`ClusterError`] on a malformed structure or missing required field.
872    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
873        let mut f_status_code: Option<NodeOperationalCertStatusEnum> = None;
874        let mut f_fabric_index: Option<u8> = None;
875        let mut f_debug_text: Option<String> = None;
876        loop {
877            match r.next()? {
878                Some(Element::ContainerEnd) => break,
879                Some(Element::Scalar {
880                    tag: Tag::Context(0),
881                    value: Value::Uint(v),
882                }) => {
883                    f_status_code = Some(NodeOperationalCertStatusEnum::from_raw(
884                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("StatusCode"))?,
885                    ))
886                }
887                Some(Element::Scalar {
888                    tag: Tag::Context(1),
889                    value: Value::Uint(v),
890                }) => {
891                    f_fabric_index = Some(
892                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
893                    )
894                }
895                Some(Element::Scalar {
896                    tag: Tag::Context(2),
897                    value: Value::Utf8(v),
898                }) => f_debug_text = Some(v),
899                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
900                Some(Element::ContainerStart { .. }) => r.skip_container()?,
901                Some(_) => {} // unknown/future scalar — skip
902            }
903        }
904        Ok(Self {
905            status_code: f_status_code.ok_or(ClusterError::MissingField("StatusCode"))?,
906            fabric_index: f_fabric_index,
907            debug_text: f_debug_text,
908        })
909    }
910    /// Decode from a standalone anonymous TLV structure.
911    ///
912    /// # Errors
913    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
914    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
915        let mut r = TlvReader::new(tlv);
916        match r.next()? {
917            Some(Element::ContainerStart {
918                kind: ContainerKind::Structure,
919                ..
920            }) => {}
921            _ => {
922                return Err(ClusterError::UnexpectedType {
923                    context: "NocResponse",
924                })
925            }
926        }
927        Self::decode_from(&mut r)
928    }
929}
930
931/// Encode the `UpdateFabricLabel` command request payload.
932#[must_use]
933#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
934pub fn encode_update_fabric_label(label: &String) -> Vec<u8> {
935    let mut buf = Vec::new();
936    let mut w = TlvWriter::new(&mut buf);
937    w.start_structure(Tag::Anonymous)
938        .expect("infallible: vec writer");
939    w.put_utf8(Tag::Context(0), &label)
940        .expect("infallible: vec writer");
941    w.end_container().expect("infallible: vec writer");
942    buf
943}
944
945/// Encode the `RemoveFabric` command request payload.
946#[must_use]
947#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
948pub fn encode_remove_fabric(fabric_index: u8) -> Vec<u8> {
949    let mut buf = Vec::new();
950    let mut w = TlvWriter::new(&mut buf);
951    w.start_structure(Tag::Anonymous)
952        .expect("infallible: vec writer");
953    w.put_uint(Tag::Context(0), u64::from(fabric_index))
954        .expect("infallible: vec writer");
955    w.end_container().expect("infallible: vec writer");
956    buf
957}
958
959/// Encode the `AddTrustedRootCertificate` command request payload.
960#[must_use]
961#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
962pub fn encode_add_trusted_root_certificate(root_ca_certificate: &Vec<u8>) -> Vec<u8> {
963    let mut buf = Vec::new();
964    let mut w = TlvWriter::new(&mut buf);
965    w.start_structure(Tag::Anonymous)
966        .expect("infallible: vec writer");
967    w.put_bytes(Tag::Context(0), &root_ca_certificate)
968        .expect("infallible: vec writer");
969    w.end_container().expect("infallible: vec writer");
970    buf
971}
972
973/// Encode the `SetVidVerificationStatement` command request payload.
974#[must_use]
975#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
976pub fn encode_set_vid_verification_statement(
977    vendor_id: Option<u16>,
978    vid_verification_statement: Option<Vec<u8>>,
979    vvsc: Option<Vec<u8>>,
980) -> Vec<u8> {
981    let mut buf = Vec::new();
982    let mut w = TlvWriter::new(&mut buf);
983    w.start_structure(Tag::Anonymous)
984        .expect("infallible: vec writer");
985    if let Some(vendor_id) = vendor_id {
986        w.put_uint(Tag::Context(0), u64::from(vendor_id))
987            .expect("infallible: vec writer");
988    }
989    if let Some(vid_verification_statement) = vid_verification_statement {
990        w.put_bytes(Tag::Context(1), &vid_verification_statement)
991            .expect("infallible: vec writer");
992    }
993    if let Some(vvsc) = vvsc {
994        w.put_bytes(Tag::Context(2), &vvsc)
995            .expect("infallible: vec writer");
996    }
997    w.end_container().expect("infallible: vec writer");
998    buf
999}
1000
1001/// Encode the `SignVidVerificationRequest` command request payload.
1002#[must_use]
1003#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1004pub fn encode_sign_vid_verification_request(
1005    fabric_index: u8,
1006    client_challenge: &Vec<u8>,
1007) -> Vec<u8> {
1008    let mut buf = Vec::new();
1009    let mut w = TlvWriter::new(&mut buf);
1010    w.start_structure(Tag::Anonymous)
1011        .expect("infallible: vec writer");
1012    w.put_uint(Tag::Context(0), u64::from(fabric_index))
1013        .expect("infallible: vec writer");
1014    w.put_bytes(Tag::Context(1), &client_challenge)
1015        .expect("infallible: vec writer");
1016    w.end_container().expect("infallible: vec writer");
1017    buf
1018}
1019
1020/// Decoded `SignVidVerificationResponse` payload.
1021#[derive(Clone, Debug, PartialEq)]
1022#[non_exhaustive]
1023pub struct SignVidVerificationResponse {
1024    /// Field FabricIndex (tag 0).
1025    pub fabric_index: u8,
1026    /// Field FabricBindingVersion (tag 1).
1027    pub fabric_binding_version: u8,
1028    /// Field Signature (tag 2).
1029    pub signature: Vec<u8>,
1030}
1031
1032impl SignVidVerificationResponse {
1033    /// Decode the fields of an already-opened anonymous structure
1034    /// (reader positioned after the struct start; consumes to its end).
1035    ///
1036    /// # Errors
1037    /// Returns [`ClusterError`] on a malformed structure or missing required field.
1038    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
1039        let mut f_fabric_index: Option<u8> = None;
1040        let mut f_fabric_binding_version: Option<u8> = None;
1041        let mut f_signature: Option<Vec<u8>> = None;
1042        loop {
1043            match r.next()? {
1044                Some(Element::ContainerEnd) => break,
1045                Some(Element::Scalar {
1046                    tag: Tag::Context(0),
1047                    value: Value::Uint(v),
1048                }) => {
1049                    f_fabric_index = Some(
1050                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
1051                    )
1052                }
1053                Some(Element::Scalar {
1054                    tag: Tag::Context(1),
1055                    value: Value::Uint(v),
1056                }) => {
1057                    f_fabric_binding_version = Some(
1058                        u8::try_from(v)
1059                            .map_err(|_| ClusterError::InvalidLength("FabricBindingVersion"))?,
1060                    )
1061                }
1062                Some(Element::Scalar {
1063                    tag: Tag::Context(2),
1064                    value: Value::Bytes(v),
1065                }) => f_signature = Some(v),
1066                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
1067                Some(Element::ContainerStart { .. }) => r.skip_container()?,
1068                Some(_) => {} // unknown/future scalar — skip
1069            }
1070        }
1071        Ok(Self {
1072            fabric_index: f_fabric_index.ok_or(ClusterError::MissingField("FabricIndex"))?,
1073            fabric_binding_version: f_fabric_binding_version
1074                .ok_or(ClusterError::MissingField("FabricBindingVersion"))?,
1075            signature: f_signature.ok_or(ClusterError::MissingField("Signature"))?,
1076        })
1077    }
1078    /// Decode from a standalone anonymous TLV structure.
1079    ///
1080    /// # Errors
1081    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
1082    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
1083        let mut r = TlvReader::new(tlv);
1084        match r.next()? {
1085            Some(Element::ContainerStart {
1086                kind: ContainerKind::Structure,
1087                ..
1088            }) => {}
1089            _ => {
1090                return Err(ClusterError::UnexpectedType {
1091                    context: "SignVidVerificationResponse",
1092                })
1093            }
1094        }
1095        Self::decode_from(&mut r)
1096    }
1097}