rectangle_device_blocks/
raw.rs

1use libipld::Ipld;
2use libipld::raw::RawCodec;
3use libipld::pb::{DagPbCodec, PbLink, PbNode};
4use prost::Message;
5use std::iter::{once, Once, Chain, Map, Flatten};
6use std::vec;
7use crate::core::{Block, Cid, DefaultHashType, BLOCK_MAX_BYTES};
8use crate::package::Package;
9use crate::unixfs;
10
11#[derive(Clone)]
12pub struct RawBlockFile {
13    pub block: Block,
14}
15
16impl RawBlockFile {
17    pub fn new(data: &[u8]) -> RawBlockFile {
18        assert!(data.len() <= BLOCK_MAX_BYTES);
19        RawBlockFile { block: Block::encode(RawCodec, DefaultHashType, data).unwrap() }
20    }
21}
22
23impl Package for RawBlockFile {
24    type BlockIterator = Once<Block>;
25
26    fn cid(&self) -> &Cid {
27        &self.block.cid
28    }
29
30    fn total_size(&self) -> u64 {
31        self.block.data.len() as u64
32    }
33
34    fn into_blocks(self) -> Self::BlockIterator {
35        once(self.block)
36    }
37}
38
39#[derive(Clone)]
40pub struct MultiRawBlockFile {
41    pub root: Block,
42    pub parts: Vec<RawBlockFile>,
43}
44
45impl MultiRawBlockFile {
46    pub fn from_bytes(bytes: &[u8]) -> MultiRawBlockFile {
47        let chunks = bytes.chunks(BLOCK_MAX_BYTES);
48        let parts = chunks.map(|chunk| RawBlockFile::new(chunk));
49        MultiRawBlockFile::new(parts.collect())
50    }
51
52    pub fn new(parts: Vec<RawBlockFile>) -> MultiRawBlockFile {
53        let links: Vec<PbLink> = parts.iter().map(|part| part.link("".to_string())).collect();
54        let sizes: Vec<u64> = parts.iter().map(|part| part.block.data.len() as u64).collect();
55        let filesize = sizes.iter().sum();
56
57        let file = unixfs::pb::Data {
58            r#type: unixfs::pb::data::DataType::File.into(),
59            blocksizes: sizes,
60            filesize: Some(filesize),
61            data: None,
62            hash_type: None,
63            fanout: None
64        };
65
66        let node = {
67            let mut data: Vec<u8> = vec![];
68            file.encode(&mut data).unwrap();
69            PbNode { links, data: data.into_boxed_slice() }
70        };
71        let ipld: Ipld = node.into();
72
73        // It takes a file size of about 32GB to reach this limit.
74        // If it's ever realistic for us to hit this limit, we could use additional index blocks.
75        let root = Block::encode(DagPbCodec, DefaultHashType, &ipld).unwrap();
76        assert!(root.data.len() <= BLOCK_MAX_BYTES);
77
78        MultiRawBlockFile { root, parts }
79    }
80}
81
82type RawIntoBlocksFn = fn(RawBlockFile) -> <RawBlockFile as Package>::BlockIterator;
83
84impl Package for MultiRawBlockFile {
85    type BlockIterator = Chain<Once<Block>, Flatten<Map< vec::IntoIter<RawBlockFile>, RawIntoBlocksFn >>>;
86
87    fn cid(&self) -> &Cid {
88        &self.root.cid
89    }
90
91    fn total_size(&self) -> u64 {
92        let parts_size: u64 = self.parts.iter().map(|part| part.total_size()).sum();
93        let root_size = self.root.data.len() as u64;
94        parts_size + root_size
95    }
96
97    fn into_blocks(self) -> Self::BlockIterator {
98        once(self.root).chain(self.parts.into_iter().map(RawBlockFile::into_blocks as RawIntoBlocksFn).flatten())
99    }
100}