/* * * Copyright (c) 2020-2022 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ use crate::{data_model::objects::ClusterType, error::*, interaction_model::core::IMStatusCode}; use std::fmt; use super::{ClusterId, DeviceType}; pub const CLUSTERS_PER_ENDPT: usize = 9; pub struct Endpoint { dev_type: DeviceType, clusters: Vec>, } pub type BoxedClusters = [Box]; impl Endpoint { pub fn new(dev_type: DeviceType) -> Result, Error> { Ok(Box::new(Endpoint { dev_type, clusters: Vec::with_capacity(CLUSTERS_PER_ENDPT), })) } pub fn add_cluster(&mut self, cluster: Box) -> Result<(), Error> { if self.clusters.len() < self.clusters.capacity() { self.clusters.push(cluster); Ok(()) } else { Err(Error::NoSpace) } } pub fn get_dev_type(&self) -> &DeviceType { &self.dev_type } fn get_cluster_index(&self, cluster_id: ClusterId) -> Option { self.clusters.iter().position(|c| c.base().id == cluster_id) } pub fn get_cluster(&self, cluster_id: ClusterId) -> Result<&dyn ClusterType, Error> { let index = self .get_cluster_index(cluster_id) .ok_or(Error::ClusterNotFound)?; Ok(self.clusters[index].as_ref()) } pub fn get_cluster_mut( &mut self, cluster_id: ClusterId, ) -> Result<&mut dyn ClusterType, Error> { let index = self .get_cluster_index(cluster_id) .ok_or(Error::ClusterNotFound)?; Ok(self.clusters[index].as_mut()) } // Returns a slice of clusters, with either a single cluster or all (wildcard) pub fn get_wildcard_clusters( &self, cluster: Option, ) -> Result<(&BoxedClusters, bool), IMStatusCode> { if let Some(c) = cluster { if let Some(i) = self.get_cluster_index(c) { Ok((&self.clusters[i..i + 1], false)) } else { Err(IMStatusCode::UnsupportedCluster) } } else { Ok((self.clusters.as_slice(), true)) } } // Returns a slice of clusters, with either a single cluster or all (wildcard) pub fn get_wildcard_clusters_mut( &mut self, cluster: Option, ) -> Result<(&mut BoxedClusters, bool), IMStatusCode> { if let Some(c) = cluster { if let Some(i) = self.get_cluster_index(c) { Ok((&mut self.clusters[i..i + 1], false)) } else { Err(IMStatusCode::UnsupportedCluster) } } else { Ok((&mut self.clusters[..], true)) } } } impl std::fmt::Display for Endpoint { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "clusters:[")?; let mut comma = ""; for element in self.clusters.iter() { write!(f, "{} {{ {} }}", comma, element.base())?; comma = ", "; } write!(f, "]") } }