Skip to main content

braid_http/
traits.rs

1use crate::error::Result;
2use crate::types::{BraidRequest, BraidResponse, Update};
3use async_trait::async_trait;
4use std::future::Future;
5use std::pin::Pin;
6use std::time::Duration;
7
8/// Abstraction for asynchronous runtime operations.
9pub trait BraidRuntime: Send + Sync + 'static {
10    /// Spawn a background task.
11    fn spawn(&self, future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>);
12
13    /// Yield execution for a duration.
14    fn sleep(&self, duration: Duration) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>>;
15
16    /// Get current Unix timestamp in milliseconds.
17    fn now_ms(&self) -> u64;
18}
19
20/// Abstraction for network operations.
21#[async_trait]
22pub trait BraidNetwork: Send + Sync + 'static {
23    /// Perform a standard Braid-HTTP request.
24    async fn fetch(&self, url: &str, req: BraidRequest) -> Result<BraidResponse>;
25
26    /// Subscribe to a Braid-HTTP 209 stream.
27    async fn subscribe(
28        &self,
29        url: &str,
30        req: BraidRequest,
31    ) -> Result<async_channel::Receiver<Result<Update>>>;
32}
33
34/// Abstraction for persistent storage.
35#[async_trait]
36pub trait BraidStorage: Send + Sync + 'static {
37    /// Store a blob with its metadata.
38    async fn put(&self, key: &str, data: bytes::Bytes, meta: String) -> Result<()>;
39
40    /// Retrieve a blob and its metadata.
41    async fn get(&self, key: &str) -> Result<Option<(bytes::Bytes, String)>>;
42
43    /// Delete a blob.
44    async fn delete(&self, key: &str) -> Result<()>;
45
46    /// List all keys in storage.
47    async fn list_keys(&self) -> Result<Vec<String>>;
48}
49
50/// Helper struct to provide default native runtime implementation.
51#[cfg(all(feature = "native", not(target_arch = "wasm32")))]
52pub struct NativeRuntime;
53
54#[cfg(all(feature = "native", not(target_arch = "wasm32")))]
55impl BraidRuntime for NativeRuntime {
56    fn spawn(&self, future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>) {
57        tokio::spawn(future);
58    }
59
60    fn sleep(&self, duration: Duration) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>> {
61        Box::pin(tokio::time::sleep(duration))
62    }
63
64    fn now_ms(&self) -> u64 {
65        std::time::SystemTime::now()
66            .duration_since(std::time::UNIX_EPOCH)
67            .unwrap()
68            .as_millis() as u64
69    }
70}
71
72#[cfg(all(feature = "wasm", target_arch = "wasm32"))]
73pub struct WasmRuntime;
74
75#[cfg(all(feature = "wasm", target_arch = "wasm32"))]
76struct SendFuture<F>(F);
77#[cfg(all(feature = "wasm", target_arch = "wasm32"))]
78unsafe impl<F> Send for SendFuture<F> {}
79#[cfg(all(feature = "wasm", target_arch = "wasm32"))]
80impl<F: Future> Future for SendFuture<F> {
81    type Output = F::Output;
82    fn poll(
83        self: Pin<&mut Self>,
84        cx: &mut std::task::Context<'_>,
85    ) -> std::task::Poll<Self::Output> {
86        let inner = unsafe { self.map_unchecked_mut(|s| &mut s.0) };
87        inner.poll(cx)
88    }
89}
90
91#[cfg(all(feature = "wasm", target_arch = "wasm32"))]
92impl BraidRuntime for WasmRuntime {
93    fn spawn(&self, future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>) {
94        wasm_bindgen_futures::spawn_local(future);
95    }
96
97    fn sleep(&self, duration: Duration) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>> {
98        let f = gloo_timers::future::sleep(duration);
99        Box::pin(SendFuture(f))
100    }
101
102    fn now_ms(&self) -> u64 {
103        js_sys::Date::now() as u64
104    }
105}