matter-clusters 0.1.0

Matter protocol cluster definitions (generated from the spec).
Documentation
//! FixedLabel cluster (0x0040).
//! @generated by `cargo xtask codegen` — do not edit.

#![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};

/// Cluster ID.
pub const CLUSTER_ID: u32 = 0x0040;
/// Cluster revision.
pub const CLUSTER_REVISION: u16 = 1;

/// Command IDs (requests and responses).
pub mod command_id {}

/// Attribute IDs (cluster-specific).
pub mod attribute_id {
    /// `LabelList`.
    pub const LABEL_LIST: u32 = 0x0000;
}

/// `LabelStruct` struct.
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct LabelStruct {
    /// Field Label (tag 0).
    pub label: String,
    /// Field Value (tag 1).
    pub value: String,
}

impl LabelStruct {
    /// Decode the fields of an already-opened anonymous structure
    /// (reader positioned after the struct start; consumes to its end).
    ///
    /// # Errors
    /// Returns [`ClusterError`] on a malformed structure or missing required field.
    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
        let mut f_label: Option<String> = None;
        let mut f_value: Option<String> = None;
        loop {
            match r.next()? {
                Some(Element::ContainerEnd) => break,
                Some(Element::Scalar {
                    tag: Tag::Context(0),
                    value: Value::Utf8(v),
                }) => f_label = Some(v),
                Some(Element::Scalar {
                    tag: Tag::Context(1),
                    value: Value::Utf8(v),
                }) => f_value = Some(v),
                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
                Some(Element::ContainerStart { .. }) => r.skip_container()?,
                Some(_) => {} // unknown/future scalar — skip
            }
        }
        Ok(Self {
            label: f_label.ok_or(ClusterError::MissingField("Label"))?,
            value: f_value.ok_or(ClusterError::MissingField("Value"))?,
        })
    }
    /// Decode from a standalone anonymous TLV structure.
    ///
    /// # Errors
    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
    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: "LabelStruct",
                })
            }
        }
        Self::decode_from(&mut r)
    }
    /// Write this struct's fields into an already-open container.
    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
    pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
        w.put_utf8(Tag::Context(0), &self.label)
            .expect("infallible: vec writer");
        w.put_utf8(Tag::Context(1), &self.value)
            .expect("infallible: vec writer");
    }
    /// Encode as a standalone anonymous TLV structure.
    #[must_use]
    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
    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
    }
}

/// Decode the `LabelList` attribute value.
///
/// # Errors
/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
pub fn decode_label_list(tlv: &[u8]) -> Result<Vec<LabelStruct>, ClusterError> {
    let mut r = TlvReader::new(tlv);
    match r.next()? {
        Some(Element::ContainerStart {
            kind: ContainerKind::Array,
            ..
        }) => {}
        _ => {
            return Err(ClusterError::UnexpectedType {
                context: "LabelList",
            })
        }
    }
    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(LabelStruct::decode_from(r)?);
            }
            None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
            Some(Element::ContainerStart { .. }) => r.skip_container()?,
            Some(_) => {} // skip unknown scalar
        }
    }
    Ok(out)
}