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 pins;
19pub mod routing;
20pub mod errors;
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::Mutex;
34use trust_dns_resolver::TokioAsyncResolver;
35
36pub use blocks::*;
37pub use pins::*;
38pub use routing::*;
39pub use errors::*;
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("on_progress", &self.on_progress.as_ref().map(|_| "Some(closure)"))
78            .finish()
79    }
80}
81
82impl<T> Default for ProgressOptions<T> {
83    fn default() -> Self {
84        Self {
85            on_progress: None,
86        }
87    }
88}
89
90impl<T> Clone for ProgressOptions<T> {
91    fn clone(&self) -> Self {
92        // Progress handlers can't be cloned, so we create a new default one
93        Self::default()
94    }
95}
96
97/// Codec loader for loading IPLD codecs
98#[async_trait]
99pub trait CodecLoader: Send + Sync {
100    /// Load a codec by its code
101    async fn load_codec(&self, code: u64) -> Result<Box<dyn Codec>, HeliaError>;
102}
103
104/// Hasher loader for loading multihash hashers
105#[async_trait]
106pub trait HasherLoader: Send + Sync {
107    /// Load a hasher by its code
108    async fn load_hasher(&self, code: u64) -> Result<Box<dyn Hasher>, HeliaError>;
109}
110
111/// IPLD codec trait
112#[async_trait]
113pub trait Codec: Send + Sync {
114    /// Encode data using this codec
115    async fn encode(&self, data: &[u8]) -> Result<Bytes, HeliaError>;
116    
117    /// Decode data using this codec
118    async fn decode(&self, data: &[u8]) -> Result<Bytes, HeliaError>;
119    
120    /// Get the codec code
121    fn code(&self) -> u64;
122}
123
124/// Multihash hasher trait
125#[async_trait]
126pub trait Hasher: Send + Sync {
127    /// Hash data using this hasher
128    async fn hash(&self, data: &[u8]) -> Result<multihash::Multihash<64>, HeliaError>;
129    
130    /// Get the hasher code
131    fn code(&self) -> u64;
132}
133
134/// Events emitted by a Helia node
135#[derive(Debug, Clone)]
136pub enum HeliaEvent {
137    /// Node has started
138    Start,
139    /// Node has stopped
140    Stop,
141}
142
143/// Garbage collection options
144#[derive(Debug)]
145pub struct GcOptions {
146    /// Abort options
147    pub abort: AbortOptions,
148    /// Progress options for GC events
149    pub progress: ProgressOptions<GcEvent>,
150}
151
152impl Default for GcOptions {
153    fn default() -> Self {
154        Self {
155            abort: AbortOptions::default(),
156            progress: ProgressOptions::default(),
157        }
158    }
159}
160
161impl Clone for GcOptions {
162    fn clone(&self) -> Self {
163        Self {
164            abort: self.abort.clone(),
165            progress: self.progress.clone(),
166        }
167    }
168}
169
170/// Events emitted during garbage collection
171#[derive(Debug, Clone, Serialize, Deserialize)]
172pub enum GcEvent {
173    /// A CID was deleted
174    Deleted(Cid),
175    /// An error occurred during GC
176    Error(String),
177}
178
179/// Component logger for structured logging
180pub trait ComponentLogger: Send + Sync {
181    /// Log a debug message
182    fn debug(&self, message: &str);
183    /// Log an info message
184    fn info(&self, message: &str);
185    /// Log a warning message
186    fn warn(&self, message: &str);
187    /// Log an error message
188    fn error(&self, message: &str);
189}
190
191/// Metrics collection interface
192#[async_trait]
193pub trait Metrics: Send + Sync {
194    /// Record a counter metric
195    async fn record_counter(&self, name: &str, value: u64, labels: HashMap<String, String>);
196    
197    /// Record a gauge metric
198    async fn record_gauge(&self, name: &str, value: f64, labels: HashMap<String, String>);
199    
200    /// Record a histogram metric
201    async fn record_histogram(&self, name: &str, value: f64, labels: HashMap<String, String>);
202}
203
204/// Non-generic Helia trait for backward compatibility and trait objects
205#[async_trait]
206pub trait Helia: Send + Sync {
207    /// The blockstore for storing blocks
208    fn blockstore(&self) -> &dyn Blocks;
209    
210    /// The datastore for key-value storage
211    fn datastore(&self) -> &dyn Datastore;
212    
213    /// Pinning operations
214    fn pins(&self) -> &dyn Pins;
215    
216    /// The logger component
217    fn logger(&self) -> &dyn ComponentLogger;
218    
219    /// The routing component
220    fn routing(&self) -> &dyn Routing;
221    
222    /// DNS resolver
223    fn dns(&self) -> &TokioAsyncResolver;
224    
225    /// Optional metrics collector
226    fn metrics(&self) -> Option<&dyn Metrics>;
227    
228    /// Start the Helia node
229    async fn start(&self) -> Result<(), HeliaError>;
230    
231    /// Stop the Helia node
232    async fn stop(&self) -> Result<(), HeliaError>;
233    
234    /// Perform garbage collection
235    async fn gc(&self, options: Option<GcOptions>) -> Result<(), HeliaError>;
236    
237    /// Load an IPLD codec
238    async fn get_codec(&self, code: u64) -> Result<Box<dyn Codec>, HeliaError>;
239    
240    /// Load a hasher
241    async fn get_hasher(&self, code: u64) -> Result<Box<dyn Hasher>, HeliaError>;
242}
243
244/// Generic Helia trait with libp2p type parameter for concrete implementations
245#[async_trait]
246pub trait HeliaWithLibp2p<T>: Helia 
247where 
248    T: libp2p::swarm::NetworkBehaviour + Send + 'static
249{
250    /// The libp2p swarm instance (wrapped in Arc<Mutex<>> for thread safety)
251    fn libp2p(&self) -> Arc<Mutex<Swarm<T>>>;
252}
253
254/// Key-value datastore interface
255#[async_trait]
256pub trait Datastore: Send + Sync {
257    /// Get a value by key
258    async fn get(&self, key: &[u8]) -> Result<Option<Bytes>, HeliaError>;
259    
260    /// Put a key-value pair
261    async fn put(&self, key: &[u8], value: Bytes) -> Result<(), HeliaError>;
262    
263    /// Delete a key
264    async fn delete(&self, key: &[u8]) -> Result<(), HeliaError>;
265    
266    /// Check if a key exists
267    async fn has(&self, key: &[u8]) -> Result<bool, HeliaError>;
268    
269    /// Query for keys with optional filters
270    async fn query(&self, prefix: Option<&[u8]>) -> Result<AwaitIterable<Bytes>, HeliaError>;
271}