Skip to content

Commit

Permalink
Explicit path expansion iterator
Browse files Browse the repository at this point in the history
  • Loading branch information
ivmarkov committed Sep 25, 2024
1 parent 850e02a commit dde3d9a
Show file tree
Hide file tree
Showing 5 changed files with 813 additions and 472 deletions.
22 changes: 13 additions & 9 deletions rs-matter/src/data_model/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,7 @@ where
// Will the clusters that are to be invoked await?
let mut awaits = false;

for item in metadata
.node()
.read(&req, None, &exchange.accessor()?, true)?
{
for item in metadata.node().read(&req, &exchange.accessor()?)? {
if item?
.map(|attr| self.handler.read_awaits(exchange, &attr))
.unwrap_or(false)
Expand All @@ -175,7 +172,7 @@ where
// of the transport layer, as the operation won't await.

let node = metadata.node();
let mut attrs = node.read(&req, None, &accessor, true)?.peekable();
let mut attrs = node.read(&req, &accessor)?.peekable();

if !req
.respond(&self.handler, exchange, None, &mut attrs, &mut wb, true)
Expand Down Expand Up @@ -215,7 +212,7 @@ where
let req = ReportDataReq::Read(&req);

let node = metadata.node();
let mut attrs = node.read(&req, None, &accessor, true)?.peekable();
let mut attrs = node.read(&req, &accessor)?.peekable();

loop {
let more_chunks = req
Expand Down Expand Up @@ -624,15 +621,19 @@ where
let mut wb = WriteBuf::new(tx);

let req = SubscribeReqRef::new(TLVElement::new(rx));
let req = ReportDataReq::Subscribe(&req);
let req = if with_dataver {
ReportDataReq::Subscribe(&req)
} else {
ReportDataReq::SubscribeReport(&req)
};

let metadata = self.handler.lock().await;

let accessor = exchange.accessor()?;

{
let node = metadata.node();
let mut attrs = node.read(&req, None, &accessor, with_dataver)?.peekable();
let mut attrs = node.read(&req, &accessor)?.peekable();

loop {
let more_chunks = req
Expand Down Expand Up @@ -780,7 +781,10 @@ impl<'a> ReportDataReq<'a> {
tw.start_struct(&TLVTag::Anonymous)?;

if let Some(subscription_id) = subscription_id {
assert!(matches!(self, ReportDataReq::Subscribe(_)));
assert!(matches!(
self,
ReportDataReq::Subscribe(_) | ReportDataReq::SubscribeReport(_)
));
tw.u32(
&TLVTag::Context(ReportDataTag::SubscriptionId as u8),
subscription_id,
Expand Down
61 changes: 7 additions & 54 deletions rs-matter/src/data_model/objects/cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ pub struct Cluster<'a> {
}

impl<'a> Cluster<'a> {
/// Create a new cluster with the provided parameters.
pub const fn new(
id: ClusterId,
feature_map: u32,
Expand All @@ -207,60 +208,10 @@ impl<'a> Cluster<'a> {
}
}

pub fn match_attributes(
&self,
attr: Option<AttrId>,
) -> impl Iterator<Item = &'_ Attribute> + '_ {
self.attributes
.iter()
.filter(move |attribute| attr.map(|attr| attr == attribute.id).unwrap_or(true))
}

pub fn match_commands(&self, cmd: Option<CmdId>) -> impl Iterator<Item = CmdId> + '_ {
self.commands
.iter()
.filter(move |id| cmd.map(|cmd| **id == cmd).unwrap_or(true))
.copied()
}

pub fn check_attribute(
&self,
accessor: &Accessor,
ep: EndptId,
attr: AttrId,
write: bool,
) -> Result<(), IMStatusCode> {
let attribute = self
.attributes
.iter()
.find(|attribute| attribute.id == attr)
.ok_or(IMStatusCode::UnsupportedAttribute)?;

Self::check_attr_access(
accessor,
GenericPath::new(Some(ep), Some(self.id), Some(attr as _)),
write,
attribute.access,
)
}

pub fn check_command(
&self,
accessor: &Accessor,
ep: EndptId,
cmd: CmdId,
) -> Result<(), IMStatusCode> {
self.commands
.iter()
.find(|id| **id == cmd)
.ok_or(IMStatusCode::UnsupportedCommand)?;

Self::check_cmd_access(
accessor,
GenericPath::new(Some(ep), Some(self.id), Some(cmd)),
)
}

/// Check if the accessor has the required permissions to access the attribute
/// designated by the provided path.
///
/// if `write` is true, the operation is a write operation, otherwise it is a read operation.
pub(crate) fn check_attr_access(
accessor: &Accessor,
path: GenericPath,
Expand Down Expand Up @@ -289,6 +240,8 @@ impl<'a> Cluster<'a> {
}
}

/// Check if the accessor has the required permissions to access the command
/// designated by the provided path.
pub(crate) fn check_cmd_access(
accessor: &Accessor,
path: GenericPath,
Expand Down
67 changes: 11 additions & 56 deletions rs-matter/src/data_model/objects/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@
* limitations under the License.
*/

use crate::{acl::Accessor, interaction_model::core::IMStatusCode};

use core::fmt;

use super::{AttrId, Attribute, Cluster, ClusterId, CmdId, DeviceType, EndptId};
use super::{Cluster, DeviceType, EndptId};

#[derive(Debug, Clone)]
pub struct Endpoint<'a> {
Expand All @@ -29,59 +27,16 @@ pub struct Endpoint<'a> {
}

impl<'a> Endpoint<'a> {
pub fn match_attributes(
&self,
cl: Option<ClusterId>,
attr: Option<AttrId>,
) -> impl Iterator<Item = (&'_ Cluster, &'_ Attribute)> + '_ {
self.match_clusters(cl).flat_map(move |cluster| {
cluster
.match_attributes(attr)
.map(move |attr| (cluster, attr))
})
}

pub fn match_commands(
&self,
cl: Option<ClusterId>,
cmd: Option<CmdId>,
) -> impl Iterator<Item = (&'_ Cluster, CmdId)> + '_ {
self.match_clusters(cl)
.flat_map(move |cluster| cluster.match_commands(cmd).map(move |cmd| (cluster, cmd)))
}

pub fn check_attribute(
&self,
accessor: &Accessor,
cl: ClusterId,
attr: AttrId,
write: bool,
) -> Result<(), IMStatusCode> {
self.check_cluster(cl)
.and_then(|cluster| cluster.check_attribute(accessor, self.id, attr, write))
}

pub fn check_command(
&self,
accessor: &Accessor,
cl: ClusterId,
cmd: CmdId,
) -> Result<(), IMStatusCode> {
self.check_cluster(cl)
.and_then(|cluster| cluster.check_command(accessor, self.id, cmd))
}

pub fn match_clusters(&self, cl: Option<ClusterId>) -> impl Iterator<Item = &'_ Cluster> + '_ {
self.clusters
.iter()
.filter(move |cluster| cl.map(|id| id == cluster.id).unwrap_or(true))
}

pub fn check_cluster(&self, cl: ClusterId) -> Result<&Cluster, IMStatusCode> {
self.clusters
.iter()
.find(|cluster| cluster.id == cl)
.ok_or(IMStatusCode::UnsupportedCluster)
pub const fn new(
id: EndptId,
device_types: &'a [DeviceType],
clusters: &'a [Cluster<'a>],
) -> Self {
Self {
id,
device_types,
clusters,
}
}
}

Expand Down
Loading

0 comments on commit dde3d9a

Please sign in to comment.