-
Notifications
You must be signed in to change notification settings - Fork 144
Expand file tree
/
Copy pathheader.rs
More file actions
95 lines (77 loc) · 2.56 KB
/
Copy pathheader.rs
File metadata and controls
95 lines (77 loc) · 2.56 KB
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
use std::{
fs::File,
io::{Cursor, Read, Seek, SeekFrom, Write},
};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use libcraft::REGION_SIZE;
use crate::SECTOR_OFFSET;
pub const HEADER_SIZE: usize = 12 * 1024;
const NUM_CHUNKS: usize = REGION_SIZE * REGION_SIZE;
#[derive(Debug, Clone)]
pub struct Header {
chunks: Vec<Entry>,
}
impl Default for Header {
fn default() -> Self {
Self {
chunks: vec![Entry::default(); NUM_CHUNKS],
}
}
}
impl Header {
pub fn read_from(file: &mut File) -> anyhow::Result<Self> {
file.seek(SeekFrom::Start(0))?;
let mut buf = [0u8; HEADER_SIZE];
file.read_exact(&mut buf)?;
let mut cursor = Cursor::new(&buf[..]);
let mut chunks = Vec::with_capacity(NUM_CHUNKS);
for _ in 0..NUM_CHUNKS {
chunks.push(Entry {
offset_in_sectors: cursor.read_u32::<BigEndian>()?,
size_in_bytes: cursor.read_u32::<BigEndian>()?,
uncompressed_size_in_bytes: cursor.read_u32::<BigEndian>()?,
});
}
Ok(Self { chunks })
}
pub fn write_to(&self, file: &mut File) -> anyhow::Result<()> {
let mut buf = [0u8; HEADER_SIZE];
let mut cursor = Cursor::new(&mut buf[..]);
for entry in &self.chunks {
cursor.write_u32::<BigEndian>(entry.offset_in_sectors)?;
cursor.write_u32::<BigEndian>(entry.size_in_bytes)?;
cursor.write_u32::<BigEndian>(entry.uncompressed_size_in_bytes)?;
}
file.seek(SeekFrom::Start(0))?;
file.write_all(&buf)?;
Ok(())
}
/// Note that the chunk coordinates are relative to the region
/// (i.e., modulo 32)
pub fn get(&self, chunk_x: u32, chunk_z: u32) -> Entry {
self.chunks[self.index(chunk_x, chunk_z)]
}
pub fn set(&mut self, chunk_x: u32, chunk_z: u32, entry: Entry) {
let index = self.index(chunk_x, chunk_z);
self.chunks[index] = entry;
}
pub fn iter(&self) -> impl Iterator<Item = Entry> + '_ {
self.chunks.iter().copied()
}
fn index(&self, chunk_x: u32, chunk_z: u32) -> usize {
assert!(chunk_x < REGION_SIZE as u32);
assert!(chunk_z < REGION_SIZE as u32);
(chunk_x as usize * REGION_SIZE) + chunk_z as usize
}
}
#[derive(Copy, Clone, Debug, Default)]
pub struct Entry {
pub offset_in_sectors: u32,
pub size_in_bytes: u32,
pub uncompressed_size_in_bytes: u32,
}
impl Entry {
pub fn exists(&self) -> bool {
self.offset_in_sectors >= SECTOR_OFFSET
}
}