use crate::{Header, HeaderSeq, ProtocolError};
use postcard_schema::Schema;
use serde::{Deserialize, Serialize};
pub mod interface_impls;
pub mod profiles;
pub mod utils;
pub trait ConstInit {
const INIT: Self;
}
#[derive(Serialize, Deserialize, Schema, Debug, PartialEq, Clone)]
#[cfg_attr(feature = "defmt-v1", derive(defmt::Format))]
pub struct SeedNetAssignment {
pub net_id: u16,
pub expires_seconds: u16,
pub max_refresh_seconds: u16,
pub min_refresh_seconds: u16,
pub refresh_token: [u8; 8],
}
#[derive(Serialize, Deserialize, Schema, Debug, PartialEq, Clone)]
pub enum SeedAssignmentError {
ProfileCantSeed,
NetIdsExhausted,
UnknownSource,
}
#[derive(Serialize, Deserialize, Schema, Debug, PartialEq, Clone)]
pub enum SeedRefreshError {
ProfileCantSeed,
UnknownNetId,
NotAssigned,
AlreadyExpired,
BadRequest,
TooSoon,
}
pub trait Profile {
#[cfg(feature = "defmt-v1")]
type InterfaceIdent: Clone + core::fmt::Debug + defmt::Format;
#[cfg(not(feature = "defmt-v1"))]
type InterfaceIdent: Clone + core::fmt::Debug;
fn send<T: Serialize>(&mut self, hdr: &Header, data: &T) -> Result<(), InterfaceSendError>;
fn send_err(
&mut self,
hdr: &Header,
err: ProtocolError,
source: Option<Self::InterfaceIdent>,
) -> Result<(), InterfaceSendError>;
fn send_raw(
&mut self,
hdr: &HeaderSeq,
data: &[u8],
source: Self::InterfaceIdent,
) -> Result<(), InterfaceSendError>;
fn interface_state(&mut self, ident: Self::InterfaceIdent) -> Option<InterfaceState>;
fn set_interface_state(
&mut self,
ident: Self::InterfaceIdent,
state: InterfaceState,
) -> Result<(), SetStateError>;
fn request_seed_net_assign(
&mut self,
source_net: u16,
) -> Result<SeedNetAssignment, SeedAssignmentError> {
_ = source_net;
Err(SeedAssignmentError::ProfileCantSeed)
}
fn refresh_seed_net_assignment(
&mut self,
source_net: u16,
refresh_net: u16,
refresh_token: [u8; 8],
) -> Result<SeedNetAssignment, SeedRefreshError> {
_ = source_net;
_ = refresh_net;
_ = refresh_token;
Err(SeedRefreshError::ProfileCantSeed)
}
}
pub trait Interface {
type Sink: InterfaceSink;
}
#[allow(clippy::result_unit_err)]
pub trait InterfaceSink {
fn send_ty<T: Serialize>(&mut self, hdr: &HeaderSeq, body: &T) -> Result<(), ()>;
fn send_raw(&mut self, hdr: &HeaderSeq, body: &[u8]) -> Result<(), ()>;
fn send_err(&mut self, hdr: &HeaderSeq, err: ProtocolError) -> Result<(), ()>;
}
#[cfg_attr(feature = "defmt-v1", derive(defmt::Format))]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[non_exhaustive]
pub enum InterfaceSendError {
DestinationLocal,
NoRouteToDest,
InterfaceFull,
InternalError,
AnyPortMissingKey,
TtlExpired,
RoutingLoop,
}
#[cfg_attr(feature = "defmt-v1", derive(defmt::Format))]
#[derive(Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum DeregisterError {
NoSuchInterface,
}
#[cfg_attr(feature = "defmt-v1", derive(defmt::Format))]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum InterfaceState {
Down,
Inactive,
ActiveLocal { node_id: u8 },
Active { net_id: u16, node_id: u8 },
}
#[cfg_attr(feature = "defmt-v1", derive(defmt::Format))]
#[derive(Clone, Copy, Debug, PartialEq)]
#[non_exhaustive]
pub enum RegisterSinkError {
AlreadyActive,
}
#[cfg_attr(feature = "defmt-v1", derive(defmt::Format))]
#[derive(Clone, Copy, Debug, PartialEq)]
#[non_exhaustive]
pub enum SetStateError {
InterfaceNotFound,
InvalidNodeId,
}
impl InterfaceSendError {
pub fn to_error(&self) -> ProtocolError {
match self {
InterfaceSendError::DestinationLocal => ProtocolError::ISE_DESTINATION_LOCAL,
InterfaceSendError::NoRouteToDest => ProtocolError::ISE_NO_ROUTE_TO_DEST,
InterfaceSendError::InterfaceFull => ProtocolError::ISE_INTERFACE_FULL,
InterfaceSendError::InternalError => ProtocolError::ISE_INTERNAL_ERROR,
InterfaceSendError::AnyPortMissingKey => ProtocolError::ISE_ANY_PORT_MISSING_KEY,
InterfaceSendError::TtlExpired => ProtocolError::ISE_TTL_EXPIRED,
InterfaceSendError::RoutingLoop => ProtocolError::ISE_ROUTING_LOOP,
}
}
}