1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use std::io;
extern crate byteorder;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
extern crate itertools;
use itertools::Itertools;
pub const SECTOR_LENGTH : usize = 2048;
pub struct ChunkList {
pub chunks: Vec<Chunk>,
}
pub struct Chunk {
pub start: u32,
pub length: u32,
}
impl Chunk {
pub fn parse(mut data : &[u8]) -> io::Result<Chunk> {
return Ok(Chunk {
start: data.read_u32::<BigEndian>()?,
length: data.read_u32::<BigEndian>()?,
});
}
pub fn serialize(&self) -> io::Result<Vec<u8>> {
let mut writer = vec![];
writer.write_u32::<BigEndian>(self.start)?;
writer.write_u32::<BigEndian>(self.length)?;
return Ok(writer);
}
}
fn fold_vecs<T>(mut a : Vec<T>, b : Vec<T>) -> Vec<T> {
a.extend(b);
return a;
}
impl ChunkList {
pub fn build(files : &[usize]) -> ChunkList {
let mut index = SECTOR_LENGTH;
let mut chunks = vec![];
for file_length in files {
chunks.push(Chunk {
start: index as u32,
length: *file_length as u32,
});
index += *file_length;
index += SECTOR_LENGTH - (*file_length % SECTOR_LENGTH);
}
return ChunkList {
chunks: chunks,
};
}
pub fn parse(data : &[u8]) -> io::Result<ChunkList> {
let chunks : Vec<Chunk> = data
.chunks(8)
.filter(|chunk| chunk[0] != 255)
.map(|chunk| Chunk::parse(chunk))
.collect::<io::Result<Vec<Chunk>>>()?;
return Ok(ChunkList {
chunks: chunks,
});
}
pub fn serialize(&self) -> io::Result<Vec<u8>> {
let mut serialized = self
.chunks
.iter()
.map(|chunk| chunk.serialize())
.fold_results(vec![], fold_vecs)?;
serialized.resize(SECTOR_LENGTH, 255);
return Ok(serialized);
}
}
impl IntoIterator for ChunkList {
type Item = Chunk;
type IntoIter = ::std::vec::IntoIter<Chunk>;
fn into_iter(self) -> Self::IntoIter {
return self.chunks.into_iter();
}
}