1use crate::{BlockKey, BlockReference, BlockStorage, ReadCapability};
6use futures_lite::io::{AsyncWrite, AsyncWriteExt};
7use std::collections::VecDeque;
8use thiserror::Error as ThisError;
9
10#[derive(ThisError, Debug)]
11pub enum Error {
12 #[error("invalid padding")]
13 Padding,
14 #[error("i/o error: {0}")]
15 Io(#[from] std::io::Error),
16 #[error("a block was not found in storage")]
17 BlockNotFound,
18 #[error("non-standard block size")]
19 NonstandardBlockSize,
20 #[error("unexpected block size")]
21 UnexpectedBlockSize,
22 #[error("unexpected key size")]
23 UnexpectedKeySize,
24 #[error("invalid base32 encoding")]
26 InvalidBase32,
27}
28
29pub type Result<T = ()> = std::result::Result<T, Error>;
30
31fn unpad(input: &mut &[u8]) -> Result {
32 loop {
33 if input.len() == 0 {
34 return Err(Error::Padding);
35 }
36 let next = input[input.len() - 1];
37 *input = &mut &input[..input.len() - 1];
38 match next {
39 0 => (),
40 0x80 => return Ok(()),
41 _ => return Err(Error::Padding),
42 }
43 }
44}
45
46pub async fn decode<S: BlockStorage<1024> + BlockStorage<{ 32 * 1024 }>, W: AsyncWrite + Unpin>(
49 target: &mut W,
50 read_capability: &ReadCapability,
51 block_storage: &S,
52) -> Result<()> {
53 match read_capability.block_size {
54 1024 => decode_const::<_, _, 1024>(target, read_capability, block_storage).await,
55 32768 => decode_const::<_, _, 32768>(target, read_capability, block_storage).await,
56 _ => Err(Error::NonstandardBlockSize),
57 }
58}
59
60pub async fn decode_const<S: BlockStorage<BS>, W: AsyncWrite + Unpin, const BS: usize>(
61 target: &mut W,
62 read_capability: &ReadCapability,
63 block_storage: &S,
64) -> Result<()> {
65 if read_capability.block_size != BS {
66 return Err(Error::UnexpectedBlockSize);
67 }
68
69 let mut subtrees = VecDeque::new();
70 subtrees.push_back(read_capability.clone());
71
72 while let Some(tree) = subtrees.pop_front() {
73 let mut block = block_storage
74 .fetch(&tree.root_reference)
75 .await?
76 .ok_or(Error::BlockNotFound)?;
77 block.chacha20(&tree.root_key);
78
79 if tree.level == 0 {
80 let mut block = (*block).as_slice();
81 if subtrees.len() == 0 {
82 unpad(&mut block)?;
84 }
85 target.write_all(block).await?;
86 } else {
87 for rk_pair_raw in block.chunks_exact(64) {
88 let has_content = rk_pair_raw.iter().any(|x| *x != 0);
89 if !has_content {
90 break;
91 }
92
93 let rk_pair = (
94 BlockReference(rk_pair_raw[..32].try_into().unwrap()),
95 BlockKey(rk_pair_raw[32..].try_into().unwrap()),
96 );
97 subtrees.push_back(ReadCapability::from_rk_pair(
98 rk_pair,
99 tree.level - 1,
100 read_capability.block_size,
101 ));
102 }
103 }
104 }
105
106 Ok(())
107}