Skip to main content

co_storage/storage/
mapped.rs

1// SPDX-License-Identifier: AGPL-3.0-only
2// Copyright (C) 2026 1io BRANDGUARDIAN GmbH
3
4use crate::{BlockStat, BlockStorage, BlockStorageContentMapping, StorageError};
5use async_trait::async_trait;
6use cid::Cid;
7use co_primitives::{Block, CloneWithBlockStorageSettings, MappedCid, MultiCodec};
8use std::collections::BTreeSet;
9
10/// Maps certain CID codecs to mapped CIDs using BlockStorageContentMapping.
11#[derive(Debug, Clone)]
12pub struct MappedBlockStorage<S> {
13	storage: S,
14	codecs: BTreeSet<MultiCodec>,
15}
16impl<S> MappedBlockStorage<S>
17where
18	S: BlockStorage + BlockStorageContentMapping + Send + Sync + 'static,
19{
20	pub fn new(storage: S, codecs: BTreeSet<MultiCodec>) -> Self {
21		Self { codecs, storage }
22	}
23
24	pub async fn to_mapped(&self, cid: &Cid) -> Cid {
25		let codec = cid.into();
26		if self.codecs.contains(&codec) {
27			match self.storage.to_mapped(cid).await {
28				Some(mapped) => mapped,
29				None => *cid,
30			}
31		} else {
32			*cid
33		}
34	}
35}
36#[async_trait]
37impl<S> BlockStorage for MappedBlockStorage<S>
38where
39	S: BlockStorage + BlockStorageContentMapping + Send + Sync + 'static,
40{
41	/// Returns a block from storage.
42	async fn get(&self, cid: &Cid) -> Result<Block, StorageError> {
43		Ok(self.storage.get(&self.to_mapped(cid).await).await?)
44	}
45
46	/// Inserts a block into storage.
47	/// Returns the CID of the block (guaranteed to be the same as the supplied).
48	async fn set(&self, block: Block) -> Result<Cid, StorageError> {
49		Ok(self.storage.set(block).await?)
50	}
51
52	/// Remove a block.
53	async fn remove(&self, cid: &Cid) -> Result<(), StorageError> {
54		Ok(self.storage.remove(&self.to_mapped(cid).await).await?)
55	}
56
57	/// Stat a block.
58	async fn stat(&self, cid: &Cid) -> Result<BlockStat, StorageError> {
59		Ok(self.storage.stat(&self.to_mapped(cid).await).await?)
60	}
61
62	fn max_block_size(&self) -> usize {
63		self.storage.max_block_size()
64	}
65}
66impl<S> CloneWithBlockStorageSettings for MappedBlockStorage<S>
67where
68	S: CloneWithBlockStorageSettings,
69{
70	fn clone_with_settings(&self, settings: co_primitives::BlockStorageCloneSettings) -> Self {
71		MappedBlockStorage { storage: self.storage.clone_with_settings(settings), codecs: self.codecs.clone() }
72	}
73}
74#[async_trait]
75impl<S> BlockStorageContentMapping for MappedBlockStorage<S>
76where
77	S: BlockStorage + BlockStorageContentMapping + 'static,
78{
79	async fn is_content_mapped(&self) -> bool {
80		self.storage.is_content_mapped().await
81	}
82
83	async fn to_plain(&self, mapped: &Cid) -> Option<Cid> {
84		self.storage.to_plain(mapped).await
85	}
86
87	async fn to_mapped(&self, plain: &Cid) -> Option<Cid> {
88		self.storage.to_mapped(plain).await
89	}
90
91	async fn insert_mappings(&self, mappings: BTreeSet<MappedCid>) {
92		self.storage.insert_mappings(mappings).await
93	}
94}