1use super::shared::{Block, StaticLocation, read_block, read_block_statics};
15use crate::error::MulReaderResult;
16use crate::mul::MulReader;
17use byteorder::{LittleEndian, ReadBytesExt};
18use std::collections::HashMap;
19use std::fs::File;
20use std::io::{Read, Seek};
21use std::path::Path;
22
23fn generate_lookup_table<T: Read + Seek>(
24 data: &mut T,
25 length: u32,
26) -> MulReaderResult<HashMap<u32, u32>> {
27 let mut lookup_table = HashMap::new();
28
29 for i in 0..(length / 4) {
30 lookup_table.insert(data.read_u32::<LittleEndian>()?, i);
31 }
32
33 Ok(lookup_table)
34}
35
36#[derive(Debug)]
38pub struct MapDiffReader<T: Read + Seek> {
39 lookup_table: HashMap<u32, u32>,
40 diff: T,
41}
42
43impl MapDiffReader<File> {
44 pub fn new(lookup_path: &Path, diff_path: &Path) -> MulReaderResult<MapDiffReader<File>> {
46 let mut lookup = File::open(lookup_path)?;
48 let diff = File::open(diff_path)?;
49
50 let meta = lookup.metadata()?;
51 let lookup_table = generate_lookup_table(&mut lookup, meta.len() as u32)?;
52
53 Ok(MapDiffReader { lookup_table, diff })
54 }
55}
56
57impl<T: Read + Seek> MapDiffReader<T> {
58 pub fn from_readable<U: Read + Seek>(
60 mut lookup_reader: U,
61 data_reader: T,
62 lookup_file_length: u32,
63 ) -> MulReaderResult<MapDiffReader<T>> {
64 let lookup_table = generate_lookup_table(&mut lookup_reader, lookup_file_length)?;
65
66 Ok(MapDiffReader {
67 lookup_table,
68 diff: data_reader,
69 })
70 }
71
72 pub fn read(&mut self, idx: u32) -> Option<MulReaderResult<Block>> {
74 match self.lookup_table.get(&idx) {
75 Some(block_idx) => Some(read_block(&mut self.diff, *block_idx)),
76 None => None,
77 }
78 }
79
80 pub fn read_all(&mut self) -> HashMap<u32, MulReaderResult<Block>> {
82 let mut out = HashMap::new();
83 let keys = self.lookup_table.keys().copied().collect::<Vec<u32>>();
84 for map_idx in keys {
85 out.insert(
86 map_idx,
87 self.read(map_idx)
88 .expect("Tried to read cached lookup that no longer exists"),
89 );
90 }
91 out
92 }
93}
94
95#[derive(Debug)]
97pub struct StaticLocationDiffReader<T: Read + Seek> {
98 mul_reader: MulReader<T>,
99 lookup_table: HashMap<u32, u32>,
100}
101
102impl StaticLocationDiffReader<File> {
103 pub fn new(
105 lookup_path: &Path,
106 diff_idx_path: &Path,
107 diff_path: &Path,
108 ) -> MulReaderResult<StaticLocationDiffReader<File>> {
109 let mut lookup = File::open(lookup_path)?;
110
111 let meta = lookup.metadata()?;
112 let lookup_table = generate_lookup_table(&mut lookup, meta.len() as u32)?;
113 let mul_reader = MulReader::new(diff_idx_path, diff_path)?;
114
115 Ok(StaticLocationDiffReader {
116 mul_reader,
117 lookup_table,
118 })
119 }
120}
121
122impl<T: Read + Seek> StaticLocationDiffReader<T> {
123 pub fn from_mul_reader<U: Read + Seek>(
125 mut lookup_reader: U,
126 mul_reader: MulReader<T>,
127 lookup_file_length: u32,
128 ) -> MulReaderResult<StaticLocationDiffReader<T>> {
129 let lookup_table = generate_lookup_table(&mut lookup_reader, lookup_file_length)?;
130
131 Ok(StaticLocationDiffReader {
132 mul_reader,
133 lookup_table,
134 })
135 }
136
137 pub fn read(&mut self, idx: u32) -> Option<MulReaderResult<Vec<StaticLocation>>> {
139 match self.lookup_table.get(&idx) {
140 Some(block_idx) => Some(read_block_statics(&mut self.mul_reader, *block_idx)),
141 None => None,
142 }
143 }
144
145 pub fn read_all(&mut self) -> HashMap<u32, MulReaderResult<Vec<StaticLocation>>> {
147 let mut out = HashMap::new();
148 let keys = self.lookup_table.keys().copied().collect::<Vec<u32>>();
149 for map_idx in keys {
150 out.insert(
151 map_idx,
152 self.read(map_idx)
153 .expect("Tried to read cached lookup that no longer exists"),
154 );
155 }
156 out
157 }
158}