helia_interface/
pins.rs

1//! Pinning interface for content addressing
2
3use std::collections::HashMap;
4
5use async_trait::async_trait;
6use cid::Cid;
7use serde::{Deserialize, Serialize};
8
9use crate::{AbortOptions, AwaitIterable, GetBlockProgressEvents, HeliaError, ProgressOptions};
10
11/// Types of pins
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13#[serde(rename_all = "lowercase")]
14pub enum PinType {
15    /// Pin recursively through all child links
16    Recursive,
17    /// Pin only this specific block
18    Direct,
19    /// Pinned indirectly through another pin
20    Indirect,
21}
22
23/// A pin represents a pinned content identifier
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct Pin {
26    /// The content identifier
27    pub cid: Cid,
28    /// The depth of the pin (0 for direct, positive for recursive)
29    pub depth: u64,
30    /// User-defined metadata associated with the pin
31    pub metadata: HashMap<String, PinMetadataValue>,
32}
33
34/// Valid metadata values for pins
35#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
36#[serde(untagged)]
37pub enum PinMetadataValue {
38    String(String),
39    Number(f64),
40    Boolean(bool),
41}
42
43/// Progress events for adding pins
44#[derive(Debug, Clone, Serialize, Deserialize)]
45#[serde(tag = "type")]
46pub enum AddPinEvents {
47    #[serde(rename = "helia:pin:add")]
48    Add { cid: Cid },
49}
50
51/// Options for adding pins
52#[derive(Debug, Default)]
53pub struct AddOptions {
54    /// Abort options
55    pub abort: AbortOptions,
56    /// Progress options
57    pub progress: ProgressOptions<AddPinProgressEvents>,
58    /// How deeply to pin the DAG, None means infinite depth
59    pub depth: Option<u64>,
60    /// Optional user-defined metadata to store with the pin
61    pub metadata: HashMap<String, PinMetadataValue>,
62}
63
64impl Clone for AddOptions {
65    fn clone(&self) -> Self {
66        Self {
67            abort: self.abort.clone(),
68            progress: self.progress.clone(),
69            depth: self.depth,
70            metadata: self.metadata.clone(),
71        }
72    }
73}
74
75/// Combined progress events for adding pins
76#[derive(Debug, Clone, Serialize, Deserialize)]
77#[serde(untagged)]
78pub enum AddPinProgressEvents {
79    Add(AddPinEvents),
80    GetBlock(GetBlockProgressEvents),
81}
82
83/// Options for removing pins
84#[derive(Debug, Clone, Default)]
85pub struct RmOptions {
86    /// Abort options
87    pub abort: AbortOptions,
88}
89
90/// Options for listing pins
91#[derive(Debug, Clone, Default)]
92pub struct LsOptions {
93    /// Abort options
94    pub abort: AbortOptions,
95    /// Optional CID to filter pins by
96    pub cid: Option<Cid>,
97}
98
99/// Options for checking if content is pinned
100#[derive(Debug, Clone, Default)]
101pub struct IsPinnedOptions {
102    /// Abort options
103    pub abort: AbortOptions,
104}
105
106/// Pinning interface
107#[async_trait]
108pub trait Pins: Send + Sync {
109    /// Pin a CID with the given options
110    async fn add(&self, cid: &Cid, options: Option<AddOptions>) -> Result<(), HeliaError>;
111
112    /// Remove a pin for the given CID
113    async fn rm(&self, cid: &Cid, options: Option<RmOptions>) -> Result<(), HeliaError>;
114
115    /// List all pins, optionally filtered by CID
116    async fn ls(&self, options: Option<LsOptions>) -> Result<AwaitIterable<Pin>, HeliaError>;
117
118    /// Check if a CID is pinned
119    async fn is_pinned(
120        &self,
121        cid: &Cid,
122        options: Option<IsPinnedOptions>,
123    ) -> Result<bool, HeliaError>;
124}