1use crate::{compression::decompress, errors::BrFsError};
2
3#[derive(Clone, Debug)]
4pub struct BrBlob {
5 pub blob_id: i64,
6 pub compression: i64,
7 pub size_uncompressed: i64,
8 pub size_compressed: i64,
9 pub delta_base_id: Option<i64>, pub hash: Vec<u8>,
11 pub content: Vec<u8>,
12}
13
14impl BrBlob {
15 pub fn hash(content: &[u8]) -> [u8; 32] {
17 *blake3::hash(content).as_bytes()
18 }
19
20 pub fn read(self) -> Result<Vec<u8>, BrFsError> {
22 let content = if self.compression == 0 {
23 self.content
24 } else {
25 if self.content.len() != self.size_compressed as usize {
27 return Err(BrFsError::InvalidSize {
28 name: "compressed content".to_string(),
29 found: self.content.len(),
30 expected: self.size_compressed as usize,
31 });
32 }
33
34 decompress(&self.content, self.size_uncompressed as usize)
36 .map_err(BrFsError::Decompress)?
37 };
38
39 if content.len() != self.size_uncompressed as usize {
41 return Err(BrFsError::InvalidSize {
42 name: "uncompressed content".to_string(),
43 found: content.len(),
44 expected: self.size_uncompressed as usize,
45 });
46 }
47
48 let hash = Self::hash(&content);
49
50 if hash != self.hash.as_slice() {
52 return Err(BrFsError::InvalidHash {
53 found: hash.to_vec(),
54 expected: self.hash,
55 });
56 }
57
58 Ok(content)
59 }
60}
61
62#[derive(Default, Clone, Debug)]
63pub struct BrRevision {
64 pub revision_id: i64,
65 pub description: String,
66 pub created_at: i64,
67}
68
69#[derive(Default, Clone, Debug)]
70pub struct BrFolder {
71 pub folder_id: i64,
72 pub parent_id: Option<i64>, pub name: String,
74 pub created_at: i64,
75 pub deleted_at: Option<i64>,
76}
77
78#[derive(Default, Clone, Debug)]
79
80pub struct BrFile {
81 pub file_id: i64,
82 pub parent_id: Option<i64>, pub name: String,
84 pub content_id: Option<i64>,
85 pub created_at: i64,
86 pub deleted_at: Option<i64>,
87}