Skip to main content

nectar_primitives/store/
typed.rs

1//! Typed chunk storage traits.
2//!
3//! Async traits (`ChunkGet`, `ChunkPut`, `ChunkHas`) are the primary API.
4//! Sync traits (`SyncChunkGet`, `SyncChunkPut`, `SyncChunkHas`) exist for
5//! CPU-bound paths (splitter, mantaray). Blanket impls bridge sync → async
6//! automatically for any `Send + Sync` type.
7
8use std::future::Future;
9
10use crate::bmt::DEFAULT_BODY_SIZE;
11use crate::chunk::{AnyChunk, ChunkAddress};
12
13/// Stores chunks (synchronous, `&self` — implementors use interior mutability).
14pub trait SyncChunkPut<const BODY_SIZE: usize = DEFAULT_BODY_SIZE> {
15    /// Error type for put operations.
16    type Error: std::error::Error + Send + Sync + 'static;
17
18    /// Store a chunk.
19    fn put(&self, chunk: AnyChunk<BODY_SIZE>) -> Result<(), Self::Error>;
20}
21
22/// Retrieves chunks by address (synchronous).
23pub trait SyncChunkGet<const BODY_SIZE: usize = DEFAULT_BODY_SIZE> {
24    /// Error type for get operations.
25    type Error: std::error::Error + Send + Sync + 'static;
26
27    /// Get a chunk by address.
28    fn get(&self, address: &ChunkAddress) -> Result<AnyChunk<BODY_SIZE>, Self::Error>;
29}
30
31/// Checks chunk existence (synchronous).
32pub trait SyncChunkHas<const BODY_SIZE: usize = DEFAULT_BODY_SIZE> {
33    /// Check if a chunk exists.
34    fn has(&self, address: &ChunkAddress) -> bool;
35}
36
37impl<T: SyncChunkPut<BS>, const BS: usize> SyncChunkPut<BS> for &T {
38    type Error = T::Error;
39    fn put(&self, chunk: AnyChunk<BS>) -> Result<(), Self::Error> {
40        (**self).put(chunk)
41    }
42}
43
44impl<T: SyncChunkPut<BS>, const BS: usize> SyncChunkPut<BS> for &mut T {
45    type Error = T::Error;
46    fn put(&self, chunk: AnyChunk<BS>) -> Result<(), Self::Error> {
47        (**self).put(chunk)
48    }
49}
50
51impl<T: SyncChunkGet<BS>, const BS: usize> SyncChunkGet<BS> for &T {
52    type Error = T::Error;
53    fn get(&self, address: &ChunkAddress) -> Result<AnyChunk<BS>, Self::Error> {
54        (**self).get(address)
55    }
56}
57
58impl<T: SyncChunkGet<BS>, const BS: usize> SyncChunkGet<BS> for &mut T {
59    type Error = T::Error;
60    fn get(&self, address: &ChunkAddress) -> Result<AnyChunk<BS>, Self::Error> {
61        (**self).get(address)
62    }
63}
64
65impl<T: SyncChunkHas<BS>, const BS: usize> SyncChunkHas<BS> for &T {
66    fn has(&self, address: &ChunkAddress) -> bool {
67        (**self).has(address)
68    }
69}
70
71impl<T: SyncChunkHas<BS>, const BS: usize> SyncChunkHas<BS> for &mut T {
72    fn has(&self, address: &ChunkAddress) -> bool {
73        (**self).has(address)
74    }
75}
76
77/// Async chunk retrieval (primary API).
78///
79/// Types implementing `SyncChunkGet + Send + Sync` get this automatically via
80/// a blanket impl. Types needing genuinely async retrieval (e.g. network
81/// fetch) should implement `ChunkGet` directly without implementing
82/// `SyncChunkGet`.
83pub trait ChunkGet<const BODY_SIZE: usize = DEFAULT_BODY_SIZE>: Send + Sync {
84    /// Error type for get operations.
85    type Error: std::error::Error + Send + Sync + 'static;
86
87    /// Get a chunk by address.
88    fn get(
89        &self,
90        address: &ChunkAddress,
91    ) -> impl Future<Output = Result<AnyChunk<BODY_SIZE>, Self::Error>> + Send;
92}
93
94impl<T, const BS: usize> ChunkGet<BS> for T
95where
96    T: SyncChunkGet<BS> + Send + Sync,
97{
98    type Error = T::Error;
99
100    async fn get(&self, address: &ChunkAddress) -> Result<AnyChunk<BS>, Self::Error> {
101        SyncChunkGet::get(self, address)
102    }
103}
104
105/// Async chunk existence check (primary API).
106pub trait ChunkHas<const BODY_SIZE: usize = DEFAULT_BODY_SIZE>: Send + Sync {
107    /// Check if a chunk exists.
108    fn has(&self, address: &ChunkAddress) -> impl Future<Output = bool> + Send;
109}
110
111impl<T, const BS: usize> ChunkHas<BS> for T
112where
113    T: SyncChunkHas<BS> + Send + Sync,
114{
115    async fn has(&self, address: &ChunkAddress) -> bool {
116        SyncChunkHas::has(self, address)
117    }
118}
119
120/// Async chunk storage (primary API, `&self`).
121///
122/// Implementors should use interior mutability (e.g. `Mutex`, `RwLock`).
123/// Types implementing `SyncChunkPut + Send + Sync` get this automatically.
124pub trait ChunkPut<const BODY_SIZE: usize = DEFAULT_BODY_SIZE>: Send + Sync {
125    /// Error type for put operations.
126    type Error: std::error::Error + Send + Sync + 'static;
127
128    /// Store a chunk.
129    fn put(
130        &self,
131        chunk: AnyChunk<BODY_SIZE>,
132    ) -> impl Future<Output = Result<(), Self::Error>> + Send;
133}
134
135impl<T, const BS: usize> ChunkPut<BS> for T
136where
137    T: SyncChunkPut<BS> + Send + Sync,
138{
139    type Error = T::Error;
140
141    async fn put(&self, chunk: AnyChunk<BS>) -> Result<(), Self::Error> {
142        SyncChunkPut::put(self, chunk)
143    }
144}