#![allow(
clippy::all,
clippy::pedantic,
dead_code,
unreachable_pub,
unused_imports
)]
use crate::datatypes::SemanticTagStruct;
use crate::error::ClusterError;
use crate::types::Nullable;
use matter_codec::{ContainerKind, Element, Tag, TlvReader, TlvWriter, Value};
pub const CLUSTER_ID: u32 = 0x003E;
pub const CLUSTER_REVISION: u16 = 2;
pub mod command_id {
pub const ATTESTATION_REQUEST: u32 = 0x00;
pub const ATTESTATION_RESPONSE: u32 = 0x01;
pub const CERTIFICATE_CHAIN_REQUEST: u32 = 0x02;
pub const CERTIFICATE_CHAIN_RESPONSE: u32 = 0x03;
pub const CSR_REQUEST: u32 = 0x04;
pub const CSR_RESPONSE: u32 = 0x05;
pub const ADD_NOC: u32 = 0x06;
pub const UPDATE_NOC: u32 = 0x07;
pub const NOC_RESPONSE: u32 = 0x08;
pub const UPDATE_FABRIC_LABEL: u32 = 0x09;
pub const REMOVE_FABRIC: u32 = 0x0A;
pub const ADD_TRUSTED_ROOT_CERTIFICATE: u32 = 0x0B;
pub const SET_VID_VERIFICATION_STATEMENT: u32 = 0x0C;
pub const SIGN_VID_VERIFICATION_REQUEST: u32 = 0x0D;
pub const SIGN_VID_VERIFICATION_RESPONSE: u32 = 0x0E;
}
pub mod attribute_id {
pub const NOCS: u32 = 0x0000;
pub const FABRICS: u32 = 0x0001;
pub const SUPPORTED_FABRICS: u32 = 0x0002;
pub const COMMISSIONED_FABRICS: u32 = 0x0003;
pub const TRUSTED_ROOT_CERTIFICATES: u32 = 0x0004;
pub const CURRENT_FABRIC_INDEX: u32 = 0x0005;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum CertificateChainTypeEnum {
DacCertificate,
PaiCertificate,
Unknown(u8),
}
impl CertificateChainTypeEnum {
#[must_use]
pub fn from_raw(v: u8) -> Self {
match v {
1 => Self::DacCertificate,
2 => Self::PaiCertificate,
other => Self::Unknown(other),
}
}
#[must_use]
pub fn to_raw(self) -> u8 {
match self {
Self::DacCertificate => 1,
Self::PaiCertificate => 2,
Self::Unknown(v) => v,
}
}
}
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct FabricDescriptorStruct {
pub root_public_key: Vec<u8>,
pub vendor_id: u16,
pub fabric_id: u64,
pub node_id: u64,
pub label: String,
pub vid_verification_statement: Option<Vec<u8>>,
pub fabric_index: u8,
}
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct NOCStruct {
pub noc: Vec<u8>,
pub icac: Nullable<Vec<u8>>,
pub vvsc: Option<Vec<u8>>,
pub fabric_index: u8,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum NodeOperationalCertStatusEnum {
Ok,
InvalidPublicKey,
InvalidNodeOpId,
InvalidNoc,
MissingCsr,
TableFull,
InvalidAdminSubject,
FabricConflict,
LabelConflict,
InvalidFabricIndex,
Unknown(u8),
}
impl NodeOperationalCertStatusEnum {
#[must_use]
pub fn from_raw(v: u8) -> Self {
match v {
0 => Self::Ok,
1 => Self::InvalidPublicKey,
2 => Self::InvalidNodeOpId,
3 => Self::InvalidNoc,
4 => Self::MissingCsr,
5 => Self::TableFull,
6 => Self::InvalidAdminSubject,
9 => Self::FabricConflict,
10 => Self::LabelConflict,
11 => Self::InvalidFabricIndex,
other => Self::Unknown(other),
}
}
#[must_use]
pub fn to_raw(self) -> u8 {
match self {
Self::Ok => 0,
Self::InvalidPublicKey => 1,
Self::InvalidNodeOpId => 2,
Self::InvalidNoc => 3,
Self::MissingCsr => 4,
Self::TableFull => 5,
Self::InvalidAdminSubject => 6,
Self::FabricConflict => 9,
Self::LabelConflict => 10,
Self::InvalidFabricIndex => 11,
Self::Unknown(v) => v,
}
}
}
impl FabricDescriptorStruct {
pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
let mut f_root_public_key: Option<Vec<u8>> = None;
let mut f_vendor_id: Option<u16> = None;
let mut f_fabric_id: Option<u64> = None;
let mut f_node_id: Option<u64> = None;
let mut f_label: Option<String> = None;
let mut f_vid_verification_statement: Option<Vec<u8>> = None;
let mut f_fabric_index: Option<u8> = None;
loop {
match r.next()? {
Some(Element::ContainerEnd) => break,
Some(Element::Scalar {
tag: Tag::Context(1),
value: Value::Bytes(v),
}) => f_root_public_key = Some(v),
Some(Element::Scalar {
tag: Tag::Context(2),
value: Value::Uint(v),
}) => {
f_vendor_id = Some(
u16::try_from(v).map_err(|_| ClusterError::InvalidLength("VendorId"))?,
)
}
Some(Element::Scalar {
tag: Tag::Context(3),
value: Value::Uint(v),
}) => {
f_fabric_id = Some(
u64::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricId"))?,
)
}
Some(Element::Scalar {
tag: Tag::Context(4),
value: Value::Uint(v),
}) => {
f_node_id =
Some(u64::try_from(v).map_err(|_| ClusterError::InvalidLength("NodeId"))?)
}
Some(Element::Scalar {
tag: Tag::Context(5),
value: Value::Utf8(v),
}) => f_label = Some(v),
Some(Element::Scalar {
tag: Tag::Context(6),
value: Value::Bytes(v),
}) => f_vid_verification_statement = Some(v),
Some(Element::Scalar {
tag: Tag::Context(254),
value: Value::Uint(v),
}) => {
f_fabric_index = Some(
u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
)
}
None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
Some(Element::ContainerStart { .. }) => r.skip_container()?,
Some(_) => {} }
}
Ok(Self {
root_public_key: f_root_public_key
.ok_or(ClusterError::MissingField("RootPublicKey"))?,
vendor_id: f_vendor_id.ok_or(ClusterError::MissingField("VendorId"))?,
fabric_id: f_fabric_id.ok_or(ClusterError::MissingField("FabricId"))?,
node_id: f_node_id.ok_or(ClusterError::MissingField("NodeId"))?,
label: f_label.ok_or(ClusterError::MissingField("Label"))?,
vid_verification_statement: f_vid_verification_statement,
fabric_index: f_fabric_index.ok_or(ClusterError::MissingField("FabricIndex"))?,
})
}
pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::ContainerStart {
kind: ContainerKind::Structure,
..
}) => {}
_ => {
return Err(ClusterError::UnexpectedType {
context: "FabricDescriptorStruct",
})
}
}
Self::decode_from(&mut r)
}
#[allow(clippy::expect_used)] pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
w.put_bytes(Tag::Context(1), &self.root_public_key)
.expect("infallible: vec writer");
w.put_uint(Tag::Context(2), u64::from(self.vendor_id))
.expect("infallible: vec writer");
w.put_uint(Tag::Context(3), u64::from(self.fabric_id))
.expect("infallible: vec writer");
w.put_uint(Tag::Context(4), u64::from(self.node_id))
.expect("infallible: vec writer");
w.put_utf8(Tag::Context(5), &self.label)
.expect("infallible: vec writer");
if let Some(vid_verification_statement) = &self.vid_verification_statement {
w.put_bytes(Tag::Context(6), &*vid_verification_statement)
.expect("infallible: vec writer");
}
w.put_uint(Tag::Context(254), u64::from(self.fabric_index))
.expect("infallible: vec writer");
}
#[must_use]
#[allow(clippy::expect_used)] pub fn encode(&self) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous)
.expect("infallible: vec writer");
self.write_fields(&mut w);
w.end_container().expect("infallible: vec writer");
buf
}
}
impl NOCStruct {
pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
let mut f_noc: Option<Vec<u8>> = None;
let mut f_icac: Option<Nullable<Vec<u8>>> = None;
let mut f_vvsc: Option<Vec<u8>> = None;
let mut f_fabric_index: Option<u8> = None;
loop {
match r.next()? {
Some(Element::ContainerEnd) => break,
Some(Element::Scalar {
tag: Tag::Context(1),
value: Value::Bytes(v),
}) => f_noc = Some(v),
Some(Element::Scalar {
tag: Tag::Context(2),
value: Value::Null,
}) => f_icac = Some(Nullable::Null),
Some(Element::Scalar {
tag: Tag::Context(2),
value: Value::Bytes(v),
}) => f_icac = Some(Nullable::Value(v)),
Some(Element::Scalar {
tag: Tag::Context(3),
value: Value::Bytes(v),
}) => f_vvsc = Some(v),
Some(Element::Scalar {
tag: Tag::Context(254),
value: Value::Uint(v),
}) => {
f_fabric_index = Some(
u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
)
}
None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
Some(Element::ContainerStart { .. }) => r.skip_container()?,
Some(_) => {} }
}
Ok(Self {
noc: f_noc.ok_or(ClusterError::MissingField("Noc"))?,
icac: f_icac.ok_or(ClusterError::MissingField("Icac"))?,
vvsc: f_vvsc,
fabric_index: f_fabric_index.ok_or(ClusterError::MissingField("FabricIndex"))?,
})
}
pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::ContainerStart {
kind: ContainerKind::Structure,
..
}) => {}
_ => {
return Err(ClusterError::UnexpectedType {
context: "NOCStruct",
})
}
}
Self::decode_from(&mut r)
}
#[allow(clippy::expect_used)] pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
w.put_bytes(Tag::Context(1), &self.noc)
.expect("infallible: vec writer");
match &self.icac {
Nullable::Null => w.put_null(Tag::Context(2)).expect("infallible: vec writer"),
Nullable::Value(icac) => {
w.put_bytes(Tag::Context(2), &*icac)
.expect("infallible: vec writer");
}
}
if let Some(vvsc) = &self.vvsc {
w.put_bytes(Tag::Context(3), &*vvsc)
.expect("infallible: vec writer");
}
w.put_uint(Tag::Context(254), u64::from(self.fabric_index))
.expect("infallible: vec writer");
}
#[must_use]
#[allow(clippy::expect_used)] pub fn encode(&self) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous)
.expect("infallible: vec writer");
self.write_fields(&mut w);
w.end_container().expect("infallible: vec writer");
buf
}
}
pub fn decode_nocs(tlv: &[u8]) -> Result<Vec<NOCStruct>, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::ContainerStart {
kind: ContainerKind::Array,
..
}) => {}
_ => return Err(ClusterError::UnexpectedType { context: "Nocs" }),
}
let r = &mut r;
let mut out = Vec::new();
loop {
match r.next()? {
Some(Element::ContainerEnd) => break,
Some(Element::ContainerStart {
kind: ContainerKind::Structure,
..
}) => {
out.push(NOCStruct::decode_from(r)?);
}
None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
Some(Element::ContainerStart { .. }) => r.skip_container()?,
Some(_) => {} }
}
Ok(out)
}
pub fn decode_fabrics(tlv: &[u8]) -> Result<Vec<FabricDescriptorStruct>, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::ContainerStart {
kind: ContainerKind::Array,
..
}) => {}
_ => return Err(ClusterError::UnexpectedType { context: "Fabrics" }),
}
let r = &mut r;
let mut out = Vec::new();
loop {
match r.next()? {
Some(Element::ContainerEnd) => break,
Some(Element::ContainerStart {
kind: ContainerKind::Structure,
..
}) => {
out.push(FabricDescriptorStruct::decode_from(r)?);
}
None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
Some(Element::ContainerStart { .. }) => r.skip_container()?,
Some(_) => {} }
}
Ok(out)
}
pub fn decode_supported_fabrics(tlv: &[u8]) -> Result<u8, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::Scalar {
value: Value::Uint(v),
..
}) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("SupportedFabrics"))?),
_ => Err(ClusterError::UnexpectedType {
context: "SupportedFabrics",
}),
}
}
pub fn decode_commissioned_fabrics(tlv: &[u8]) -> Result<u8, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::Scalar {
value: Value::Uint(v),
..
}) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("CommissionedFabrics"))?),
_ => Err(ClusterError::UnexpectedType {
context: "CommissionedFabrics",
}),
}
}
pub fn decode_trusted_root_certificates(tlv: &[u8]) -> Result<Vec<Vec<u8>>, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::ContainerStart {
kind: ContainerKind::Array,
..
}) => {}
_ => {
return Err(ClusterError::UnexpectedType {
context: "TrustedRootCertificates",
})
}
}
let r = &mut r;
let mut out = Vec::new();
loop {
match r.next()? {
Some(Element::ContainerEnd) => break,
Some(Element::Scalar {
value: Value::Bytes(v),
..
}) => out.push(v),
None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
Some(Element::ContainerStart { .. }) => r.skip_container()?,
Some(_) => {} }
}
Ok(out)
}
pub fn decode_current_fabric_index(tlv: &[u8]) -> Result<u8, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::Scalar {
value: Value::Uint(v),
..
}) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("CurrentFabricIndex"))?),
_ => Err(ClusterError::UnexpectedType {
context: "CurrentFabricIndex",
}),
}
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_attestation_request(attestation_nonce: &Vec<u8>) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous)
.expect("infallible: vec writer");
w.put_bytes(Tag::Context(0), &attestation_nonce)
.expect("infallible: vec writer");
w.end_container().expect("infallible: vec writer");
buf
}
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct AttestationResponse {
pub attestation_elements: Vec<u8>,
pub attestation_signature: Vec<u8>,
}
impl AttestationResponse {
pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
let mut f_attestation_elements: Option<Vec<u8>> = None;
let mut f_attestation_signature: Option<Vec<u8>> = None;
loop {
match r.next()? {
Some(Element::ContainerEnd) => break,
Some(Element::Scalar {
tag: Tag::Context(0),
value: Value::Bytes(v),
}) => f_attestation_elements = Some(v),
Some(Element::Scalar {
tag: Tag::Context(1),
value: Value::Bytes(v),
}) => f_attestation_signature = Some(v),
None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
Some(Element::ContainerStart { .. }) => r.skip_container()?,
Some(_) => {} }
}
Ok(Self {
attestation_elements: f_attestation_elements
.ok_or(ClusterError::MissingField("AttestationElements"))?,
attestation_signature: f_attestation_signature
.ok_or(ClusterError::MissingField("AttestationSignature"))?,
})
}
pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::ContainerStart {
kind: ContainerKind::Structure,
..
}) => {}
_ => {
return Err(ClusterError::UnexpectedType {
context: "AttestationResponse",
})
}
}
Self::decode_from(&mut r)
}
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_certificate_chain_request(certificate_type: CertificateChainTypeEnum) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous)
.expect("infallible: vec writer");
w.put_uint(Tag::Context(0), u64::from(certificate_type.to_raw()))
.expect("infallible: vec writer");
w.end_container().expect("infallible: vec writer");
buf
}
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct CertificateChainResponse {
pub certificate: Vec<u8>,
}
impl CertificateChainResponse {
pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
let mut f_certificate: Option<Vec<u8>> = None;
loop {
match r.next()? {
Some(Element::ContainerEnd) => break,
Some(Element::Scalar {
tag: Tag::Context(0),
value: Value::Bytes(v),
}) => f_certificate = Some(v),
None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
Some(Element::ContainerStart { .. }) => r.skip_container()?,
Some(_) => {} }
}
Ok(Self {
certificate: f_certificate.ok_or(ClusterError::MissingField("Certificate"))?,
})
}
pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::ContainerStart {
kind: ContainerKind::Structure,
..
}) => {}
_ => {
return Err(ClusterError::UnexpectedType {
context: "CertificateChainResponse",
})
}
}
Self::decode_from(&mut r)
}
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_csr_request(csr_nonce: &Vec<u8>, is_for_update_noc: Option<bool>) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous)
.expect("infallible: vec writer");
w.put_bytes(Tag::Context(0), &csr_nonce)
.expect("infallible: vec writer");
if let Some(is_for_update_noc) = is_for_update_noc {
w.put_bool(Tag::Context(1), is_for_update_noc)
.expect("infallible: vec writer");
}
w.end_container().expect("infallible: vec writer");
buf
}
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct CsrResponse {
pub nocsr_elements: Vec<u8>,
pub attestation_signature: Vec<u8>,
}
impl CsrResponse {
pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
let mut f_nocsr_elements: Option<Vec<u8>> = None;
let mut f_attestation_signature: Option<Vec<u8>> = None;
loop {
match r.next()? {
Some(Element::ContainerEnd) => break,
Some(Element::Scalar {
tag: Tag::Context(0),
value: Value::Bytes(v),
}) => f_nocsr_elements = Some(v),
Some(Element::Scalar {
tag: Tag::Context(1),
value: Value::Bytes(v),
}) => f_attestation_signature = Some(v),
None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
Some(Element::ContainerStart { .. }) => r.skip_container()?,
Some(_) => {} }
}
Ok(Self {
nocsr_elements: f_nocsr_elements.ok_or(ClusterError::MissingField("NocsrElements"))?,
attestation_signature: f_attestation_signature
.ok_or(ClusterError::MissingField("AttestationSignature"))?,
})
}
pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::ContainerStart {
kind: ContainerKind::Structure,
..
}) => {}
_ => {
return Err(ClusterError::UnexpectedType {
context: "CsrResponse",
})
}
}
Self::decode_from(&mut r)
}
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_add_noc(
noc_value: &Vec<u8>,
icac_value: Option<Vec<u8>>,
ipk_value: &Vec<u8>,
case_admin_subject: u64,
admin_vendor_id: u16,
) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous)
.expect("infallible: vec writer");
w.put_bytes(Tag::Context(0), &noc_value)
.expect("infallible: vec writer");
if let Some(icac_value) = icac_value {
w.put_bytes(Tag::Context(1), &icac_value)
.expect("infallible: vec writer");
}
w.put_bytes(Tag::Context(2), &ipk_value)
.expect("infallible: vec writer");
w.put_uint(Tag::Context(3), u64::from(case_admin_subject))
.expect("infallible: vec writer");
w.put_uint(Tag::Context(4), u64::from(admin_vendor_id))
.expect("infallible: vec writer");
w.end_container().expect("infallible: vec writer");
buf
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_update_noc(noc_value: &Vec<u8>, icac_value: Option<Vec<u8>>) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous)
.expect("infallible: vec writer");
w.put_bytes(Tag::Context(0), &noc_value)
.expect("infallible: vec writer");
if let Some(icac_value) = icac_value {
w.put_bytes(Tag::Context(1), &icac_value)
.expect("infallible: vec writer");
}
w.end_container().expect("infallible: vec writer");
buf
}
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct NocResponse {
pub status_code: NodeOperationalCertStatusEnum,
pub fabric_index: Option<u8>,
pub debug_text: Option<String>,
}
impl NocResponse {
pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
let mut f_status_code: Option<NodeOperationalCertStatusEnum> = None;
let mut f_fabric_index: Option<u8> = None;
let mut f_debug_text: Option<String> = None;
loop {
match r.next()? {
Some(Element::ContainerEnd) => break,
Some(Element::Scalar {
tag: Tag::Context(0),
value: Value::Uint(v),
}) => {
f_status_code = Some(NodeOperationalCertStatusEnum::from_raw(
u8::try_from(v).map_err(|_| ClusterError::InvalidLength("StatusCode"))?,
))
}
Some(Element::Scalar {
tag: Tag::Context(1),
value: Value::Uint(v),
}) => {
f_fabric_index = Some(
u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
)
}
Some(Element::Scalar {
tag: Tag::Context(2),
value: Value::Utf8(v),
}) => f_debug_text = Some(v),
None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
Some(Element::ContainerStart { .. }) => r.skip_container()?,
Some(_) => {} }
}
Ok(Self {
status_code: f_status_code.ok_or(ClusterError::MissingField("StatusCode"))?,
fabric_index: f_fabric_index,
debug_text: f_debug_text,
})
}
pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::ContainerStart {
kind: ContainerKind::Structure,
..
}) => {}
_ => {
return Err(ClusterError::UnexpectedType {
context: "NocResponse",
})
}
}
Self::decode_from(&mut r)
}
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_update_fabric_label(label: &String) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous)
.expect("infallible: vec writer");
w.put_utf8(Tag::Context(0), &label)
.expect("infallible: vec writer");
w.end_container().expect("infallible: vec writer");
buf
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_remove_fabric(fabric_index: u8) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous)
.expect("infallible: vec writer");
w.put_uint(Tag::Context(0), u64::from(fabric_index))
.expect("infallible: vec writer");
w.end_container().expect("infallible: vec writer");
buf
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_add_trusted_root_certificate(root_ca_certificate: &Vec<u8>) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous)
.expect("infallible: vec writer");
w.put_bytes(Tag::Context(0), &root_ca_certificate)
.expect("infallible: vec writer");
w.end_container().expect("infallible: vec writer");
buf
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_set_vid_verification_statement(
vendor_id: Option<u16>,
vid_verification_statement: Option<Vec<u8>>,
vvsc: Option<Vec<u8>>,
) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous)
.expect("infallible: vec writer");
if let Some(vendor_id) = vendor_id {
w.put_uint(Tag::Context(0), u64::from(vendor_id))
.expect("infallible: vec writer");
}
if let Some(vid_verification_statement) = vid_verification_statement {
w.put_bytes(Tag::Context(1), &vid_verification_statement)
.expect("infallible: vec writer");
}
if let Some(vvsc) = vvsc {
w.put_bytes(Tag::Context(2), &vvsc)
.expect("infallible: vec writer");
}
w.end_container().expect("infallible: vec writer");
buf
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_sign_vid_verification_request(
fabric_index: u8,
client_challenge: &Vec<u8>,
) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous)
.expect("infallible: vec writer");
w.put_uint(Tag::Context(0), u64::from(fabric_index))
.expect("infallible: vec writer");
w.put_bytes(Tag::Context(1), &client_challenge)
.expect("infallible: vec writer");
w.end_container().expect("infallible: vec writer");
buf
}
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct SignVidVerificationResponse {
pub fabric_index: u8,
pub fabric_binding_version: u8,
pub signature: Vec<u8>,
}
impl SignVidVerificationResponse {
pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
let mut f_fabric_index: Option<u8> = None;
let mut f_fabric_binding_version: Option<u8> = None;
let mut f_signature: Option<Vec<u8>> = None;
loop {
match r.next()? {
Some(Element::ContainerEnd) => break,
Some(Element::Scalar {
tag: Tag::Context(0),
value: Value::Uint(v),
}) => {
f_fabric_index = Some(
u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
)
}
Some(Element::Scalar {
tag: Tag::Context(1),
value: Value::Uint(v),
}) => {
f_fabric_binding_version = Some(
u8::try_from(v)
.map_err(|_| ClusterError::InvalidLength("FabricBindingVersion"))?,
)
}
Some(Element::Scalar {
tag: Tag::Context(2),
value: Value::Bytes(v),
}) => f_signature = Some(v),
None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
Some(Element::ContainerStart { .. }) => r.skip_container()?,
Some(_) => {} }
}
Ok(Self {
fabric_index: f_fabric_index.ok_or(ClusterError::MissingField("FabricIndex"))?,
fabric_binding_version: f_fabric_binding_version
.ok_or(ClusterError::MissingField("FabricBindingVersion"))?,
signature: f_signature.ok_or(ClusterError::MissingField("Signature"))?,
})
}
pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::ContainerStart {
kind: ContainerKind::Structure,
..
}) => {}
_ => {
return Err(ClusterError::UnexpectedType {
context: "SignVidVerificationResponse",
})
}
}
Self::decode_from(&mut r)
}
}