1use chacha20::cipher::{KeyIvInit, StreamCipher};
13use chacha20::ChaCha20;
14
15use crate::errors::*;
16use crate::log::*;
17use crate::types::*;
18
19impl BlockV0 {
20 pub fn new(
21 children: Vec<BlockId>,
22 mut header_ref: Option<CommitHeaderRef>,
23 content: Vec<u8>,
24 key: Option<SymKey>,
25 ) -> BlockV0 {
26 let (commit_header, commit_header_key) = header_ref
27 .take()
28 .map_or((CommitHeaderObject::None, None), |obj_ref| {
29 (obj_ref.obj, Some(obj_ref.key))
30 });
31 let bc = BlockContentV0 {
32 children,
33 commit_header: commit_header,
34 encrypted_content: content,
35 };
36 let mut b = BlockV0 {
37 id: None,
38 key,
39 content: BlockContent::V0(bc),
40 commit_header_key,
41 };
42 b.id = Some(b.compute_id());
43 b
44 }
45
46 pub fn dummy() -> BlockV0 {
47 BlockV0::new(vec![], None, vec![], None)
48 }
49
50 pub fn new_random_access(
51 children: Vec<BlockId>,
52 content: Vec<u8>,
53 key: Option<SymKey>,
54 ) -> BlockV0 {
55 let bc = BlockContentV0 {
56 children,
57 commit_header: CommitHeaderObject::RandomAccess,
58 encrypted_content: content,
59 };
60 let mut b = BlockV0 {
61 id: None,
62 key,
63 content: BlockContent::V0(bc),
64 commit_header_key: None,
65 };
66 b.id = Some(b.compute_id());
67 b
68 }
69
70 pub fn compute_id(&self) -> BlockId {
72 let ser = serde_bare::to_vec(&self.content).unwrap();
73 let hash = blake3::hash(ser.as_slice());
74 Digest::Blake3Digest32(hash.as_bytes().clone())
75 }
76
77 pub fn children(&self) -> &Vec<BlockId> {
78 self.content.children()
79 }
80}
81
82impl From<&Digest> for String {
83 fn from(id: &Digest) -> Self {
84 let mut ser = serde_bare::to_vec(id).unwrap();
85 ser.reverse();
86 base64_url::encode(&ser)
87 }
88}
89
90impl BlockContent {
91 pub fn encrypted_content(&self) -> &Vec<u8> {
93 match self {
94 BlockContent::V0(bc) => &bc.encrypted_content,
95 }
96 }
97
98 pub fn children(&self) -> &Vec<BlockId> {
107 match self {
108 BlockContent::V0(b) => &b.children,
109 }
110 }
111}
112
113impl Block {
114 pub fn new(
115 children: Vec<BlockId>,
116 header_ref: Option<CommitHeaderRef>,
117 content: Vec<u8>,
118 key: Option<SymKey>,
119 ) -> Block {
120 Block::V0(BlockV0::new(children, header_ref, content, key))
121 }
122
123 pub fn dummy() -> Block {
124 Block::V0(BlockV0::dummy())
125 }
126
127 pub fn new_random_access(
128 children: Vec<BlockId>,
129 content: Vec<u8>,
130 key: Option<SymKey>,
131 ) -> Block {
132 Block::V0(BlockV0::new_random_access(children, content, key))
133 }
134
135 pub fn new_with_encrypted_content(content: Vec<u8>, key: Option<SymKey>) -> Block {
136 Block::V0(BlockV0::new(vec![], None, content, key))
137 }
138
139 pub fn size(&self) -> usize {
140 serde_bare::to_vec(&self).unwrap().len()
141 }
142
143 pub fn compute_id(&self) -> BlockId {
145 match self {
146 Block::V0(v0) => v0.compute_id(),
147 }
148 }
149
150 pub fn get_and_save_id(&mut self) -> BlockId {
152 match &self {
153 Block::V0(b) => match b.id {
154 Some(id) => id,
155 None => {
156 let id = self.compute_id();
157 let Block::V0(c) = self;
158 c.id = Some(id);
159 id
160 }
161 },
162 }
163 }
164
165 pub fn id(&self) -> BlockId {
167 match self {
168 Block::V0(b) => match b.id {
169 Some(id) => id,
170 None => self.compute_id(),
171 },
172 }
173 }
174
175 pub fn content(&self) -> &BlockContent {
177 match self {
178 Block::V0(b) => &b.content,
179 }
180 }
181
182 pub fn encrypted_content(&self) -> &Vec<u8> {
184 match self {
185 Block::V0(b) => &b.content.encrypted_content(),
186 }
187 }
188
189 pub fn children(&self) -> &Vec<BlockId> {
191 match self {
192 Block::V0(b) => &b.content.children(),
193 }
194 }
195
196 pub fn destroy_header(&mut self) {
197 match self {
198 Block::V0(b) => b.commit_header_key = None,
199 }
200 }
201
202 pub fn header_ref(&self) -> Option<CommitHeaderRef> {
204 match self {
205 Block::V0(b) => match b.commit_header_key.as_ref() {
206 Some(key) => match b.content.commit_header_obj() {
207 CommitHeaderObject::None => None,
208 CommitHeaderObject::RandomAccess => None,
209 _ => Some(CommitHeaderRef {
210 obj: b.content.commit_header_obj().clone(),
211 key: key.clone(),
212 }),
213 },
214
215 None => None,
216 },
217 }
218 }
219
220 pub fn key(&self) -> Option<SymKey> {
222 match self {
223 Block::V0(b) => b.key.clone(),
224 }
225 }
226
227 pub fn set_key(&mut self, key: Option<SymKey>) {
229 match self {
230 Block::V0(b) => b.key = key,
231 }
232 }
233
234 pub fn read(
235 &self,
236 key: &SymKey,
237 ) -> Result<(Vec<(BlockId, BlockKey)>, Vec<u8>), ObjectParseError> {
238 match self {
239 Block::V0(b) => {
240 let mut content_dec = b.content.encrypted_content().clone();
242 match key {
243 SymKey::ChaCha20Key(key) => {
244 let nonce = [0u8; 12];
245 let mut cipher = ChaCha20::new(key.into(), &nonce.into());
246 let mut content_dec_slice = &mut content_dec.as_mut_slice();
247 cipher.apply_keystream(&mut content_dec_slice);
248 }
249 }
250
251 let content: ChunkContentV0;
253 match serde_bare::from_slice(content_dec.as_slice()) {
254 Ok(c) => content = c,
255 Err(_e) => {
256 return Err(ObjectParseError::BlockDeserializeError);
258 }
259 }
260 match content {
262 ChunkContentV0::InternalNode(keys) => {
263 let b_children = b.children();
264 if keys.len() != b_children.len() {
265 log_debug!(
266 "Invalid keys length: got {}, expected {}",
267 keys.len(),
268 b_children.len()
269 );
270 log_debug!("!!! children: {:?}", b_children);
271 log_debug!("!!! keys: {:?}", keys);
272 return Err(ObjectParseError::InvalidKeys);
273 }
274 let mut children = Vec::with_capacity(b_children.len());
275 for (id, key) in b_children.iter().zip(keys.iter()) {
276 children.push((id.clone(), key.clone()));
277 }
278 Ok((children, vec![]))
279 }
280 ChunkContentV0::DataChunk(chunk) => Ok((vec![], chunk)),
281 }
282 }
283 }
284 }
285}