1#![cfg_attr(docsrs, feature(doc_cfg, doc_cfg_hide))]
2#![warn(missing_docs)]
3#[cfg(not(feature = "std"))]
81compile_error!(
82 "The feature `std` is required. \
83 no_std support is blocked on Rust issue \
84 #48331 <https://github.com/rust-lang/rust/issues/48331>.\
85 "
86);
87
88mod error;
89
90mod block_hash;
91mod cdrom;
92mod chdfile;
93mod compression;
94
95#[cfg(feature = "huffman_api")]
96pub mod huffman;
97
98#[cfg(not(feature = "huffman_api"))]
99mod huffman;
100
101#[cfg(feature = "codec_api")]
102#[cfg_attr(docsrs, doc(cfg(codec_api)))]
114pub mod codecs {
115 pub use crate::compression::codecs::*;
116 pub use crate::compression::{
117 CodecImplementation, CompressionCodec, CompressionCodecType, DecompressResult,
118 };
119}
120
121const fn make_tag(a: &[u8; 4]) -> u32 {
122 ((a[0] as u32) << 24) | ((a[1] as u32) << 16) | ((a[2] as u32) << 8) | (a[3] as u32)
123}
124
125macro_rules! const_assert {
126 ($($list:ident : $ty:ty),* => $expr:expr) => {{
127 struct Assert<$(const $list: $ty,)*>;
128 impl<$(const $list: $ty,)*> Assert<$($list,)*> {
129 const OK: u8 = 0 - !($expr) as u8;
130 }
131 Assert::<$($list,)*>::OK
132 }};
133 ($expr:expr) => {
134 const OK: u8 = 0 - !($expr) as u8;
135 };
136}
137
138pub(crate) use const_assert;
139
140pub use chdfile::{Chd, Hunk};
141pub use error::{Error, Result};
142pub mod header;
143pub mod map;
144pub mod metadata;
145pub mod read;
146
147#[cfg(feature = "unstable_lending_iterators")]
148#[cfg_attr(docsrs, doc(cfg(unstable_lending_iterators)))]
149pub mod iter;
150
151#[cfg(test)]
152mod tests {
153 use crate::metadata::Metadata;
154 use crate::read::{ChdReader, HunkBufReader};
155 use crate::Chd;
156 use std::convert::TryInto;
157 use std::fs::File;
158 use std::io::{BufReader, Read, Write};
159
160 #[cfg(feature = "unstable_lending_iterators")]
161 use crate::iter::LendingIterator;
162
163 #[test]
164 fn read_metas_test() {
165 let mut f = File::open(".testimages/Test.chd").expect("");
166 let mut chd = Chd::open(&mut f, None).expect("file");
167
168 let metadatas: Vec<Metadata> = chd.metadata_refs().try_into().expect("");
169 let meta_datas: Vec<_> = metadatas
170 .into_iter()
171 .map(|s| String::from_utf8(s.value).unwrap())
172 .collect();
173 println!("{:?}", meta_datas);
174 }
175
176 #[test]
177 fn read_hunk_buffer_test() {
178 let mut f = BufReader::new(File::open(".testimages/cliffhgr.chd").expect(""));
179 let mut chd = Chd::open(&mut f, None).expect("file");
180 let hunk_count = chd.header().hunk_count();
181
182 let mut hunk_buf = Vec::new();
183 let mut cmp_buf = Vec::new();
184 for hunk_num in 0..hunk_count {
185 let mut hunk = chd.hunk(hunk_num).expect("could not acquire hunk");
186 let read = HunkBufReader::new_in(&mut hunk, &mut cmp_buf, hunk_buf)
187 .expect(format!("could not read_hunk {}", hunk_num).as_str());
188 hunk_buf = read.into_inner();
189 }
190 }
191
192 #[test]
193 fn read_hunk_test() {
194 let mut f = BufReader::new(File::open(".testimages/cliffhgr.chd").expect(""));
195 let mut chd = Chd::open(&mut f, None).expect("file");
196 let hunk_count = chd.header().hunk_count();
197
198 let mut hunk_buf = chd.get_hunksized_buffer();
199 let mut cmp_buf = Vec::new();
200 for hunk_num in 0..hunk_count {
201 let mut hunk = chd.hunk(hunk_num).expect("could not acquire hunk");
202 hunk.read_hunk_in(&mut cmp_buf, &mut hunk_buf)
203 .expect(format!("could not read_hunk {}", hunk_num).as_str());
204 println!("Read hunk {}", hunk_num);
205 }
206 }
207
208 #[test]
209 fn read_file_test() {
210 let mut f = BufReader::new(File::open(".testimages/Test.chd").expect(""));
211 let chd = Chd::open(&mut f, None).expect("file");
212 let mut read = ChdReader::new(chd);
213
214 let mut buf = Vec::new(); read.read_to_end(&mut buf).expect("can read to end");
216 let mut f_out = File::create(".testimages/out.bin").expect("");
217 f_out.write_all(&buf).expect("did not write")
218 }
219
220 #[test]
221 fn read_parent_test() {
222 let p = BufReader::new(File::open(".testimages/TombRaider.chd").expect(""));
223 let pchd = Chd::open(p, None).expect("parent");
224
225 let f = BufReader::new(File::open(".testimages/TombRaiderR1.chd").expect(""));
226
227 let _chd = Chd::open(f, Some(Box::new(pchd))).expect("child");
228 }
229
230 #[test]
231 #[cfg(feature = "unsound_owning_iterators")]
232 fn hunk_iter_test() {
233 let f_bytes = include_bytes!("../.testimages/mocapbj_a29a02.chd");
234 let mut f_cursor = Cursor::new(f_bytes);
235 let mut chd = Chd::open(&mut f_cursor, None).expect("file");
237 let mut hunk_buf = chd.get_hunksized_buffer();
238 let mut comp_buf = Vec::new();
239 for (_hunk_num, mut hunk) in chd.hunks().skip(7838).enumerate() {
240 hunk.read_hunk_in(&mut comp_buf, &mut hunk_buf)
241 .expect("hunk could not be read");
242 }
243 }
244
245 #[test]
246 #[cfg(feature = "unstable_lending_iterators")]
247 fn hunk_iter_lending_test() {
248 let mut f = BufReader::new(File::open(".testimages/cliffhgr.chd").expect(""));
249 let mut chd = Chd::open(&mut f, None).expect("file");
252 let mut hunk_buf = chd.get_hunksized_buffer();
253 let mut comp_buf = Vec::new();
254 let mut hunks = chd.hunks();
255 let mut hunk_num = 0;
256 while let Some(mut hunk) = hunks.next() {
257 hunk.read_hunk_in(&mut comp_buf, &mut hunk_buf)
258 .expect(&*format!("hunk {} could not be read", hunk_num));
259 hunk_num += 1;
260 }
261 }
262
263 #[test]
264 #[cfg(feature = "unstable_lending_iterators")]
265 fn metadata_iter_lending_test() {
266 let mut f = BufReader::new(File::open(".testimages/Test.chd").expect(""));
267 let mut chd = Chd::open(&mut f, None).expect("file");
268 let mut metas = chd.metadata();
269 while let Some(mut meta) = metas.next() {
270 let contents = meta.read().expect("metadata entry could not be read");
271 println!("{:?}", String::from_utf8(contents.value));
272 }
273 }
274
275 #[test]
276 #[cfg(feature = "unsound_owning_iterators")]
277 fn metadata_iter_test() {
278 let mut f = BufReader::new(File::open(".testimages/Test.chd").expect(""));
279 let mut chd = Chd::open(&mut f, None).expect("file");
280 for mut meta in chd.metadata().expect("metadata could not be read") {
281 let contents = meta.read().expect("metadata entry could not be read");
282 println!("{:?}", String::from_utf8(contents.value));
283 }
284 }
285}