#![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 = 0xFC00;
pub const CLUSTER_REVISION: u16 = 1;
pub mod command_id {
pub const RESET: u32 = 0x00;
pub const SET_LEVEL: u32 = 0x01;
pub const SET_LEVEL_RESPONSE: u32 = 0x02;
pub const SET_POINT: u32 = 0x03;
}
pub mod attribute_id {
pub const SWITCH: u32 = 0x0000;
pub const LEVEL: u32 = 0x0001;
pub const MODE: u32 = 0x0002;
pub const FLAGS: u32 = 0x0003;
pub const LABEL: u32 = 0x0004;
pub const TOKEN: u32 = 0x0005;
pub const RAW_MODE: u32 = 0x0006;
pub const CAPS: u32 = 0x0007;
pub const POINT: u32 = 0x0008;
pub const IDS: u32 = 0x0009;
pub const POINTS: u32 = 0x000A;
}
bitflags::bitflags! {
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Feature: u32 {
const FA = 1 << 0;
const FB = 1 << 1;
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ModeEnum {
Auto,
Manual,
Unknown(u8),
}
impl ModeEnum {
#[must_use]
pub fn from_raw(v: u8) -> Self {
match v {
0 => Self::Auto,
1 => Self::Manual,
other => Self::Unknown(other),
}
}
#[must_use]
pub fn to_raw(self) -> u8 {
match self {
Self::Auto => 0,
Self::Manual => 1,
Self::Unknown(v) => v,
}
}
}
bitflags::bitflags! {
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct FlagsBitmap: u8 {
const ALPHA = 1 << 0;
const BETA = 1 << 1;
}
}
bitflags::bitflags! {
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct WideFlags: u16 {
const FIRST = 1 << 0;
const NINTH = 1 << 8;
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct PointStruct {
pub x: u16,
pub y: u16,
}
impl PointStruct {
pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
let mut f_x: Option<u16> = None;
let mut f_y: Option<u16> = None;
loop {
match r.next()? {
Some(Element::ContainerEnd) => break,
Some(Element::Scalar {
tag: Tag::Context(0),
value: Value::Uint(v),
}) => f_x = Some(u16::try_from(v).map_err(|_| ClusterError::InvalidLength("X"))?),
Some(Element::Scalar {
tag: Tag::Context(1),
value: Value::Uint(v),
}) => f_y = Some(u16::try_from(v).map_err(|_| ClusterError::InvalidLength("Y"))?),
None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
Some(Element::ContainerStart { .. }) => r.skip_container()?,
Some(_) => {} }
}
Ok(Self {
x: f_x.ok_or(ClusterError::MissingField("X"))?,
y: f_y.ok_or(ClusterError::MissingField("Y"))?,
})
}
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: "PointStruct",
})
}
}
Self::decode_from(&mut r)
}
#[allow(clippy::expect_used)] pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
w.put_uint(Tag::Context(0), u64::from(self.x))
.expect("infallible: vec writer");
w.put_uint(Tag::Context(1), u64::from(self.y))
.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_switch(tlv: &[u8]) -> Result<bool, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::Scalar {
value: Value::Bool(v),
..
}) => Ok(v),
_ => Err(ClusterError::UnexpectedType { context: "Switch" }),
}
}
pub fn decode_level(tlv: &[u8]) -> Result<Nullable<u16>, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::Scalar {
value: Value::Null, ..
}) => Ok(Nullable::Null),
Some(Element::Scalar {
value: Value::Uint(v),
..
}) => Ok(Nullable::Value(
u16::try_from(v).map_err(|_| ClusterError::InvalidLength("Level"))?,
)),
_ => Err(ClusterError::UnexpectedType { context: "Level" }),
}
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_level(value: Nullable<u16>) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
match value {
Nullable::Null => w.put_null(Tag::Anonymous).expect("infallible: vec writer"),
Nullable::Value(value) => {
w.put_uint(Tag::Anonymous, u64::from(value))
.expect("infallible: vec writer");
}
}
buf
}
pub fn decode_mode(tlv: &[u8]) -> Result<ModeEnum, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::Scalar {
value: Value::Uint(v),
..
}) => Ok(ModeEnum::from_raw(
u8::try_from(v).map_err(|_| ClusterError::InvalidLength("Mode"))?,
)),
_ => Err(ClusterError::UnexpectedType { context: "Mode" }),
}
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_mode(value: ModeEnum) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.put_uint(Tag::Anonymous, u64::from(value.to_raw()))
.expect("infallible: vec writer");
buf
}
pub fn decode_flags(tlv: &[u8]) -> Result<FlagsBitmap, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::Scalar {
value: Value::Uint(v),
..
}) => Ok(FlagsBitmap::from_bits_retain(
u8::try_from(v).map_err(|_| ClusterError::InvalidLength("Flags"))?,
)),
_ => Err(ClusterError::UnexpectedType { context: "Flags" }),
}
}
pub fn decode_label(tlv: &[u8]) -> Result<String, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::Scalar {
value: Value::Utf8(v),
..
}) => Ok(v),
_ => Err(ClusterError::UnexpectedType { context: "Label" }),
}
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_label(value: &String) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.put_utf8(Tag::Anonymous, &value)
.expect("infallible: vec writer");
buf
}
pub fn decode_token(tlv: &[u8]) -> Result<Vec<u8>, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::Scalar {
value: Value::Bytes(v),
..
}) => Ok(v),
_ => Err(ClusterError::UnexpectedType { context: "Token" }),
}
}
pub fn decode_raw_mode(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("RawMode"))?),
_ => Err(ClusterError::UnexpectedType { context: "RawMode" }),
}
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_raw_mode(value: u8) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.put_uint(Tag::Anonymous, u64::from(value))
.expect("infallible: vec writer");
buf
}
pub fn decode_caps(tlv: &[u8]) -> Result<WideFlags, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::Scalar {
value: Value::Uint(v),
..
}) => Ok(WideFlags::from_bits_retain(
u16::try_from(v).map_err(|_| ClusterError::InvalidLength("Caps"))?,
)),
_ => Err(ClusterError::UnexpectedType { context: "Caps" }),
}
}
pub fn decode_point(tlv: &[u8]) -> Result<PointStruct, ClusterError> {
PointStruct::decode(tlv)
}
pub fn decode_ids(tlv: &[u8]) -> Result<Vec<u32>, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::ContainerStart {
kind: ContainerKind::Array,
..
}) => {}
_ => return Err(ClusterError::UnexpectedType { context: "Ids" }),
}
let r = &mut r;
let mut out = Vec::new();
loop {
match r.next()? {
Some(Element::ContainerEnd) => break,
Some(Element::Scalar {
value: Value::Uint(v),
..
}) => out.push(u32::try_from(v).map_err(|_| ClusterError::InvalidLength("Ids"))?),
None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
Some(Element::ContainerStart { .. }) => r.skip_container()?,
Some(_) => {} }
}
Ok(out)
}
pub fn decode_points(tlv: &[u8]) -> Result<Vec<PointStruct>, ClusterError> {
let mut r = TlvReader::new(tlv);
match r.next()? {
Some(Element::ContainerStart {
kind: ContainerKind::Array,
..
}) => {}
_ => return Err(ClusterError::UnexpectedType { context: "Points" }),
}
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(PointStruct::decode_from(r)?);
}
None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
Some(Element::ContainerStart { .. }) => r.skip_container()?,
Some(_) => {} }
}
Ok(out)
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_reset() -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous)
.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_level(target: u16, mode: Option<ModeEnum>) -> 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(target))
.expect("infallible: vec writer");
if let Some(mode) = mode {
w.put_uint(Tag::Context(1), u64::from(mode.to_raw()))
.expect("infallible: vec writer");
}
w.end_container().expect("infallible: vec writer");
buf
}
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct SetLevelResponse {
pub status: u8,
pub reached: Option<u16>,
}
impl SetLevelResponse {
pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
let mut f_status: Option<u8> = None;
let mut f_reached: Option<u16> = None;
loop {
match r.next()? {
Some(Element::ContainerEnd) => break,
Some(Element::Scalar {
tag: Tag::Context(0),
value: Value::Uint(v),
}) => {
f_status =
Some(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("Status"))?)
}
Some(Element::Scalar {
tag: Tag::Context(1),
value: Value::Uint(v),
}) => {
f_reached =
Some(u16::try_from(v).map_err(|_| ClusterError::InvalidLength("Reached"))?)
}
None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
Some(Element::ContainerStart { .. }) => r.skip_container()?,
Some(_) => {} }
}
Ok(Self {
status: f_status.ok_or(ClusterError::MissingField("Status"))?,
reached: f_reached,
})
}
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: "SetLevelResponse",
})
}
}
Self::decode_from(&mut r)
}
}
#[must_use]
#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_set_point(point: PointStruct) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous)
.expect("infallible: vec writer");
w.start_structure(Tag::Context(0))
.expect("infallible: vec writer");
point.write_fields(&mut w);
w.end_container().expect("infallible: vec writer");
w.end_container().expect("infallible: vec writer");
buf
}