datasus_dbc/
decompress.rs1use super::error::{Error, Result};
2use explode::ExplodeReader;
3use std::fs::File;
4use std::fs::OpenOptions;
5use std::io;
6use std::io::Chain;
7use std::io::Cursor;
8use std::io::Read;
9use std::path::Path;
10
11type DbfReader<R> = Chain<Chain<Cursor<[u8; 10]>, Cursor<Vec<u8>>>, ExplodeReader<R>>;
12
13pub fn decompress<P>(dbc_path: P, dbf_path: P) -> Result<()>
15where
16 P: AsRef<Path>,
17{
18 let dbc_file = File::open(dbc_path)?;
19 let mut dbf_reader = into_dbf_reader(dbc_file)?;
20 let mut dbf_file = OpenOptions::new().write(true).create(true).open(dbf_path)?;
21 io::copy(&mut dbf_reader, &mut dbf_file)?;
22
23 Ok(())
24}
25
26pub fn into_dbf_reader<R>(mut dbc_reader: R) -> Result<DbfReader<R>>
28where
29 R: io::Read,
30{
31 let mut pre_header: [u8; 10] = Default::default();
32 let mut crc32: [u8; 4] = Default::default();
33 dbc_reader
34 .read_exact(&mut pre_header)
35 .map_err(|_| Error::MissingHeader)?;
36
37 let header_size: usize = usize::from(pre_header[8]) + (usize::from(pre_header[9]) << 8);
38
39 let mut header: Vec<u8> = vec![0; header_size - 10];
40 dbc_reader
41 .read_exact(&mut header)
42 .map_err(|_| Error::InvalidHeaderSize)?;
43 dbc_reader
44 .read_exact(&mut crc32)
45 .map_err(|_| Error::InvalidHeaderSize)?;
46
47 let pre_header_reader = Cursor::new(pre_header);
49 let header_reader = Cursor::new(header);
50 let compressed_content_reader = ExplodeReader::new(dbc_reader);
51
52 let dbf_reader = pre_header_reader
53 .chain(header_reader)
54 .chain(compressed_content_reader);
55
56 Ok(dbf_reader)
57}
58
59#[cfg(test)]
60mod tests {
61 use std::fs;
62
63 use super::*;
64
65 #[test]
66 fn test_decompress() -> Result<()> {
67 let input = r"test\data\sids.dbc";
68 let output = r"test\data\sids.dbf";
69 let expected = r"test\data\expected-sids.dbf";
70
71 decompress(input, output)?;
72
73 let output_file = fs::read(output)?;
74 let expected_file = fs::read(expected)?;
75 fs::remove_file(output)?;
76
77 assert_eq!(
78 output_file, expected_file,
79 "Decompressed .dbf is not equal to expected result"
80 );
81
82 Ok(())
83 }
84}