use std::{
io::{Read, Write},
sync::Arc,
};
use crate::registry::ServiceRegistry;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct WearablePeer {
pub id: String,
pub name: String,
pub has_app: bool,
}
#[derive(thiserror::Error, Debug)]
pub enum WearableError {
#[error("there is no link to a paired device in this build")]
Unavailable,
#[error("the paired device link failed: {0}")]
Failed(String),
}
pub struct WearableStream {
pub peer: String,
pub path: String,
reader: Box<dyn Read + Send>,
}
impl WearableStream {
pub fn new(peer: String, path: String, reader: Box<dyn Read + Send>) -> Self {
Self { peer, path, reader }
}
}
impl Read for WearableStream {
fn read(&mut self, buffer: &mut [u8]) -> std::io::Result<usize> {
self.reader.read(buffer)
}
}
pub enum WearableEvent {
Message {
peer: String,
path: String,
data: Vec<u8>,
},
Stream(WearableStream),
}
pub trait WearableReceiver: Send + Sync {
fn receive(&self, event: WearableEvent);
}
impl<F: Fn(WearableEvent) + Send + Sync> WearableReceiver for F {
fn receive(&self, event: WearableEvent) {
self(event);
}
}
pub trait WearableLink: Send + Sync {
fn peers(&self) -> Result<Vec<WearablePeer>, WearableError>;
fn send_message(&self, peer: &str, path: &str, data: &[u8]) -> Result<(), WearableError>;
fn open_stream(&self, peer: &str, path: &str) -> Result<Box<dyn Write + Send>, WearableError>;
fn open_url(&self, peer: &str, url: &str) -> Result<(), WearableError>;
}
static PLATFORM: ServiceRegistry<dyn WearableLink> = ServiceRegistry::new();
static RECEIVER: ServiceRegistry<dyn WearableReceiver> = ServiceRegistry::new();
pub fn set_platform_wearable_link(link: Option<Arc<dyn WearableLink>>) {
match link {
Some(link) => PLATFORM.set(link),
None => PLATFORM.clear(),
}
}
fn link() -> Result<Arc<dyn WearableLink>, WearableError> {
PLATFORM.get().ok_or(WearableError::Unavailable)
}
pub fn wearable_peers() -> Result<Vec<WearablePeer>, WearableError> {
link()?.peers()
}
pub fn send_wearable_message(peer: &str, path: &str, data: &[u8]) -> Result<(), WearableError> {
link()?.send_message(peer, path, data)
}
pub fn open_wearable_stream(
peer: &str,
path: &str,
) -> Result<Box<dyn Write + Send>, WearableError> {
link()?.open_stream(peer, path)
}
pub fn open_on_wearable_peer(peer: &str, url: &str) -> Result<(), WearableError> {
link()?.open_url(peer, url)
}
pub fn set_wearable_receiver(receiver: Option<Arc<dyn WearableReceiver>>) {
match receiver {
Some(receiver) => RECEIVER.set(receiver),
None => RECEIVER.clear(),
}
}
pub fn publish_wearable_event(event: WearableEvent) {
match RECEIVER.get() {
Some(receiver) => receiver.receive(event),
None => log::warn!(
"a paired device sent something, and the application has no wearable receiver"
),
}
}
#[cfg(test)]
#[path = "tests/wearable_tests.rs"]
mod tests;