use std::sync::{Arc, Mutex};
use anyhow::Result;
use arora_bridge::FakeBridge;
use arora_hal::{Hal, HalDescription, HalResult, UpdatesStream};
use arora_simple_data_store::SimpleDataStore;
use arora_types::data::{Key, State, StateChange};
use arora_types::value::Value;
use async_trait::async_trait;
use futures::channel::mpsc::UnboundedSender;
#[derive(Default)]
struct ExampleHal {
inner: Arc<Mutex<Inner>>,
}
#[derive(Default)]
struct Inner {
state: State,
subscribers: Vec<UnboundedSender<StateChange>>,
}
impl ExampleHal {
fn apply(&self, changes: &StateChange) {
if changes.is_empty() {
return;
}
let mut inner = self.inner.lock().unwrap();
inner.state.apply(changes.clone());
inner
.subscribers
.retain(|tx| tx.unbounded_send(changes.clone()).is_ok());
}
}
#[async_trait]
impl Hal for ExampleHal {
async fn describe(&self) -> HalDescription {
HalDescription {
model_family: Some("example-device".to_string()),
hardware_version: Some("0.1".to_string()),
software_version: Some(env!("CARGO_PKG_VERSION").to_string()),
}
}
async fn read(&self, keys: &[Key]) -> HalResult<Vec<Option<Value>>> {
let inner = self.inner.lock().unwrap();
Ok(keys
.iter()
.map(|key| inner.state.get(key).cloned().flatten())
.collect())
}
async fn read_all(&self) -> HalResult<State> {
Ok(self.inner.lock().unwrap().state.clone())
}
async fn write(&self, changes: StateChange) -> HalResult<()> {
self.apply(&changes);
Ok(())
}
fn try_send(&self, changes: &StateChange) {
self.apply(changes);
}
fn updates(&self) -> UpdatesStream {
let (tx, rx) = futures::channel::mpsc::unbounded();
self.inner.lock().unwrap().subscribers.push(tx);
Box::pin(rx)
}
}
#[tokio::main]
async fn main() -> Result<()> {
arora::run_with(
Box::new(ExampleHal::default()),
Box::new(FakeBridge::new()),
Box::new(SimpleDataStore::new()),
)
.await
}