co_storage/storage/
static_storage.rs1use crate::{ExtendedBlock, ExtendedBlockStorage};
5use async_trait::async_trait;
6use cid::Cid;
7use co_primitives::{Block, BlockStat, BlockStorage, KnownMultiCodec, StorageError};
8use std::{collections::BTreeMap, ops::Range};
9
10#[derive(Debug, Clone)]
12pub struct StaticBlockStorage<'a> {
13 data: &'a [u8],
14 blocks: BTreeMap<Cid, StaticBlock>,
15}
16impl<'a> StaticBlockStorage<'a> {
17 pub fn builder(data: &'a [u8]) -> StaticBlockStorageBuilder<'a> {
19 StaticBlockStorageBuilder::new(data)
20 }
21
22 pub fn new_unchecked(cid: Cid, data: &'a [u8]) -> Self {
24 Self { blocks: [(cid, StaticBlock::Range(0..data.len()))].into_iter().collect(), data }
25 }
26
27 pub fn new_raw(data: &'a [u8]) -> (Cid, Self) {
29 let cid = Block::cid_data(KnownMultiCodec::Raw, data);
30 let storage = Self { blocks: [(cid, StaticBlock::Range(0..data.len()))].into_iter().collect(), data };
31 (cid, storage)
32 }
33}
34#[async_trait]
35impl<'a> BlockStorage for StaticBlockStorage<'a> {
36 async fn get(&self, cid: &Cid) -> Result<Block, StorageError> {
37 let block = self
38 .blocks
39 .get(cid)
40 .ok_or_else(|| StorageError::NotFound(*cid, anyhow::anyhow!("Block not found")))?;
41 Ok(Block::new_unchecked(*cid, block.to_vec(self.data)))
42 }
43
44 async fn set(&self, _block: Block) -> Result<Cid, StorageError> {
45 Err(StorageError::InvalidArgument(anyhow::anyhow!("Readonly storage")))
46 }
47
48 async fn stat(&self, cid: &Cid) -> Result<BlockStat, StorageError> {
49 let block = self
50 .blocks
51 .get(cid)
52 .ok_or_else(|| StorageError::NotFound(*cid, anyhow::anyhow!("Block not found")))?;
53 Ok(BlockStat { size: block.len() as u64 })
54 }
55
56 async fn remove(&self, _cid: &Cid) -> Result<(), StorageError> {
57 Err(StorageError::InvalidArgument(anyhow::anyhow!("Readonly storage")))
58 }
59
60 fn max_block_size(&self) -> usize {
61 0
62 }
63}
64#[async_trait]
65impl<'a> ExtendedBlockStorage for StaticBlockStorage<'a> {
66 async fn set_extended(&self, _block: ExtendedBlock) -> Result<Cid, StorageError> {
67 Err(StorageError::InvalidArgument(anyhow::anyhow!("Readonly storage")))
68 }
69
70 async fn exists(&self, cid: &Cid) -> Result<bool, StorageError> {
71 Ok(self.blocks.contains_key(cid))
72 }
73
74 async fn clear(&self) -> Result<(), StorageError> {
75 Err(StorageError::InvalidArgument(anyhow::anyhow!("Readonly storage")))
76 }
77}
78
79#[derive(Debug, Clone)]
80enum StaticBlock {
81 Range(Range<usize>),
82 Data(Vec<u8>),
83}
84impl StaticBlock {
85 pub fn to_vec(&self, data: &[u8]) -> Vec<u8> {
86 match self {
87 Self::Range(range) => data[range.start..range.end].to_vec(),
88 Self::Data(data) => data.clone(),
89 }
90 }
91
92 pub fn len(&self) -> usize {
93 match self {
94 StaticBlock::Range(range) => range.len(),
95 StaticBlock::Data(data) => data.len(),
96 }
97 }
98}
99
100pub struct StaticBlockStorageBuilder<'a> {
101 data: &'a [u8],
102 blocks: BTreeMap<Cid, StaticBlock>,
103}
104impl<'a> StaticBlockStorageBuilder<'a> {
105 pub fn new(data: &'a [u8]) -> Self {
106 Self { data, blocks: Default::default() }
107 }
108
109 pub fn with_range(mut self, cid: Cid, range: Range<usize>) -> Self {
110 self.blocks.insert(cid, StaticBlock::Range(range));
111 self
112 }
113
114 pub fn with_block(mut self, cid: Cid, data: Vec<u8>) -> Self {
115 self.blocks.insert(cid, StaticBlock::Data(data));
116 self
117 }
118
119 pub fn build(self) -> StaticBlockStorage<'a> {
120 StaticBlockStorage { blocks: self.blocks, data: self.data }
121 }
122}