use core::future::Future;
use core::pin::pin;
use embassy_futures::select::select;
use crate::crypto::Crypto;
use crate::dm::clusters::net_comm::NetworksAccess;
use crate::dm::{EventId, EventNumber, Metadata};
use crate::error::{Error, ErrorCode};
use crate::im::encoding::{EventPriority, IMBuffer};
use crate::im::events::EventTLVWrite;
use crate::persist::KvBlobStoreAccess;
use crate::tlv::TLVElement;
use crate::transport::exchange::Exchange;
use crate::utils::select::Coalesce;
use crate::utils::storage::pooled::Buffers;
use crate::utils::sync::DynBase;
use crate::Matter;
use super::{AttrDetails, AttrId, ClusterId, CmdDetails, EndptId, InvokeReply, ReadReply};
pub use asynch::*;
pub trait DynAttrChangeNotifier: DynBase + AttrChangeNotifier {}
impl<T> DynAttrChangeNotifier for T where T: DynBase + AttrChangeNotifier {}
pub trait AttrChangeNotifier {
fn notify_attr_changed(&self, endpoint_id: EndptId, cluster_id: ClusterId, attr_id: AttrId);
fn notify_cluster_changed(&self, endpoint_id: EndptId, cluster_id: ClusterId);
fn notify_endpoint_changed(&self, endpoint_id: EndptId);
fn notify_all_changed(&self);
}
impl<T> AttrChangeNotifier for &T
where
T: AttrChangeNotifier,
{
fn notify_attr_changed(&self, endpoint_id: EndptId, cluster_id: ClusterId, attr_id: AttrId) {
(**self).notify_attr_changed(endpoint_id, cluster_id, attr_id)
}
fn notify_cluster_changed(&self, endpoint_id: EndptId, cluster_id: ClusterId) {
(**self).notify_cluster_changed(endpoint_id, cluster_id)
}
fn notify_endpoint_changed(&self, endpoint_id: EndptId) {
(**self).notify_endpoint_changed(endpoint_id)
}
fn notify_all_changed(&self) {
(**self).notify_all_changed()
}
}
impl AttrChangeNotifier for () {
fn notify_attr_changed(&self, _endpt: EndptId, _clust: ClusterId, _attr: AttrId) {
}
fn notify_cluster_changed(&self, _endpt: EndptId, _clust: ClusterId) {
}
fn notify_endpoint_changed(&self, _endpt: EndptId) {
}
fn notify_all_changed(&self) {
}
}
pub trait OwnAttrChangeNotifier {
fn notify_own_attr_changed(&self, attr_id: AttrId);
fn notify_own_cluster_changed(&self);
fn notify_own_endpoint_changed(&self);
}
impl<T> OwnAttrChangeNotifier for &T
where
T: OwnAttrChangeNotifier,
{
fn notify_own_attr_changed(&self, attr_id: AttrId) {
(**self).notify_own_attr_changed(attr_id)
}
fn notify_own_cluster_changed(&self) {
(**self).notify_own_cluster_changed()
}
fn notify_own_endpoint_changed(&self) {
(**self).notify_own_endpoint_changed()
}
}
pub trait EventEmitter {
fn emit_event<F>(
&self,
endpoint_id: EndptId,
cluster_id: ClusterId,
event_id: EventId,
priority: EventPriority,
f: F,
) -> Result<EventNumber, Error>
where
F: FnOnce(EventTLVWrite<'_>) -> Result<(), Error>;
}
impl<T> EventEmitter for &T
where
T: EventEmitter,
{
fn emit_event<F>(
&self,
endpoint_id: EndptId,
cluster_id: ClusterId,
event_id: EventId,
priority: EventPriority,
f: F,
) -> Result<EventNumber, Error>
where
F: FnOnce(EventTLVWrite<'_>) -> Result<(), Error>,
{
(**self).emit_event(endpoint_id, cluster_id, event_id, priority, f)
}
}
pub trait OwnEventEmitter {
fn emit_own_event<F>(
&self,
event_id: EventId,
priority: EventPriority,
f: F,
) -> Result<EventNumber, Error>
where
F: FnOnce(EventTLVWrite<'_>) -> Result<(), Error>;
}
impl<T> OwnEventEmitter for &T
where
T: OwnEventEmitter,
{
fn emit_own_event<F>(
&self,
event_id: EventId,
priority: EventPriority,
f: F,
) -> Result<EventNumber, Error>
where
F: FnOnce(EventTLVWrite<'_>) -> Result<(), Error>,
{
(**self).emit_own_event(event_id, priority, f)
}
}
pub trait HandlerContext: AttrChangeNotifier + EventEmitter {
fn matter(&self) -> &Matter<'_>;
fn crypto(&self) -> impl Crypto + '_;
fn kv(&self) -> impl KvBlobStoreAccess + '_;
fn networks(&self) -> impl NetworksAccess + '_;
fn metadata(&self) -> impl Metadata + '_;
fn handler(&self) -> impl AsyncHandler + '_;
fn buffers(&self) -> impl Buffers<IMBuffer> + '_;
}
impl<T> HandlerContext for &T
where
T: HandlerContext,
{
fn matter(&self) -> &Matter<'_> {
(**self).matter()
}
fn crypto(&self) -> impl Crypto + '_ {
(**self).crypto()
}
fn kv(&self) -> impl KvBlobStoreAccess + '_ {
(**self).kv()
}
fn networks(&self) -> impl NetworksAccess + '_ {
(**self).networks()
}
fn metadata(&self) -> impl Metadata + '_ {
(**self).metadata()
}
fn handler(&self) -> impl AsyncHandler + '_ {
(**self).handler()
}
fn buffers(&self) -> impl Buffers<IMBuffer> + '_ {
(**self).buffers()
}
}
pub trait MatchContext {
fn endpt(&self) -> Option<EndptId>;
fn cluster(&self) -> Option<ClusterId>;
}
impl<T> MatchContext for &T
where
T: MatchContext,
{
fn endpt(&self) -> Option<EndptId> {
(**self).endpt()
}
fn cluster(&self) -> Option<ClusterId> {
(**self).cluster()
}
}
pub(crate) struct MatchContextInstance {
endpt: Option<EndptId>,
cluster: Option<ClusterId>,
}
impl MatchContextInstance {
pub(crate) const fn new(endpt: Option<EndptId>, cluster: Option<ClusterId>) -> Self {
Self { endpt, cluster }
}
}
impl MatchContext for MatchContextInstance {
fn endpt(&self) -> Option<EndptId> {
self.endpt
}
fn cluster(&self) -> Option<ClusterId> {
self.cluster
}
}
pub trait OperationContext:
MatchContext + HandlerContext + OwnAttrChangeNotifier + OwnEventEmitter
{
fn exchange(&self) -> &Exchange<'_>;
}
impl<T> OperationContext for &T
where
T: OperationContext,
{
fn exchange(&self) -> &Exchange<'_> {
(**self).exchange()
}
}
pub trait ReadContext: OperationContext {
fn attr(&self) -> &AttrDetails;
}
impl<T> ReadContext for &T
where
T: ReadContext,
{
fn attr(&self) -> &AttrDetails {
(**self).attr()
}
}
pub trait WriteContext: OperationContext {
fn attr(&self) -> &AttrDetails;
fn data(&self) -> &TLVElement<'_>;
fn notify_changed(&self) {
self.notify_attr_changed(
self.attr().endpoint_id,
self.attr().cluster_id,
self.attr().attr_id,
);
}
}
impl<T> WriteContext for &T
where
T: WriteContext,
{
fn attr(&self) -> &AttrDetails {
(**self).attr()
}
fn data(&self) -> &TLVElement<'_> {
(**self).data()
}
fn notify_changed(&self) {
(**self).notify_changed()
}
}
pub trait InvokeContext: OperationContext {
fn cmd(&self) -> &CmdDetails;
fn data(&self) -> &TLVElement<'_>;
}
impl<T> InvokeContext for &T
where
T: InvokeContext,
{
fn cmd(&self) -> &CmdDetails {
(**self).cmd()
}
fn data(&self) -> &TLVElement<'_> {
(**self).data()
}
}
pub(crate) struct ReadContextInstance<'a, C> {
exchange: &'a Exchange<'a>,
context: C,
attr: &'a AttrDetails,
}
impl<'a, C> ReadContextInstance<'a, C>
where
C: HandlerContext,
{
#[inline(always)]
pub(crate) const fn new(exchange: &'a Exchange<'a>, context: C, attr: &'a AttrDetails) -> Self {
Self {
exchange,
context,
attr,
}
}
}
impl<C> HandlerContext for ReadContextInstance<'_, C>
where
C: HandlerContext,
{
fn matter(&self) -> &Matter<'_> {
self.context.matter()
}
fn crypto(&self) -> impl Crypto + '_ {
self.context.crypto()
}
fn kv(&self) -> impl KvBlobStoreAccess + '_ {
self.context.kv()
}
fn networks(&self) -> impl NetworksAccess + '_ {
self.context.networks()
}
fn metadata(&self) -> impl Metadata + '_ {
self.context.metadata()
}
fn handler(&self) -> impl AsyncHandler + '_ {
self.context.handler()
}
fn buffers(&self) -> impl Buffers<IMBuffer> + '_ {
self.context.buffers()
}
}
impl<C> AttrChangeNotifier for ReadContextInstance<'_, C>
where
C: HandlerContext,
{
fn notify_attr_changed(&self, endpoint_id: EndptId, cluster_id: ClusterId, attr_id: AttrId) {
self.context
.notify_attr_changed(endpoint_id, cluster_id, attr_id);
}
fn notify_cluster_changed(&self, endpoint_id: EndptId, cluster_id: ClusterId) {
self.context.notify_cluster_changed(endpoint_id, cluster_id);
}
fn notify_endpoint_changed(&self, endpoint_id: EndptId) {
self.context.notify_endpoint_changed(endpoint_id);
}
fn notify_all_changed(&self) {
self.context.notify_all_changed();
}
}
impl<C> EventEmitter for ReadContextInstance<'_, C>
where
C: HandlerContext,
{
fn emit_event<F>(
&self,
endpoint_id: EndptId,
cluster_id: ClusterId,
event_id: EventId,
priority: EventPriority,
f: F,
) -> Result<EventNumber, Error>
where
F: FnOnce(EventTLVWrite<'_>) -> Result<(), Error>,
{
self.context
.emit_event(endpoint_id, cluster_id, event_id, priority, f)
}
}
impl<C> MatchContext for ReadContextInstance<'_, C>
where
C: HandlerContext,
{
fn endpt(&self) -> Option<EndptId> {
Some(self.attr.endpoint_id)
}
fn cluster(&self) -> Option<ClusterId> {
Some(self.attr.cluster_id)
}
}
impl<C> OperationContext for ReadContextInstance<'_, C>
where
C: HandlerContext,
{
fn exchange(&self) -> &Exchange<'_> {
self.exchange
}
}
impl<C> OwnAttrChangeNotifier for ReadContextInstance<'_, C>
where
C: HandlerContext,
{
fn notify_own_attr_changed(&self, attr_id: AttrId) {
self.notify_attr_changed(self.attr.endpoint_id, self.attr.cluster_id, attr_id);
}
fn notify_own_cluster_changed(&self) {
self.notify_cluster_changed(self.attr.endpoint_id, self.attr.cluster_id);
}
fn notify_own_endpoint_changed(&self) {
self.notify_endpoint_changed(self.attr.endpoint_id);
}
}
impl<C> OwnEventEmitter for ReadContextInstance<'_, C>
where
C: HandlerContext,
{
fn emit_own_event<F>(
&self,
event_id: EventId,
priority: EventPriority,
f: F,
) -> Result<EventNumber, Error>
where
F: FnOnce(EventTLVWrite<'_>) -> Result<(), Error>,
{
self.context.emit_event(
self.attr.endpoint_id,
self.attr.cluster_id,
event_id,
priority,
f,
)
}
}
impl<C> ReadContext for ReadContextInstance<'_, C>
where
C: HandlerContext,
{
fn attr(&self) -> &AttrDetails {
self.attr
}
}
pub(crate) struct WriteContextInstance<'a, C> {
exchange: &'a Exchange<'a>,
context: C,
attr: &'a AttrDetails,
data: &'a TLVElement<'a>,
}
impl<'a, C> WriteContextInstance<'a, C>
where
C: HandlerContext,
{
#[inline(always)]
#[allow(clippy::too_many_arguments)]
pub(crate) const fn new(
exchange: &'a Exchange<'a>,
context: C,
attr: &'a AttrDetails,
data: &'a TLVElement<'a>,
) -> Self {
Self {
exchange,
context,
attr,
data,
}
}
}
impl<C> HandlerContext for WriteContextInstance<'_, C>
where
C: HandlerContext,
{
fn matter(&self) -> &Matter<'_> {
self.context.matter()
}
fn crypto(&self) -> impl Crypto + '_ {
self.context.crypto()
}
fn kv(&self) -> impl KvBlobStoreAccess + '_ {
self.context.kv()
}
fn networks(&self) -> impl NetworksAccess + '_ {
self.context.networks()
}
fn metadata(&self) -> impl Metadata + '_ {
self.context.metadata()
}
fn handler(&self) -> impl AsyncHandler + '_ {
self.context.handler()
}
fn buffers(&self) -> impl Buffers<IMBuffer> + '_ {
self.context.buffers()
}
}
impl<C> AttrChangeNotifier for WriteContextInstance<'_, C>
where
C: HandlerContext,
{
fn notify_attr_changed(&self, endpoint_id: EndptId, cluster_id: ClusterId, attr_id: AttrId) {
self.context
.notify_attr_changed(endpoint_id, cluster_id, attr_id);
}
fn notify_cluster_changed(&self, endpoint_id: EndptId, cluster_id: ClusterId) {
self.context.notify_cluster_changed(endpoint_id, cluster_id);
}
fn notify_endpoint_changed(&self, endpoint_id: EndptId) {
self.context.notify_endpoint_changed(endpoint_id);
}
fn notify_all_changed(&self) {
self.context.notify_all_changed();
}
}
impl<C> EventEmitter for WriteContextInstance<'_, C>
where
C: HandlerContext,
{
fn emit_event<F>(
&self,
endpoint_id: EndptId,
cluster_id: ClusterId,
event_id: EventId,
priority: EventPriority,
f: F,
) -> Result<EventNumber, Error>
where
F: FnOnce(EventTLVWrite<'_>) -> Result<(), Error>,
{
self.context
.emit_event(endpoint_id, cluster_id, event_id, priority, f)
}
}
impl<C> MatchContext for WriteContextInstance<'_, C>
where
C: HandlerContext,
{
fn endpt(&self) -> Option<EndptId> {
Some(self.attr.endpoint_id)
}
fn cluster(&self) -> Option<ClusterId> {
Some(self.attr.cluster_id)
}
}
impl<C> OperationContext for WriteContextInstance<'_, C>
where
C: HandlerContext,
{
fn exchange(&self) -> &Exchange<'_> {
self.exchange
}
}
impl<C> OwnAttrChangeNotifier for WriteContextInstance<'_, C>
where
C: HandlerContext,
{
fn notify_own_attr_changed(&self, attr_id: AttrId) {
self.notify_attr_changed(self.attr.endpoint_id, self.attr.cluster_id, attr_id);
}
fn notify_own_cluster_changed(&self) {
self.notify_cluster_changed(self.attr.endpoint_id, self.attr.cluster_id);
}
fn notify_own_endpoint_changed(&self) {
self.notify_endpoint_changed(self.attr.endpoint_id);
}
}
impl<C> OwnEventEmitter for WriteContextInstance<'_, C>
where
C: HandlerContext,
{
fn emit_own_event<F>(
&self,
event_id: EventId,
priority: EventPriority,
f: F,
) -> Result<EventNumber, Error>
where
F: FnOnce(EventTLVWrite<'_>) -> Result<(), Error>,
{
self.context.emit_event(
self.attr.endpoint_id,
self.attr.cluster_id,
event_id,
priority,
f,
)
}
}
impl<C> WriteContext for WriteContextInstance<'_, C>
where
C: HandlerContext,
{
fn attr(&self) -> &AttrDetails {
self.attr
}
fn data(&self) -> &TLVElement<'_> {
self.data
}
}
pub(crate) struct InvokeContextInstance<'a, C> {
exchange: &'a Exchange<'a>,
context: C,
cmd: &'a CmdDetails,
data: &'a TLVElement<'a>,
}
impl<'a, C> InvokeContextInstance<'a, C>
where
C: HandlerContext,
{
#[inline(always)]
#[allow(clippy::too_many_arguments)]
pub(crate) const fn new(
exchange: &'a Exchange<'a>,
context: C,
cmd: &'a CmdDetails,
data: &'a TLVElement<'a>,
) -> Self {
Self {
exchange,
context,
cmd,
data,
}
}
}
impl<C> HandlerContext for InvokeContextInstance<'_, C>
where
C: HandlerContext,
{
fn matter(&self) -> &Matter<'_> {
self.context.matter()
}
fn crypto(&self) -> impl Crypto + '_ {
self.context.crypto()
}
fn kv(&self) -> impl KvBlobStoreAccess + '_ {
self.context.kv()
}
fn networks(&self) -> impl NetworksAccess + '_ {
self.context.networks()
}
fn metadata(&self) -> impl Metadata + '_ {
self.context.metadata()
}
fn handler(&self) -> impl AsyncHandler + '_ {
self.context.handler()
}
fn buffers(&self) -> impl Buffers<IMBuffer> + '_ {
self.context.buffers()
}
}
impl<C> AttrChangeNotifier for InvokeContextInstance<'_, C>
where
C: HandlerContext,
{
fn notify_attr_changed(&self, endpoint_id: EndptId, cluster_id: ClusterId, attr_id: AttrId) {
self.context
.notify_attr_changed(endpoint_id, cluster_id, attr_id);
}
fn notify_cluster_changed(&self, endpoint_id: EndptId, cluster_id: ClusterId) {
self.context.notify_cluster_changed(endpoint_id, cluster_id);
}
fn notify_endpoint_changed(&self, endpoint_id: EndptId) {
self.context.notify_endpoint_changed(endpoint_id);
}
fn notify_all_changed(&self) {
self.context.notify_all_changed();
}
}
impl<C> EventEmitter for InvokeContextInstance<'_, C>
where
C: HandlerContext,
{
fn emit_event<F>(
&self,
endpoint_id: EndptId,
cluster_id: ClusterId,
event_id: EventId,
priority: EventPriority,
f: F,
) -> Result<EventNumber, Error>
where
F: FnOnce(EventTLVWrite<'_>) -> Result<(), Error>,
{
self.context
.emit_event(endpoint_id, cluster_id, event_id, priority, f)
}
}
impl<C> MatchContext for InvokeContextInstance<'_, C>
where
C: HandlerContext,
{
fn endpt(&self) -> Option<EndptId> {
Some(self.cmd.endpoint_id)
}
fn cluster(&self) -> Option<ClusterId> {
Some(self.cmd.cluster_id)
}
}
impl<C> OperationContext for InvokeContextInstance<'_, C>
where
C: HandlerContext,
{
fn exchange(&self) -> &Exchange<'_> {
self.exchange
}
}
impl<C> OwnAttrChangeNotifier for InvokeContextInstance<'_, C>
where
C: HandlerContext,
{
fn notify_own_attr_changed(&self, attr_id: AttrId) {
self.notify_attr_changed(self.cmd.endpoint_id, self.cmd.cluster_id, attr_id);
}
fn notify_own_cluster_changed(&self) {
self.notify_cluster_changed(self.cmd.endpoint_id, self.cmd.cluster_id);
}
fn notify_own_endpoint_changed(&self) {
self.notify_endpoint_changed(self.cmd.endpoint_id);
}
}
impl<C> OwnEventEmitter for InvokeContextInstance<'_, C>
where
C: HandlerContext,
{
fn emit_own_event<F>(
&self,
event_id: EventId,
priority: EventPriority,
f: F,
) -> Result<EventNumber, Error>
where
F: FnOnce(EventTLVWrite<'_>) -> Result<(), Error>,
{
self.context.emit_event(
self.cmd.endpoint_id,
self.cmd.cluster_id,
event_id,
priority,
f,
)
}
}
impl<C> InvokeContext for InvokeContextInstance<'_, C>
where
C: HandlerContext,
{
fn cmd(&self) -> &CmdDetails {
self.cmd
}
fn data(&self) -> &TLVElement<'_> {
self.data
}
}
pub trait DataModel: Metadata + AsyncHandler {}
impl<T> DataModel for T where T: Metadata + AsyncHandler {}
pub trait Handler {
fn read(&self, ctx: impl ReadContext, reply: impl ReadReply) -> Result<(), Error>;
fn write(&self, _ctx: impl WriteContext) -> Result<(), Error> {
Err(ErrorCode::AttributeNotFound.into())
}
fn invoke(&self, _ctx: impl InvokeContext, _reply: impl InvokeReply) -> Result<(), Error> {
Err(ErrorCode::CommandNotFound.into())
}
fn bump_dataver(&self, ctx: impl MatchContext);
fn run(&self, _ctx: impl HandlerContext) -> impl Future<Output = Result<(), Error>> {
core::future::pending::<Result<(), Error>>()
}
}
impl<T> Handler for &T
where
T: Handler,
{
fn read(&self, ctx: impl ReadContext, reply: impl ReadReply) -> Result<(), Error> {
(**self).read(ctx, reply)
}
fn write(&self, ctx: impl WriteContext) -> Result<(), Error> {
(**self).write(ctx)
}
fn invoke(&self, ctx: impl InvokeContext, reply: impl InvokeReply) -> Result<(), Error> {
(**self).invoke(ctx, reply)
}
fn bump_dataver(&self, ctx: impl MatchContext) {
(**self).bump_dataver(ctx)
}
fn run(&self, ctx: impl HandlerContext) -> impl Future<Output = Result<(), Error>> {
(**self).run(ctx)
}
}
impl<T> Handler for &mut T
where
T: Handler,
{
fn read(&self, ctx: impl ReadContext, reply: impl ReadReply) -> Result<(), Error> {
(**self).read(ctx, reply)
}
fn write(&self, ctx: impl WriteContext) -> Result<(), Error> {
(**self).write(ctx)
}
fn invoke(&self, ctx: impl InvokeContext, reply: impl InvokeReply) -> Result<(), Error> {
(**self).invoke(ctx, reply)
}
fn bump_dataver(&self, ctx: impl MatchContext) {
(**self).bump_dataver(ctx)
}
fn run(&self, ctx: impl HandlerContext) -> impl Future<Output = Result<(), Error>> {
(**self).run(ctx)
}
}
pub trait NonBlockingHandler: Handler {}
impl<T> NonBlockingHandler for &T where T: NonBlockingHandler {}
impl<T> NonBlockingHandler for &mut T where T: NonBlockingHandler {}
impl<M, H> Handler for (M, H)
where
H: Handler,
{
fn read(&self, ctx: impl ReadContext, reply: impl ReadReply) -> Result<(), Error> {
self.1.read(ctx, reply)
}
fn write(&self, ctx: impl WriteContext) -> Result<(), Error> {
self.1.write(ctx)
}
fn invoke(&self, ctx: impl InvokeContext, reply: impl InvokeReply) -> Result<(), Error> {
self.1.invoke(ctx, reply)
}
fn bump_dataver(&self, ctx: impl MatchContext) {
self.1.bump_dataver(ctx)
}
fn run(&self, ctx: impl HandlerContext) -> impl Future<Output = Result<(), Error>> {
self.1.run(ctx)
}
}
impl<M, H> NonBlockingHandler for (M, H) where H: NonBlockingHandler {}
pub trait Matcher {
fn matches(&self, ctx: impl MatchContext) -> bool;
}
impl<T> Matcher for &T
where
T: Matcher,
{
fn matches(&self, ctx: impl MatchContext) -> bool {
T::matches(self, ctx)
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct EpClMatcher {
endpoint_id: Option<EndptId>,
cluster_id: Option<ClusterId>,
}
impl EpClMatcher {
pub const fn new(endpoint_id: Option<EndptId>, cluster_id: Option<ClusterId>) -> Self {
Self {
endpoint_id,
cluster_id,
}
}
}
impl Matcher for EpClMatcher {
fn matches(&self, ctx: impl MatchContext) -> bool {
(self.endpoint_id.is_none() || ctx.endpt().is_none() || self.endpoint_id == ctx.endpt())
&& (self.cluster_id.is_none()
|| ctx.cluster().is_none()
|| self.cluster_id == ctx.cluster())
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct EmptyHandler;
impl EmptyHandler {
pub const fn chain<M, H>(self, matcher: M, handler: H) -> ChainedHandler<M, H, Self> {
ChainedHandler {
matcher,
handler,
next: self,
}
}
}
impl Handler for EmptyHandler {
fn read(&self, _ctx: impl ReadContext, _reply: impl ReadReply) -> Result<(), Error> {
Err(ErrorCode::EndpointNotFound.into())
}
fn write(&self, _ctx: impl WriteContext) -> Result<(), Error> {
Err(ErrorCode::EndpointNotFound.into())
}
fn invoke(&self, _ctx: impl InvokeContext, _reply: impl InvokeReply) -> Result<(), Error> {
Err(ErrorCode::EndpointNotFound.into())
}
fn bump_dataver(&self, _ctx: impl MatchContext) {
}
}
impl NonBlockingHandler for EmptyHandler {}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ChainedHandler<M, H, T> {
pub matcher: M,
pub handler: H,
pub next: T,
}
impl<M, H, T> ChainedHandler<M, H, T> {
pub const fn new(matcher: M, handler: H, next: T) -> Self {
Self {
matcher,
handler,
next,
}
}
pub const fn chain<M2, H2>(self, matcher: M2, handler: H2) -> ChainedHandler<M2, H2, Self> {
ChainedHandler::new(matcher, handler, self)
}
}
impl<M, H, T> Handler for ChainedHandler<M, H, T>
where
M: Matcher,
H: Handler,
T: Handler,
{
fn read(&self, ctx: impl ReadContext, reply: impl ReadReply) -> Result<(), Error> {
if self.matcher.matches(&ctx) {
self.handler.read(ctx, reply)
} else {
self.next.read(ctx, reply)
}
}
fn write(&self, ctx: impl WriteContext) -> Result<(), Error> {
if self.matcher.matches(&ctx) {
self.handler.write(ctx)
} else {
self.next.write(ctx)
}
}
fn invoke(&self, ctx: impl InvokeContext, reply: impl InvokeReply) -> Result<(), Error> {
if self.matcher.matches(&ctx) {
self.handler.invoke(ctx, reply)
} else {
self.next.invoke(ctx, reply)
}
}
fn bump_dataver(&self, ctx: impl MatchContext) {
if self.matcher.matches(&ctx) {
self.handler.bump_dataver(&ctx)
}
self.next.bump_dataver(ctx)
}
async fn run(&self, ctx: impl HandlerContext) -> Result<(), Error> {
let mut handler = pin!(self.handler.run(&ctx));
let mut next = pin!(self.next.run(&ctx));
select(&mut handler, &mut next).coalesce().await
}
}
impl<M, H, T> NonBlockingHandler for ChainedHandler<M, H, T>
where
M: Matcher,
H: NonBlockingHandler,
T: NonBlockingHandler,
{
}
#[allow(unused_macros)]
#[macro_export]
macro_rules! handler_chain_type {
($m:ty => $h:ty) => {
$crate::dm::ChainedHandler<$m, $h, $crate::dm::EmptyHandler>
};
($m1:ty => $h1:ty, $($m:ty => $h:ty),+) => {
$crate::dm::ChainedHandler<$m1, $h1, handler_chain_type!($($m => $h),+)>
};
($m:ty => $h:ty | $f:ty) => {
$crate::dm::ChainedHandler<$m, $h, $f>
};
($m1:ty => $h1:ty, $($m:ty => $h:ty),+ | $f:ty) => {
$crate::dm::ChainedHandler<$m1, $h1, handler_chain_type!($($m => $h),+ | $f)>
};
}
mod asynch {
use core::future::{ready, Future};
use core::pin::pin;
use either::Either;
use embassy_futures::select::select;
use crate::dm::{HandlerContext, InvokeReply, MatchContext, Matcher, ReadReply};
use crate::error::{Error, ErrorCode};
use crate::utils::select::Coalesce;
use super::{
ChainedHandler, EmptyHandler, Handler, InvokeContext, NonBlockingHandler, ReadContext,
WriteContext,
};
pub trait AsyncHandler {
fn read_awaits(&self, _ctx: impl ReadContext) -> bool {
true
}
fn write_awaits(&self, _ctx: impl WriteContext) -> bool {
true
}
fn invoke_awaits(&self, _ctx: impl InvokeContext) -> bool {
true
}
fn read(
&self,
ctx: impl ReadContext,
reply: impl ReadReply,
) -> impl Future<Output = Result<(), Error>>;
fn write(&self, _ctx: impl WriteContext) -> impl Future<Output = Result<(), Error>> {
core::future::ready(Err(ErrorCode::AttributeNotFound.into()))
}
fn invoke(
&self,
_ctx: impl InvokeContext,
_reply: impl InvokeReply,
) -> impl Future<Output = Result<(), Error>> {
core::future::ready(Err(ErrorCode::CommandNotFound.into()))
}
fn bump_dataver(&self, ctx: impl MatchContext);
fn run(&self, _ctx: impl HandlerContext) -> impl Future<Output = Result<(), Error>> {
core::future::pending::<Result<(), Error>>()
}
}
impl<T> AsyncHandler for &mut T
where
T: AsyncHandler,
{
fn read_awaits(&self, ctx: impl ReadContext) -> bool {
(**self).read_awaits(ctx)
}
fn write_awaits(&self, ctx: impl WriteContext) -> bool {
(**self).write_awaits(ctx)
}
fn invoke_awaits(&self, ctx: impl InvokeContext) -> bool {
(**self).invoke_awaits(ctx)
}
fn read(
&self,
ctx: impl ReadContext,
reply: impl ReadReply,
) -> impl Future<Output = Result<(), Error>> {
(**self).read(ctx, reply)
}
fn write(&self, ctx: impl WriteContext) -> impl Future<Output = Result<(), Error>> {
(**self).write(ctx)
}
fn invoke(
&self,
ctx: impl InvokeContext,
reply: impl InvokeReply,
) -> impl Future<Output = Result<(), Error>> {
(**self).invoke(ctx, reply)
}
fn bump_dataver(&self, ctx: impl MatchContext) {
(**self).bump_dataver(ctx)
}
fn run(&self, ctx: impl HandlerContext) -> impl Future<Output = Result<(), Error>> {
(**self).run(ctx)
}
}
impl<T> AsyncHandler for &T
where
T: AsyncHandler,
{
fn read_awaits(&self, ctx: impl ReadContext) -> bool {
(**self).read_awaits(ctx)
}
fn write_awaits(&self, ctx: impl WriteContext) -> bool {
(**self).write_awaits(ctx)
}
fn invoke_awaits(&self, ctx: impl InvokeContext) -> bool {
(**self).invoke_awaits(ctx)
}
fn read(
&self,
ctx: impl ReadContext,
reply: impl ReadReply,
) -> impl Future<Output = Result<(), Error>> {
(**self).read(ctx, reply)
}
fn write(&self, ctx: impl WriteContext) -> impl Future<Output = Result<(), Error>> {
(**self).write(ctx)
}
fn invoke(
&self,
ctx: impl InvokeContext,
reply: impl InvokeReply,
) -> impl Future<Output = Result<(), Error>> {
(**self).invoke(ctx, reply)
}
fn bump_dataver(&self, ctx: impl MatchContext) {
(**self).bump_dataver(ctx)
}
fn run(&self, ctx: impl HandlerContext) -> impl Future<Output = Result<(), Error>> {
(**self).run(ctx)
}
}
impl<M, H> AsyncHandler for (M, H)
where
H: AsyncHandler,
{
fn read_awaits(&self, ctx: impl ReadContext) -> bool {
self.1.read_awaits(ctx)
}
fn write_awaits(&self, ctx: impl WriteContext) -> bool {
self.1.write_awaits(ctx)
}
fn invoke_awaits(&self, ctx: impl InvokeContext) -> bool {
self.1.invoke_awaits(ctx)
}
fn read(
&self,
ctx: impl ReadContext,
reply: impl ReadReply,
) -> impl Future<Output = Result<(), Error>> {
self.1.read(ctx, reply)
}
fn write(&self, ctx: impl WriteContext) -> impl Future<Output = Result<(), Error>> {
self.1.write(ctx)
}
fn invoke(
&self,
ctx: impl InvokeContext,
reply: impl InvokeReply,
) -> impl Future<Output = Result<(), Error>> {
self.1.invoke(ctx, reply)
}
fn bump_dataver(&self, ctx: impl MatchContext) {
self.1.bump_dataver(ctx)
}
fn run(&self, ctx: impl HandlerContext) -> impl Future<Output = Result<(), Error>> {
self.1.run(ctx)
}
}
impl<T> AsyncHandler for Async<T>
where
T: NonBlockingHandler,
{
fn read_awaits(&self, _ctx: impl ReadContext) -> bool {
false
}
fn write_awaits(&self, _ctx: impl WriteContext) -> bool {
false
}
fn invoke_awaits(&self, _ctx: impl InvokeContext) -> bool {
false
}
fn read(
&self,
ctx: impl ReadContext,
reply: impl ReadReply,
) -> impl Future<Output = Result<(), Error>> {
ready(Handler::read(&self.0, ctx, reply))
}
fn write(&self, ctx: impl WriteContext) -> impl Future<Output = Result<(), Error>> {
ready(Handler::write(&self.0, ctx))
}
fn invoke(
&self,
ctx: impl InvokeContext,
reply: impl InvokeReply,
) -> impl Future<Output = Result<(), Error>> {
ready(Handler::invoke(&self.0, ctx, reply))
}
fn bump_dataver(&self, ctx: impl MatchContext) {
Handler::bump_dataver(&self.0, ctx)
}
fn run(&self, ctx: impl HandlerContext) -> impl Future<Output = Result<(), Error>> {
Handler::run(&self.0, ctx)
}
}
impl AsyncHandler for EmptyHandler {
fn read_awaits(&self, _ctx: impl ReadContext) -> bool {
false
}
fn write_awaits(&self, _ctx: impl WriteContext) -> bool {
false
}
fn invoke_awaits(&self, _ctx: impl InvokeContext) -> bool {
false
}
fn read(
&self,
_ctx: impl ReadContext,
_reply: impl ReadReply,
) -> impl Future<Output = Result<(), Error>> {
core::future::ready(Err(ErrorCode::EndpointNotFound.into()))
}
fn write(&self, _ctx: impl WriteContext) -> impl Future<Output = Result<(), Error>> {
core::future::ready(Err(ErrorCode::EndpointNotFound.into()))
}
fn invoke(
&self,
_ctx: impl InvokeContext,
_reply: impl InvokeReply,
) -> impl Future<Output = Result<(), Error>> {
core::future::ready(Err(ErrorCode::EndpointNotFound.into()))
}
fn bump_dataver(&self, _ctx: impl MatchContext) {
}
}
impl<M, H, T> AsyncHandler for ChainedHandler<M, H, T>
where
M: Matcher,
H: AsyncHandler,
T: AsyncHandler,
{
fn read_awaits(&self, ctx: impl ReadContext) -> bool {
if self.matcher.matches(&ctx) {
self.handler.read_awaits(ctx)
} else {
self.next.read_awaits(ctx)
}
}
fn write_awaits(&self, ctx: impl WriteContext) -> bool {
if self.matcher.matches(&ctx) {
self.handler.write_awaits(ctx)
} else {
self.next.write_awaits(ctx)
}
}
fn invoke_awaits(&self, ctx: impl InvokeContext) -> bool {
if self.matcher.matches(&ctx) {
self.handler.invoke_awaits(ctx)
} else {
self.next.invoke_awaits(ctx)
}
}
fn read(
&self,
ctx: impl ReadContext,
reply: impl ReadReply,
) -> impl Future<Output = Result<(), Error>> {
if self.matcher.matches(&ctx) {
Either::Left(self.handler.read(ctx, reply))
} else {
Either::Right(self.next.read(ctx, reply))
}
}
fn write(&self, ctx: impl WriteContext) -> impl Future<Output = Result<(), Error>> {
if self.matcher.matches(&ctx) {
Either::Left(self.handler.write(ctx))
} else {
Either::Right(self.next.write(ctx))
}
}
fn invoke(
&self,
ctx: impl InvokeContext,
reply: impl InvokeReply,
) -> impl Future<Output = Result<(), Error>> {
if self.matcher.matches(&ctx) {
Either::Left(self.handler.invoke(ctx, reply))
} else {
Either::Right(self.next.invoke(ctx, reply))
}
}
fn bump_dataver(&self, ctx: impl MatchContext) {
if self.matcher.matches(&ctx) {
self.handler.bump_dataver(&ctx)
}
self.next.bump_dataver(ctx)
}
async fn run(&self, ctx: impl HandlerContext) -> Result<(), Error> {
let mut handler = pin!(self.handler.run(&ctx));
let mut next = pin!(self.next.run(&ctx));
select(&mut handler, &mut next).coalesce().await
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Async<T>(pub T);
impl<T> Handler for Async<T>
where
T: Handler,
{
fn read(&self, ctx: impl ReadContext, reply: impl ReadReply) -> Result<(), Error> {
self.0.read(ctx, reply)
}
fn write(&self, ctx: impl WriteContext) -> Result<(), Error> {
self.0.write(ctx)
}
fn invoke(&self, ctx: impl InvokeContext, reply: impl InvokeReply) -> Result<(), Error> {
self.0.invoke(ctx, reply)
}
fn bump_dataver(&self, ctx: impl MatchContext) {
self.0.bump_dataver(ctx)
}
fn run(&self, ctx: impl HandlerContext) -> impl Future<Output = Result<(), Error>> {
self.0.run(ctx)
}
}
impl<T> NonBlockingHandler for Async<T> where T: NonBlockingHandler {}
}