#![forbid(unsafe_code)]
use crate::error::ImError;
use matter_codec::{Tag, Value};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct CommandPath {
pub endpoint: u16,
pub cluster: u32,
pub command: u32,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct AttributePath {
pub endpoint: u16,
pub cluster: u32,
pub attribute: u32,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
pub struct ReadPath {
pub endpoint: Option<u16>,
pub cluster: Option<u32>,
pub attribute: Option<u32>,
}
impl ReadPath {
#[must_use]
pub fn concrete(endpoint: u16, cluster: u32, attribute: u32) -> Self {
Self {
endpoint: Some(endpoint),
cluster: Some(cluster),
attribute: Some(attribute),
}
}
#[must_use]
pub fn cluster(endpoint: u16, cluster: u32) -> Self {
Self {
endpoint: Some(endpoint),
cluster: Some(cluster),
attribute: None,
}
}
#[must_use]
pub fn all() -> Self {
Self {
endpoint: None,
cluster: None,
attribute: None,
}
}
}
impl From<AttributePath> for ReadPath {
fn from(p: AttributePath) -> Self {
Self {
endpoint: Some(p.endpoint),
cluster: Some(p.cluster),
attribute: Some(p.attribute),
}
}
}
pub(crate) fn attribute_path_from_value(
members: &[(Tag, Value)],
) -> Result<AttributePath, ImError> {
let mut endpoint = None;
let mut cluster = None;
let mut attribute = None;
for (tag, v) in members {
match (tag, v) {
(Tag::Context(2), Value::Uint(n)) => {
endpoint =
Some(u16::try_from(*n).map_err(|_| {
ImError::UnexpectedValue("AttributePath.endpoint exceeds u16")
})?);
}
(Tag::Context(3), Value::Uint(n)) => {
cluster =
Some(u32::try_from(*n).map_err(|_| {
ImError::UnexpectedValue("AttributePath.cluster exceeds u32")
})?);
}
(Tag::Context(4), Value::Uint(n)) => {
attribute = Some(u32::try_from(*n).map_err(|_| {
ImError::UnexpectedValue("AttributePath.attribute exceeds u32")
})?);
}
_ => {}
}
}
Ok(AttributePath {
endpoint: endpoint.ok_or(ImError::MissingField("AttributePath.endpoint"))?,
cluster: cluster.ok_or(ImError::MissingField("AttributePath.cluster"))?,
attribute: attribute.ok_or(ImError::MissingField("AttributePath.attribute"))?,
})
}
pub(crate) fn attribute_path_and_append_from_value(
members: &[(Tag, Value)],
) -> Result<(AttributePath, bool), ImError> {
let path = attribute_path_from_value(members)?;
let append = members
.iter()
.any(|(tag, v)| matches!(tag, Tag::Context(5)) && matches!(v, Value::Null));
Ok((path, append))
}