Skip to content

Commit 3f5907f

Browse files
committed
fix build
1 parent 1e83c0c commit 3f5907f

File tree

3 files changed

+88
-45
lines changed

3 files changed

+88
-45
lines changed

src/archive.rs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
use std::cmp::Ordering;
55
use std::collections::HashMap;
66
use std::fs::File;
7-
use std::io::{self, Read, Result, Write};
7+
use std::io::{self, Read, Result, Seek, Write};
88
use std::mem;
9-
use std::path::{Path, PathBuf};
9+
use std::path::Path;
1010

1111
use crate::fnv1a64_hash_string;
1212
use crate::io::*;
@@ -15,23 +15,22 @@ use crate::kraken::*;
1515
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
1616

1717
#[derive(Debug, Clone, Default)]
18-
pub(crate) struct Archive {
19-
pub(crate) header: Header,
20-
pub(crate) index: Index,
18+
pub struct Archive {
19+
pub header: Header,
20+
pub index: Index,
2121

2222
// custom
23-
pub(crate) file_names: HashMap<u64, String>,
23+
pub file_names: HashMap<u64, String>,
2424
}
2525

2626
impl Archive {
2727
// Function to read a Header from a file
28-
pub fn from_file<P>(file_path: &P) -> Result<Archive>
28+
pub fn from_file<P>(file_path: P) -> Result<Archive>
2929
where
3030
P: AsRef<Path>,
3131
{
3232
let mut file = File::open(file_path)?;
3333
let mut buffer = Vec::with_capacity(mem::size_of::<Header>());
34-
3534
file.read_to_end(&mut buffer)?;
3635

3736
// Ensure that the buffer has enough bytes to represent a Header
@@ -43,14 +42,22 @@ impl Archive {
4342
}
4443

4544
let mut cursor = io::Cursor::new(&buffer);
46-
let header = Header::from_reader(&mut cursor)?;
45+
46+
Archive::from_reader(&mut cursor)
47+
}
48+
49+
pub fn from_reader<R>(cursor: &mut R) -> Result<Archive>
50+
where
51+
R: Read + Seek,
52+
{
53+
let header = Header::from_reader(cursor)?;
4754

4855
// read custom data
4956
let mut file_names: HashMap<u64, String> = HashMap::default();
5057
if let Ok(custom_data_length) = cursor.read_u32::<LittleEndian>() {
5158
if custom_data_length > 0 {
52-
cursor.set_position(Header::HEADER_EXTENDED_SIZE);
53-
if let Ok(footer) = LxrsFooter::from_reader(&mut cursor) {
59+
cursor.seek(io::SeekFrom::Start(Header::HEADER_EXTENDED_SIZE))?;
60+
if let Ok(footer) = LxrsFooter::from_reader(cursor) {
5461
// add files to hashmap
5562
for f in footer.files {
5663
let hash = fnv1a64_hash_string(&f);
@@ -61,8 +68,8 @@ impl Archive {
6168
}
6269

6370
// move to offset Header.IndexPosition
64-
cursor.set_position(header.index_position);
65-
let index = Index::from_reader(&mut cursor)?;
71+
cursor.seek(io::SeekFrom::Start(header.index_position))?;
72+
let index = Index::from_reader(cursor)?;
6673

6774
Ok(Archive {
6875
header,
@@ -72,7 +79,7 @@ impl Archive {
7279
}
7380

7481
// get filehashes
75-
pub(crate) fn get_file_hashes(&self) -> Vec<u64> {
82+
pub fn get_file_hashes(&self) -> Vec<u64> {
7683
self.index
7784
.file_entries
7885
.iter()
@@ -82,7 +89,7 @@ impl Archive {
8289
}
8390

8491
#[derive(Debug, Clone, Copy)]
85-
pub(crate) struct Header {
92+
pub struct Header {
8693
pub magic: u32,
8794
pub version: u32,
8895
pub index_position: u64,
@@ -376,21 +383,21 @@ mod integration_tests {
376383
#[test]
377384
fn read_archive() {
378385
let archive_path = PathBuf::from("tests").join("test1.archive");
379-
let result = Archive::from_file(&archive_path);
386+
let result = Archive::from_file(archive_path);
380387
assert!(result.is_ok());
381388
}
382389

383390
#[test]
384391
fn read_archive2() {
385392
let archive_path = PathBuf::from("tests").join("nci.archive");
386-
let result = Archive::from_file(&archive_path);
393+
let result = Archive::from_file(archive_path);
387394
assert!(result.is_ok());
388395
}
389396

390397
#[test]
391398
fn read_custom_data() {
392399
let archive_path = PathBuf::from("tests").join("test1.archive");
393-
let archive = Archive::from_file(&archive_path).expect("Could not parse archive");
400+
let archive = Archive::from_file(archive_path).expect("Could not parse archive");
394401
let mut file_names = archive
395402
.file_names
396403
.values()

src/archive_file.rs

Lines changed: 60 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::{
1515
collections::{HashMap, HashSet},
1616
fs::{create_dir_all, File},
1717
io::{self, BufWriter, Read, Result, Seek, SeekFrom, Write},
18-
path::{Path, PathBuf},
18+
path::Path,
1919
};
2020

2121
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
@@ -32,7 +32,7 @@ use crate::{
3232

3333
// public static void CreateFromDirectory (string sourceDirectoryName, System.IO.Stream destination);
3434

35-
/// Creates a zip archive in the specified stream that contains the files and directories from the specified directory.
35+
/// Creates an archive in the specified stream that contains the files and directories from the specified directory.
3636
///
3737
/// # Errors
3838
///
@@ -57,7 +57,7 @@ where
5757

5858
// public static void CreateFromDirectory (string sourceDirectoryName, string destinationArchiveFileName);
5959

60-
/// Creates a zip archive that contains the files and directories from the specified directory.
60+
/// Creates an archive that contains the files and directories from the specified directory.
6161
///
6262
/// # Errors
6363
///
@@ -82,20 +82,28 @@ where
8282

8383
// public static void ExtractToDirectory (System.IO.Stream source, string destinationDirectoryName, bool overwriteFiles);
8484

85-
/// Extracts all the files from the zip archive stored in the specified stream and places them in the specified destination directory on the file system, and optionally allows choosing if the files in the destination directory should be overwritten.
85+
/// Extracts all the files from the archive stored in the specified stream and places them in the specified destination directory on the file system, and optionally allows choosing if the files in the destination directory should be overwritten.
8686
///
8787
/// # Errors
8888
///
8989
/// This function will return an error if any io fails.
9090
pub fn extract_to_directory<R, P>(
91-
source: R,
92-
destination_directory_name: P,
91+
source: &mut R,
92+
destination_directory_name: &P,
9393
overwrite_files: bool,
94+
hash_map: Option<HashMap<u64, String>>,
9495
) -> io::Result<()>
9596
where
9697
P: AsRef<Path>,
97-
R: Read,
98+
R: Read + Seek,
9899
{
100+
let map = if let Some(hash_map) = hash_map {
101+
hash_map
102+
} else {
103+
get_red4_hashes()
104+
};
105+
106+
extract_archive(source, destination_directory_name, overwrite_files, &map)
99107
}
100108

101109
// public static void ExtractToDirectory (string sourceArchiveFileName, string destinationDirectoryName, bool overwriteFiles);
@@ -106,17 +114,28 @@ where
106114
///
107115
/// This function will return an error if any io fails.
108116
pub fn extract_to_directory_path<P>(
109-
source_archive_file_name: P,
110-
destination_directory_name: P,
117+
source_archive_file_name: &P,
118+
destination_directory_name: &P,
111119
overwrite_files: bool,
120+
hash_map: Option<HashMap<u64, String>>,
112121
) -> io::Result<()>
113122
where
114123
P: AsRef<Path>,
115124
{
125+
let map = if let Some(hash_map) = hash_map {
126+
hash_map
127+
} else {
128+
get_red4_hashes()
129+
};
130+
131+
let archive_file = File::open(source_archive_file_name)?;
132+
let mut archive_reader = io::BufReader::new(archive_file);
133+
116134
extract_archive(
117-
source_archive_file_name,
135+
&mut archive_reader,
118136
destination_directory_name,
119137
overwrite_files,
138+
&map,
120139
)
121140
}
122141

@@ -126,9 +145,14 @@ pub enum ArchiveMode {
126145
Update,
127146
}
128147

148+
/*
149+
TODO We don't support different modes for now
150+
needs a wrapper class for archives
151+
152+
129153
// public static System.IO.Compression.ZipArchive Open (string archiveFileName, System.IO.Compression.ZipArchiveMode mode);
130154
131-
/// Opens a zip archive at the specified path and in the specified mode.
155+
/// Opens an archive at the specified path and in the specified mode.
132156
///
133157
/// # Errors
134158
///
@@ -140,9 +164,11 @@ where
140164
todo!()
141165
}
142166
167+
*/
168+
143169
// public static System.IO.Compression.ZipArchive OpenRead (string archiveFileName);
144170

145-
/// Opens a zip archive for reading at the specified path.
171+
/// Opens an archive for reading at the specified path.
146172
///
147173
/// # Errors
148174
///
@@ -151,7 +177,7 @@ pub fn open_read<P>(archive_file_name: P) -> io::Result<Archive>
151177
where
152178
P: AsRef<Path>,
153179
{
154-
todo!()
180+
Archive::from_file(archive_file_name)
155181
}
156182

157183
/////////////////////////////////////////////////////////////////////////////////////////
@@ -167,15 +193,18 @@ where
167193
/// # Errors
168194
///
169195
/// This function will return an error if any parsing fails
170-
fn extract_archive<P>(in_file: &P, out_dir: &P, hash_map: &HashMap<u64, String>) -> io::Result<()>
196+
fn extract_archive<P, R>(
197+
archive_reader: &mut R,
198+
out_dir: &P,
199+
overwrite_files: bool,
200+
hash_map: &HashMap<u64, String>,
201+
) -> io::Result<()>
171202
where
172203
P: AsRef<Path>,
204+
R: Read + Seek,
173205
{
174206
// parse archive headers
175-
let archive = Archive::from_file(in_file)?;
176-
177-
let archive_file = File::open(in_file)?;
178-
let mut archive_reader = io::BufReader::new(archive_file);
207+
let archive = Archive::from_reader(archive_reader)?;
179208

180209
for (hash, file_entry) in archive.index.file_entries.iter() {
181210
// get filename
@@ -188,12 +217,21 @@ where
188217
}
189218

190219
// name or hash is a relative path
191-
let mut: PathBuf
192-
let outfile = out_dir.join(name_or_hash);
220+
let outfile = out_dir.as_ref().join(name_or_hash);
193221
create_dir_all(outfile.parent().expect("Could not create an out_dir"))?;
194222

195223
// extract to stream
196-
let mut fs = File::create(outfile)?;
224+
let mut fs = if overwrite_files {
225+
File::create(outfile)?
226+
} else {
227+
File::options()
228+
.read(true)
229+
.write(true)
230+
.create_new(true)
231+
.open(outfile)?
232+
};
233+
234+
//let mut fs = File::create(outfile)?;
197235
let mut file_writer = BufWriter::new(&mut fs);
198236
// decompress main file
199237
let start_index = file_entry.segments_start;
@@ -209,7 +247,7 @@ where
209247
archive_reader.read_exact(&mut buffer[..])?;
210248
file_writer.write_all(&buffer)?;
211249
} else {
212-
decompress_segment(&mut archive_reader, segment, &mut file_writer)?;
250+
decompress_segment(archive_reader, segment, &mut file_writer)?;
213251
}
214252
}
215253

tests/functional_tests.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
#[cfg(test)]
66
mod tests {
77
use std::fs::create_dir_all;
8+
use std::path::Path;
89
//use std::path::Path;
910
use std::time::Instant;
1011
use std::{fs, path::PathBuf};
1112

13+
use red4lib::archive_file::extract_to_directory_path;
1214
use red4lib::*;
1315

1416
#[test]
@@ -21,7 +23,6 @@ mod tests {
2123
println!("Execution time csv: {:?}", duration);
2224
}
2325

24-
/*
2526
#[test]
2627
fn test_extract_archive() {
2728
let archive_path = PathBuf::from("tests").join("test1.archive");
@@ -34,7 +35,7 @@ mod tests {
3435
assert!(fs::remove_dir_all(&dst_path).is_ok());
3536
}
3637

37-
let result = extract_archive(&archive_path, &dst_path, &hashes);
38+
let result = extract_to_directory_path(&archive_path, &dst_path, true, Some(hashes));
3839
assert!(result.is_ok());
3940

4041
// check
@@ -94,7 +95,6 @@ mod tests {
9495
assert!(fs::remove_dir_all(&dst_path).is_ok());
9596
}
9697
}
97-
*/
9898

9999
#[test]
100100
fn test_pack_archive() {
@@ -129,7 +129,6 @@ mod tests {
129129
// HELPERS
130130
/////////////////////////////////////////////////////////////////////////////////////////
131131

132-
/*
133132
fn assert_binary_equality(e: &PathBuf, f: &PathBuf) {
134133
// compare bytes
135134
let mut fe = fs::File::open(e).expect("Could not open file");
@@ -171,5 +170,4 @@ mod tests {
171170
// Return an empty vector if there's an error
172171
Vec::new()
173172
}
174-
*/
175173
}

0 commit comments

Comments
 (0)