helia_interface/
lib.rs

1//! # Helia Interface
2//!
3//! The API defined by a Helia node
4//!
5//! This crate provides the core interfaces and traits that define the Helia IPFS implementation.
6//!
7//! ## Example
8//!
9//! ```rust
10//! use helia_interface::Helia;
11//!
12//! async fn do_something<H: Helia>(helia: H) {
13//!     // use helia node functions here
14//! }
15//! ```
16
17pub mod blocks;
18pub mod errors;
19pub mod pins;
20pub mod routing;
21
22use std::collections::HashMap;
23use std::future::Future;
24use std::pin::Pin;
25use std::sync::Arc;
26
27use async_trait::async_trait;
28use bytes::Bytes;
29use cid::Cid;
30use futures::Stream;
31use libp2p::Swarm;
32use serde::{Deserialize, Serialize};
33use tokio::sync::{broadcast, Mutex};
34use trust_dns_resolver::TokioAsyncResolver;
35
36pub use blocks::*;
37pub use errors::*;
38pub use pins::*;
39pub use routing::*;
40
41/// Type alias for async iterables/streams
42pub type AwaitIterable<T> = Pin<Box<dyn Stream<Item = T> + Send>>;
43
44/// Type alias for awaitable results
45pub type Await<T> = Pin<Box<dyn Future<Output = T> + Send>>;
46
47/// Options that include an abort signal for canceling operations
48#[derive(Debug, Default)]
49pub struct AbortOptions {
50    // For now, we'll use a simpler approach without tokio channels
51    // pub signal: Option<mpsc::Receiver<()>>,
52}
53
54impl Clone for AbortOptions {
55    fn clone(&self) -> Self {
56        // AbortOptions can't be cloned due to the receiver, so we create a new default one
57        Self::default()
58    }
59}
60
61/// Progress event for tracking operation status
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct ProgressEvent<T> {
64    pub event_type: String,
65    pub detail: T,
66}
67
68/// Options for operations that support progress tracking
69pub struct ProgressOptions<T> {
70    /// Optional progress event handler
71    pub on_progress: Option<Box<dyn Fn(ProgressEvent<T>) + Send + Sync>>,
72}
73
74impl<T> std::fmt::Debug for ProgressOptions<T> {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        f.debug_struct("ProgressOptions")
77            .field(
78                "on_progress",
79                &self.on_progress.as_ref().map(|_| "Some(closure)"),
80            )
81            .finish()
82    }
83}
84
85impl<T> Default for ProgressOptions<T> {
86    fn default() -> Self {
87        Self { on_progress: None }
88    }
89}
90
91impl<T> Clone for ProgressOptions<T> {
92    fn clone(&self) -> Self {
93        // Progress handlers can't be cloned, so we create a new default one
94        Self::default()
95    }
96}
97
98/// Codec loader for loading IPLD codecs
99#[async_trait]
100pub trait CodecLoader: Send + Sync {
101    /// Load a codec by its code
102    async fn load_codec(&self, code: u64) -> Result<Box<dyn Codec>, HeliaError>;
103}
104
105/// Hasher loader for loading multihash hashers
106#[async_trait]
107pub trait HasherLoader: Send + Sync {
108    /// Load a hasher by its code
109    async fn load_hasher(&self, code: u64) -> Result<Box<dyn Hasher>, HeliaError>;
110}
111
112/// IPLD codec trait
113#[async_trait]
114pub trait Codec: Send + Sync {
115    /// Encode data using this codec
116    async fn encode(&self, data: &[u8]) -> Result<Bytes, HeliaError>;
117
118    /// Decode data using this codec
119    async fn decode(&self, data: &[u8]) -> Result<Bytes, HeliaError>;
120
121    /// Get the codec code
122    fn code(&self) -> u64;
123}
124
125/// Multihash hasher trait
126#[async_trait]
127pub trait Hasher: Send + Sync {
128    /// Hash data using this hasher
129    async fn hash(&self, data: &[u8]) -> Result<multihash::Multihash<64>, HeliaError>;
130
131    /// Get the hasher code
132    fn code(&self) -> u64;
133}
134
135/// Events emitted by a Helia node
136#[derive(Debug, Clone)]
137pub enum HeliaEvent {
138    /// Node has started
139    Start,
140    /// Node has stopped
141    Stop,
142    /// Garbage collection started
143    GcStarted,
144    /// Garbage collection completed
145    GcCompleted,
146}
147
148/// Type alias for event receiver
149pub type HeliaEventReceiver = broadcast::Receiver<HeliaEvent>;
150
151/// Garbage collection options
152#[derive(Debug)]
153pub struct GcOptions {
154    /// Abort options
155    pub abort: AbortOptions,
156    /// Progress options for GC events
157    pub progress: ProgressOptions<GcEvent>,
158}
159
160impl Default for GcOptions {
161    fn default() -> Self {
162        Self {
163            abort: AbortOptions::default(),
164            progress: ProgressOptions::default(),
165        }
166    }
167}
168
169impl Clone for GcOptions {
170    fn clone(&self) -> Self {
171        Self {
172            abort: self.abort.clone(),
173            progress: self.progress.clone(),
174        }
175    }
176}
177
178/// Events emitted during garbage collection
179#[derive(Debug, Clone, Serialize, Deserialize)]
180pub enum GcEvent {
181    /// A CID was deleted
182    Deleted(Cid),
183    /// An error occurred during GC
184    Error(String),
185}
186
187/// Component logger for structured logging
188pub trait ComponentLogger: Send + Sync {
189    /// Log a debug message
190    fn debug(&self, message: &str);
191    /// Log an info message
192    fn info(&self, message: &str);
193    /// Log a warning message
194    fn warn(&self, message: &str);
195    /// Log an error message
196    fn error(&self, message: &str);
197}
198
199/// Metrics collection interface
200#[async_trait]
201pub trait Metrics: Send + Sync {
202    /// Record a counter metric
203    async fn record_counter(&self, name: &str, value: u64, labels: HashMap<String, String>);
204
205    /// Record a gauge metric
206    async fn record_gauge(&self, name: &str, value: f64, labels: HashMap<String, String>);
207
208    /// Record a histogram metric
209    async fn record_histogram(&self, name: &str, value: f64, labels: HashMap<String, String>);
210}
211
212/// Non-generic Helia trait for backward compatibility and trait objects
213#[async_trait]
214pub trait Helia: Send + Sync {
215    /// The blockstore for storing blocks
216    fn blockstore(&self) -> &dyn Blocks;
217
218    /// The datastore for key-value storage
219    fn datastore(&self) -> &dyn Datastore;
220
221    /// Pinning operations
222    fn pins(&self) -> &dyn Pins;
223
224    /// The logger component
225    fn logger(&self) -> &dyn ComponentLogger;
226
227    /// The routing component
228    fn routing(&self) -> &dyn Routing;
229
230    /// DNS resolver
231    fn dns(&self) -> &TokioAsyncResolver;
232
233    /// Optional metrics collector
234    fn metrics(&self) -> Option<&dyn Metrics>;
235
236    /// Subscribe to events emitted by this Helia node
237    /// 
238    /// Returns a receiver that will receive all events emitted by the node.
239    /// Multiple subscribers can listen to events simultaneously.
240    /// 
241    /// # Example
242    /// 
243    /// ```rust,ignore
244    /// use helia_interface::{Helia, HeliaEvent};
245    /// 
246    /// let mut events_rx = helia.subscribe_events();
247    /// 
248    /// tokio::spawn(async move {
249    ///     while let Ok(event) = events_rx.recv().await {
250    ///         match event {
251    ///             HeliaEvent::Start => println!("Helia started"),
252    ///             HeliaEvent::Stop => println!("Helia stopped"),
253    ///             HeliaEvent::GcStarted => println!("GC started"),
254    ///             HeliaEvent::GcCompleted => println!("GC completed"),
255    ///         }
256    ///     }
257    /// });
258    /// ```
259    fn subscribe_events(&self) -> HeliaEventReceiver;
260
261    /// Start the Helia node
262    async fn start(&self) -> Result<(), HeliaError>;
263
264    /// Stop the Helia node
265    async fn stop(&self) -> Result<(), HeliaError>;
266
267    /// Perform garbage collection
268    async fn gc(&self, options: Option<GcOptions>) -> Result<(), HeliaError>;
269
270    /// Load an IPLD codec
271    async fn get_codec(&self, code: u64) -> Result<Box<dyn Codec>, HeliaError>;
272
273    /// Load a hasher
274    async fn get_hasher(&self, code: u64) -> Result<Box<dyn Hasher>, HeliaError>;
275}
276
277/// Generic Helia trait with libp2p type parameter for concrete implementations
278#[async_trait]
279pub trait HeliaWithLibp2p<T>: Helia
280where
281    T: libp2p::swarm::NetworkBehaviour + Send + 'static,
282{
283    /// The libp2p swarm instance (wrapped in Arc<Mutex<>> for thread safety)
284    fn libp2p(&self) -> Arc<Mutex<Swarm<T>>>;
285}
286
287/// Trait for NetworkBehaviours that include Bitswap
288///
289/// This trait allows Helia to work with any custom `NetworkBehaviour` that includes
290/// a `BitswapBehaviour` field. By implementing this trait, applications can share
291/// their custom swarm with Helia instead of running separate connections.
292///
293/// # Example
294///
295/// ```rust,ignore
296/// use libp2p::swarm::NetworkBehaviour;
297/// use helia_bitswap::BitswapBehaviour;
298/// use helia_interface::WithBitswap;
299///
300/// #[derive(NetworkBehaviour)]
301/// pub struct MyBehaviour {
302///     pub gossipsub: gossipsub::Behaviour,
303///     pub bitswap: BitswapBehaviour,
304/// }
305///
306/// impl WithBitswap for MyBehaviour {
307///     fn bitswap_mut(&mut self) -> &mut BitswapBehaviour {
308///         &mut self.bitswap
309///     }
310///     
311///     fn bitswap(&self) -> &BitswapBehaviour {
312///         &self.bitswap
313///     }
314/// }
315/// ```
316pub trait WithBitswap {
317    /// Get a mutable reference to the BitswapBehaviour
318    fn bitswap_mut(&mut self) -> &mut dyn std::any::Any;
319    
320    /// Get an immutable reference to the BitswapBehaviour
321    fn bitswap(&self) -> &dyn std::any::Any;
322}
323
324/// Key-value datastore interface
325#[async_trait]
326pub trait Datastore: Send + Sync {
327    /// Get a value by key
328    async fn get(&self, key: &[u8]) -> Result<Option<Bytes>, HeliaError>;
329
330    /// Put a key-value pair
331    async fn put(&self, key: &[u8], value: Bytes) -> Result<(), HeliaError>;
332
333    /// Delete a key
334    async fn delete(&self, key: &[u8]) -> Result<(), HeliaError>;
335
336    /// Check if a key exists
337    async fn has(&self, key: &[u8]) -> Result<bool, HeliaError>;
338
339    /// Query for keys with optional filters
340    async fn query(&self, prefix: Option<&[u8]>) -> Result<AwaitIterable<Bytes>, HeliaError>;
341}