rectangle_device_blocks/
dir.rs

1use libipld::Ipld;
2use libipld::pb::{DagPbCodec, PbNode};
3use prost::Message;
4use std::iter::{once, Once};
5use std::convert::TryFrom;
6use crate::core::{Block, Cid, DefaultHashType, BLOCK_MAX_BYTES};
7use crate::package::Package;
8use crate::unixfs;
9
10pub use libipld::pb::PbLink;
11
12pub struct DirectoryBlock {
13    pub block: Block,
14    pub links: Vec<PbLink>
15}
16
17impl DirectoryBlock {
18    pub fn new(links: Vec<PbLink>) -> DirectoryBlock {
19        let dir = unixfs::pb::Data {
20            r#type: unixfs::pb::data::DataType::Directory.into(),
21            blocksizes: vec![],
22            filesize: None,
23            data: None,
24            hash_type: None,
25            fanout: None
26        };
27
28        let mut data = vec![];
29        dir.encode(&mut data).unwrap();
30        let node = PbNode {
31            data: data.into_boxed_slice(),
32            links,
33        };
34        let ipld: Ipld = node.into();
35
36        // This is a single block directory. It can only hold ~10000-20000 files
37        let block = Block::encode(DagPbCodec, DefaultHashType, &ipld).unwrap();
38        assert!(block.data.len() <= BLOCK_MAX_BYTES);
39
40        let links = PbNode::try_from(&ipld).unwrap().links;
41        DirectoryBlock { block, links }
42    }
43}
44
45impl Package for DirectoryBlock {
46    type BlockIterator = Once<Block>;
47
48    fn cid(&self) -> &Cid {
49        &self.block.cid
50    }
51
52    fn total_size(&self) -> u64 {
53        let linked_size: u64 = self.links.iter().map(|link| link.size).sum();
54        let dir_block_size = self.block.data.len() as u64;
55        linked_size + dir_block_size
56    }
57
58    fn into_blocks(self) -> Self::BlockIterator {
59        once(self.block)
60    }
61}