darkfi/geode/
chunked_storage.rs1use std::{
20 hash::{Hash, Hasher},
21 path::{Path, PathBuf},
22};
23
24use crate::geode::{file_sequence::FileSequence, MAX_CHUNK_SIZE};
25
26#[derive(Clone, Debug, Eq)]
27pub struct Chunk {
28 pub hash: blake3::Hash,
29 pub available: bool,
30 pub size: usize,
31}
32
33impl Hash for Chunk {
34 fn hash<H: Hasher>(&self, state: &mut H) {
35 self.hash.hash(state);
36 }
37}
38
39impl PartialEq for Chunk {
40 fn eq(&self, other: &Self) -> bool {
41 self.hash == other.hash
42 }
43}
44
45#[derive(Clone, Debug)]
48pub struct ChunkedStorage {
49 chunks: Vec<Chunk>,
52 fileseq: FileSequence,
55 is_dir: bool,
58}
59
60impl ChunkedStorage {
61 pub fn new(hashes: &[blake3::Hash], files: &[(PathBuf, u64)], is_dir: bool) -> Self {
62 Self {
63 chunks: hashes
64 .iter()
65 .map(|x| Chunk { hash: *x, available: false, size: MAX_CHUNK_SIZE })
66 .collect(),
67 fileseq: FileSequence::new(files, is_dir),
68 is_dir,
69 }
70 }
71
72 pub fn is_complete(&self) -> bool {
74 !self.chunks.iter().any(|c| !c.available)
75 }
76
77 pub fn iter(&self) -> core::slice::Iter<'_, Chunk> {
79 self.chunks.iter()
80 }
81
82 pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, Chunk> {
84 self.chunks.iter_mut()
85 }
86
87 pub fn len(&self) -> usize {
89 self.chunks.len()
90 }
91
92 pub fn is_empty(&self) -> bool {
94 self.chunks.is_empty()
95 }
96
97 pub fn local_chunks(&self) -> usize {
99 self.chunks.iter().filter(|c| c.available).count()
100 }
101
102 pub fn get_chunks(&self) -> &Vec<Chunk> {
104 &self.chunks
105 }
106
107 pub fn get_chunk_mut(&mut self, index: usize) -> &mut Chunk {
109 &mut self.chunks[index]
110 }
111
112 pub fn get_chunk_index(&self, hash: &blake3::Hash) -> Option<usize> {
113 for (i, chunk) in self.chunks.iter().enumerate() {
114 if chunk.hash == *hash {
115 return Some(i)
116 }
117 }
118 None
119 }
120
121 pub fn get_files(&self) -> &Vec<(PathBuf, u64)> {
123 self.fileseq.get_files()
124 }
125
126 pub fn get_fileseq(&self) -> &FileSequence {
128 &self.fileseq
129 }
130
131 pub fn get_fileseq_mut(&mut self) -> &mut FileSequence {
133 &mut self.fileseq
134 }
135
136 pub fn is_dir(&self) -> bool {
138 self.is_dir
139 }
140
141 pub fn get_chunks_of_file(&self, file: &Path) -> Vec<blake3::Hash> {
143 let files = self.fileseq.get_files();
144 let file_index = files.iter().position(|(f, _)| f == file);
145 if file_index.is_none() {
146 return vec![];
147 }
148 let file_index = file_index.unwrap();
149
150 let start_pos = self.fileseq.get_file_position(file_index);
151
152 let end_pos = start_pos + files[file_index].1;
153
154 let start_index = (start_pos as f64 / MAX_CHUNK_SIZE as f64).floor();
155 let end_index = (end_pos as f64 / MAX_CHUNK_SIZE as f64).floor();
156
157 let chunk_indexes: Vec<usize> = (start_index as usize..=end_index as usize).collect();
158
159 chunk_indexes
160 .iter()
161 .filter_map(|&index| self.chunks.get(index))
162 .map(|c| &c.hash)
163 .cloned()
164 .collect()
165 }
166}