1use nom::{bytes::complete::tag, multi::many1, sequence::tuple, IResult};
2
3use crate::chunk::{read_chunk, Chunk};
4
5#[derive(Debug)]
9pub struct ChunksDiskFormat {
10 version: u8,
11 chunks: Vec<Chunk>,
12 file_index: Option<u64>,
13 addr: Option<*const u8>,
14}
15
16impl ChunksDiskFormat {
17 pub fn new(chunks: Vec<Chunk>, file_index: Option<u64>) -> Self {
22 Self {
23 version: 1,
24 chunks,
25 file_index,
26 addr: None,
27 }
28 }
29
30 pub fn version(&self) -> u8 {
32 self.version
33 }
34
35 pub fn chunks(&self) -> &[Chunk] {
37 &self.chunks
38 }
39
40 fn set_addr(&mut self, addr: *const u8) {
41 self.addr = Some(addr);
42 }
43
44 fn set_file_index(&mut self, file_index: u64) {
45 self.file_index = Some(file_index);
46 }
47
48 fn compute_chunk_refs(&mut self) {
49 let chunks_addr = match self.addr {
50 Some(addr) => addr,
51 None => return,
52 };
53 let file_index = match self.file_index {
54 Some(file_index) => file_index,
55 None => return,
56 };
57 for chunk in self.chunks.iter_mut() {
58 chunk.compute_chunk_ref(file_index, chunks_addr);
59 }
60 }
61}
62
63impl PartialEq for ChunksDiskFormat {
64 fn eq(&self, other: &Self) -> bool {
65 self.version == other.version
66 && self.chunks == other.chunks
67 && self.file_index == other.file_index
68 }
69}
70
71fn read_chunks_disk_format(input: &[u8]) -> IResult<&[u8], ChunksDiskFormat> {
72 let (remaining_input, (_, mut chunks_disk_format)) = tuple((
73 tag([0x85, 0xBD, 0x40, 0xDD]),
75 read_version_one,
76 ))(input)?;
77
78 chunks_disk_format.set_addr(input.as_ptr());
79
80 Ok((remaining_input, chunks_disk_format))
81}
82
83fn read_version_one(input: &[u8]) -> IResult<&[u8], ChunksDiskFormat> {
84 let (remaining_input, (_, _, chunks)) = tuple((
85 tag([1u8]),
87 tag([0u8; 3]),
89 many1(read_chunk),
91 ))(input)?;
92
93 Ok((
94 remaining_input,
95 ChunksDiskFormat {
96 version: 1,
97 chunks,
98 file_index: None,
99 addr: None,
100 },
101 ))
102}
103
104pub fn read_chunks(input: &[u8], file_index: Option<u64>) -> IResult<&[u8], ChunksDiskFormat> {
111 let (remaining_input, mut chunks_disk_format) = read_chunks_disk_format(input)?;
112 if let Some(file_index) = file_index {
113 chunks_disk_format.set_file_index(file_index);
114 }
115 chunks_disk_format.compute_chunk_refs();
116 Ok((remaining_input, chunks_disk_format))
117}