1use nom::{bytes::complete::tag, multi::many1, IResult, Parser};
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)) = (
73 tag(&[0x85, 0xBD, 0x40, 0xDD][..]),
75 read_version_one,
76 )
77 .parse(input)?;
78
79 chunks_disk_format.set_addr(input.as_ptr());
80
81 Ok((remaining_input, chunks_disk_format))
82}
83
84fn read_version_one(input: &[u8]) -> IResult<&[u8], ChunksDiskFormat> {
85 let (remaining_input, (_, _, chunks)) = (
86 tag(&[1u8][..]),
88 tag(&[0u8; 3][..]),
90 many1(read_chunk),
92 )
93 .parse(input)?;
94
95 Ok((
96 remaining_input,
97 ChunksDiskFormat {
98 version: 1,
99 chunks,
100 file_index: None,
101 addr: None,
102 },
103 ))
104}
105
106pub fn read_chunks(input: &[u8], file_index: Option<u64>) -> IResult<&[u8], ChunksDiskFormat> {
113 let (remaining_input, mut chunks_disk_format) = read_chunks_disk_format(input)?;
114 if let Some(file_index) = file_index {
115 chunks_disk_format.set_file_index(file_index);
116 }
117 chunks_disk_format.compute_chunk_refs();
118 Ok((remaining_input, chunks_disk_format))
119}