|
|
|
use alloc::string::String;
|
|
|
|
use crate::message::MessageBytes;
|
|
|
|
use crate::res::IFResult;
|
|
|
|
|
|
|
|
|
|
|
|
/// Some data that can be provided to the interface to send the message to a target.
|
|
|
|
///
|
|
|
|
/// For IP this might be `IP:port`.
|
|
|
|
/// Radio interface, for example, may not have the functionality of targeting, but that's fine
|
|
|
|
pub(crate) type TargetingData = String;
|
|
|
|
|
|
|
|
/// In an std environment we require that the interface can be send safely between threads
|
|
|
|
#[cfg(not(feature = "std"))]
|
|
|
|
pub trait InterfaceRequirements {}
|
|
|
|
|
|
|
|
#[cfg(feature = "std")]
|
|
|
|
pub trait InterfaceRequirements: Send + Sync {}
|
|
|
|
|
|
|
|
|
|
|
|
/// An interface that can be used to
|
|
|
|
pub trait Interface: InterfaceRequirements {
|
|
|
|
/// Run one main loop iteration.
|
|
|
|
/// On platforms that support concurrency, these functions will be run simultaneously for all interfaces.
|
|
|
|
/// Most likely, this function will accept messages and save them somewhere internally to give out later in `Interface.receive()`.
|
|
|
|
///
|
|
|
|
/// For systems that don't support concurrency, there can be only one interface in this function waits for a message (to avoid blocking).
|
|
|
|
/// That's why it's necessary to check if it is the case for this interface, and it's done using function `Interface::has_blocking_main()`
|
|
|
|
fn main_loop_iteration(&mut self) -> IFResult<()>;
|
|
|
|
/// Check if `main_loop_iteration` stops execution and waits for a message
|
|
|
|
fn has_blocking_main(&self) -> bool {
|
|
|
|
false // hopefully...
|
|
|
|
}
|
|
|
|
/// Get some way of identification for this interface
|
|
|
|
fn id(&self) -> &str;
|
|
|
|
/// Send a message. If no `interface_data` is provided, we should consider it to be a broadcast.
|
|
|
|
/// If, on the other hand, `interface_data` is not `None`, it should be used to send the message to the target.
|
|
|
|
fn send(&mut self, message: &[u8] /*MessageBytes*/, interface_data: Option<TargetingData>) -> IFResult<()>;
|
|
|
|
/// Receive a message through this interface. Returns a result with an option of (message bytes, target).
|
|
|
|
/// `None` means there is no message available at the time.
|
|
|
|
/// The implementations of this function shouldn't wait for new messages, but
|
|
|
|
fn receive(&mut self) -> IFResult<Option<(MessageBytes, TargetingData /*interface data*/)>>;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
pub mod test_interface {
|
|
|
|
use crate::interface::{Interface, InterfaceRequirements, TargetingData};
|
|
|
|
use crate::message::MessageBytes;
|
|
|
|
use crate::res::IFResult;
|
|
|
|
use alloc::vec::Vec;
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct TestInterface {
|
|
|
|
messages: Vec<(Vec<u8>, TargetingData)>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl InterfaceRequirements for TestInterface {}
|
|
|
|
|
|
|
|
impl Interface for TestInterface {
|
|
|
|
fn main_loop_iteration(&mut self) -> IFResult<()> {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn id(&self) -> &str {
|
|
|
|
"test_interface"
|
|
|
|
}
|
|
|
|
|
|
|
|
fn send(&mut self, message: &[u8], interface_data: Option<TargetingData>) -> IFResult<()> {
|
|
|
|
self.messages.push((Vec::from(message), interface_data.unwrap_or_default()));
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn receive(&mut self) -> IFResult<Option<(MessageBytes, TargetingData)>> {
|
|
|
|
Ok(
|
|
|
|
self.messages.pop()
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|