Skip to content

Commit

Permalink
Merge pull request #79 from sokorototo/main
Browse files Browse the repository at this point in the history
Added a new API, did some maintenance.
  • Loading branch information
sokorototo authored Sep 3, 2022
2 parents f26950d + be18502 commit 3c9d682
Show file tree
Hide file tree
Showing 22 changed files with 274 additions and 377 deletions.
246 changes: 105 additions & 141 deletions Cargo.lock

Large diffs are not rendered by default.

25 changes: 11 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,12 @@ use std::fs::File;
use vach::prelude::{Archive, Resource, Flags};

let target = File::open("sounds.vach")?;
let archive = Archive::from_handle(target)?;
let resource: Resource = archive.fetch("ambient")?;
let mut archive = Archive::new(target)?;
let resource: Resource = archive.fetch_mut("ambient")?;

// By default all resources are flagged as NOT authenticated
println!("{}", Sound::new(&resource.data)?);
assert!(!resource.authenticated);

let mut buffer = Vec::new();
let (flags, content_version, is_authenticated) = archive.fetch_write("ftstep", &mut buffer)?;
```

##### > Build a signed `.vach` file
Expand Down Expand Up @@ -148,10 +145,10 @@ let mut public_key_bytes: [u8; crate::PUBLIC_KEY_LENGTH] = include_bytes!(PUBLIC
let mut config = ArchiveConfig::default().key(PublicKey::from_bytes(&public_key_bytes)?);

let target = File::open("sounds.vach")?;
let archive = Archive::with_config(target, &config)?;
let mut archive = Archive::with_config(target, &config)?;

// Resources are marked as secure (=true) if the signatures match the data
let resource = archive.fetch("ambient")?;
let resource = archive.fetch_mut("ambient")?;
println!("{}", Sound::new(&resource.data)?);
assert!(resource.authenticated);
```
Expand All @@ -172,21 +169,21 @@ let mut builder = Builder::new();
let config = BuilderConfig::default().magic(*MAGIC);

// Add data
builder.add_leaf(Leaf::from_handle(data_1).id("d1").compress(CompressMode::Always))?;
builder.add_leaf(Leaf::from_handle(data_2).id("d2").compress(CompressMode::Never))?;
builder.add_leaf(Leaf::from_handle(data_3).id("d3").compress(CompressMode::Detect))?;
builder.add_leaf(Leaf::new(data_1).id("d1").compress(CompressMode::Always))?;
builder.add_leaf(Leaf::new(data_2).id("d2").compress(CompressMode::Never))?;
builder.add_leaf(Leaf::new(data_3).id("d3").compress(CompressMode::Detect))?;

// Dump data
builder.dump(&mut target, &config)?;

// Load data
let config = ArchiveConfig::default().magic(*MAGIC);
let archive = Archive::with_config(target, &config)?;
let mut archive = Archive::with_config(target, &config)?;

// Quick assertions
assert_eq!(archive.fetch("d1")?.data.as_slice(), data_1);
assert_eq!(archive.fetch("d2")?.data.as_slice(), data_2);
assert_eq!(archive.fetch("d3")?.data.as_slice(), data_3);
assert_eq!(archive.fetch_mut("d1")?.data.as_slice(), data_1);
assert_eq!(archive.fetch_mut("d2")?.data.as_slice(), data_2);
assert_eq!(archive.fetch_mut("d3")?.data.as_slice(), data_3);
```

> For more information on how to use the library, read the documentation. [Always read the documentation!](https://youtu.be/TUE_HSgQiG0?t=91) or read the tests, they offer great insight into how the crate works.
Expand Down
1 change: 0 additions & 1 deletion vach-benchmarks/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ publish = false
[dependencies]
criterion = "0.3.5"
vach = { path = "../vach", features = ["compression", "crypto"] }
rayon = "*"

[[bench]]
name = "benchmark"
Expand Down
40 changes: 14 additions & 26 deletions vach-benchmarks/benches/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use std::collections::HashMap;
use std::io;
use criterion::{Criterion, black_box, criterion_group, criterion_main, Throughput};

use rayon::iter::{ParallelIterator, IntoParallelRefIterator};
use criterion::{Criterion, black_box, criterion_group, criterion_main, Throughput};
use vach::prelude::*;
use vach::crypto_utils::gen_keypair;

Expand Down Expand Up @@ -57,13 +55,13 @@ pub fn criterion_benchmark(c: &mut Criterion) {

// Add data
builder
.add_leaf(Leaf::from_handle(data_1).id("d1").compress(CompressMode::Always))
.add_leaf(Leaf::new(data_1).id("d1").compress(CompressMode::Always))
.unwrap();
builder
.add_leaf(Leaf::from_handle(data_2).id("d2").compress(CompressMode::Never))
.add_leaf(Leaf::new(data_2).id("d2").compress(CompressMode::Never))
.unwrap();
builder
.add_leaf(Leaf::from_handle(data_3).id("d3").compress(CompressMode::Detect))
.add_leaf(Leaf::new(data_3).id("d3").compress(CompressMode::Detect))
.unwrap();

// Dump data
Expand All @@ -80,12 +78,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {

{
// Builds an archive source from which to benchmark
let template = Leaf::default()
.encrypt(false)
.sign(false)
.compress(CompressMode::Never)
.compression_algo(CompressionAlgorithm::LZ4);
let mut builder = Builder::new().template(template);
let mut builder = Builder::new().template(Leaf::default().encrypt(false).sign(false));

// Add data
builder.add(data_1, "d1").unwrap();
Expand All @@ -99,28 +92,23 @@ pub fn criterion_benchmark(c: &mut Criterion) {
// Load data
throughput_group.throughput(Throughput::Elements(3));

let archive = Archive::with_config(&mut target, &h_config).unwrap();
let mut sink = Sink::new();
let mut archive = Archive::with_config(&mut target, &h_config).unwrap();

throughput_group.bench_function("Archive::fetch_write(---)", |b| {
throughput_group.bench_function("Archive::fetch(---)", |b| {
// Load data
b.iter(|| {
archive.fetch_write("d1", &mut sink).unwrap();
archive.fetch_write("d2", &mut sink).unwrap();
archive.fetch_write("d3", &mut sink).unwrap();
archive.fetch("d1").unwrap();
archive.fetch("d2").unwrap();
archive.fetch("d3").unwrap();
});
});

throughput_group.bench_function("Archive::fetch_batch(---)", |b| {
throughput_group.bench_function("Archive::fetch_mut(---)", |b| {
// Load data
b.iter(|| {
let resources = ["d2", "d1", "d3"]
.as_slice()
.par_iter()
.map(|id| (id, archive.fetch(&id)))
.collect::<HashMap<_, _>>();

criterion::black_box(resources)
archive.fetch_mut("d1").unwrap();
archive.fetch_mut("d2").unwrap();
archive.fetch_mut("d3").unwrap();
});
});

Expand Down
4 changes: 2 additions & 2 deletions vach-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "vach-cli"
version = "0.4.0"
version = "0.4.1"
edition = "2021"
authors = [
"Jasper Fortuin <[email protected]>",
Expand Down Expand Up @@ -29,5 +29,5 @@ pretty_env_logger = "0.4.0"
term_size = "0.3.2"

[dependencies.vach]
version = "0.4.0"
path = "../vach"
features = ["compression", "multithreaded", "crypto"]
15 changes: 2 additions & 13 deletions vach-cli/src/commands/pack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,20 +208,9 @@ impl CommandTrait for Evaluator {
);

// Since it wraps it's internal state in an arc, we can safely clone and send across threads
let callback = |id: &str, _: &RegistryEntry| {
let callback = |leaf: &Leaf, _: &RegistryEntry| {
pbar.inc(1);

// Prevent column from wrapping around
let mut msg = id.to_string();
if let Some((terminal_width, _)) = term_size::dimensions() {
// Make sure progress bar never get's longer than terminal size
if msg.len() + 140 >= terminal_width {
msg.truncate(terminal_width - 140);
msg.push_str("...");
}
};

pbar.set_message(msg)
pbar.set_message(leaf.id.to_string())
};

// Build a builder-config using the above extracted data
Expand Down
28 changes: 10 additions & 18 deletions vach-cli/src/commands/unpack.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::fs::{self, File};
use std::str::FromStr;
use std::io::{Read, Seek};
use std::io::{Read, Seek, Write};
use std::path::PathBuf;
use std::time::Instant;

Expand Down Expand Up @@ -123,19 +123,11 @@ fn extract_archive<T: Read + Seek + Send + Sync>(archive: &Archive<T>, target_fo
let entry_vec = archive.entries().iter().map(|a| (a.0, a.1.offset)).collect::<Vec<_>>();

// ignore the unprofessional match clause
match entry_vec.as_slice().par_iter().try_for_each(|(id, offset)| {
// Prevent column from wrapping around
if let Some((terminal_width, _)) = term_size::dimensions() {
let mut msg = id.to_string();
// Make sure progress bar never get's longer than terminal size
if msg.len() + 140 >= terminal_width {
msg.truncate(terminal_width - 140);
msg.push_str("...");
}

// Set's the Progress Bar message
pbar.set_message(msg.to_string());
};
if let Err(err) = entry_vec.as_slice().par_iter().try_for_each(|(id, offset)| {
let msg = id.to_string();

// Set's the Progress Bar message
pbar.set_message(msg);

// Process filesystem
let mut save_path = target_folder.clone();
Expand All @@ -147,18 +139,18 @@ fn extract_archive<T: Read + Seek + Send + Sync>(archive: &Archive<T>, target_fo

// Write to file and update process queue
let mut file = File::create(save_path)?;
archive.fetch_write(id, &mut file)?;
let resource = archive.fetch(id)?;
file.write_all(&resource.data)?;

// Increment Progress Bar
pbar.inc(*offset);
Ok(())
}) {
Ok(it) => it,
Err(err) => return Err(err),
return Err(err);
};

// Finished extracting
pbar.finish_and_clear();
pbar.finish();
log::info!(
"Extracted {} files in {}s",
archive.entries().len(),
Expand Down
13 changes: 13 additions & 0 deletions vach-mimetype.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
<mime-type type="application/vach">
<acronym>VACH</acronym>
<expanded-acronym>Virtual No-So-Virtual Archive</expanded-acronym>
<comment>A simple read-only archive format implented in Rust</comment>
<icon name="application-x-archive"/>
<glob pattern="*.vach"/>
<magic priority="100">
<match type="string" value="VfACH" offset="0"/>
</magic>
</mime-type>
</mime-info>
10 changes: 5 additions & 5 deletions vach/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "vach"

# NOTE: Make sure spec.txt and vach::VERSION constants are all synced up
version = "0.4.0"
version = "0.4.1"

edition = "2021"
authors = [
Expand Down Expand Up @@ -31,21 +31,21 @@ aes-gcm = { version = "0.9.4", features = ["aes"], optional = true }
# Compression dependencies
lz4_flex = { version = "0.9.2", optional = true, default-features = false, features = [
"checked-decode",
"frame"
"frame",
] }
snap = { version = "1.0.5", optional = true }
brotli = { version = "3.3.4", optional = true }

# Multithreaded features
parking_lot = { version = "0.12.1", optional = true }
parking_lot = { version = "0.12.1" }
rayon = { version = "1.5.2", optional = true }
num_cpus = { version = "1.13.1", optional = true }

[features]
default = ["builder", "archive"]

archive = ["parking_lot"]
builder = ["parking_lot"]
archive = []
builder = []

crypto = ["ed25519-dalek", "aes-gcm", "rand"]
multithreaded = ["rayon", "num_cpus"]
Expand Down
12 changes: 4 additions & 8 deletions vach/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
<h1 align=center>
<strong>vach</strong>
</h1>
<p align=center> A simple archiving format, designed for storing assets in compact secure containers </p>

<p align=center>
<img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/zeskeertwee/vach?logo=rust&logoColor=orange&style=flat-square">
<a href="https://docs.rs/vach"><img alt="docs.rs" src="https://img.shields.io/docsrs/vach?style=flat-square"></a>
<a href="https://crates.io/crates/vach"><img alt="Crate Version on Crates.io" src="https://img.shields.io/crates/v/vach?style=flat-square"></a>
<br/>
Expand Down Expand Up @@ -35,8 +31,8 @@ use vach::prelude::{Archive, Resource, Flags};

let source = File::open("sounds.vach")?;

let archive = Archive::from_handle(source)?;
let resource: Resource = archive.fetch("footstep.wav")?;
let mut archive = Archive::new(source)?;
let resource: Resource = archive.fetch_mut("footstep.wav")?;

// By default all resources are flagged as NOT secure
assert!(!resource.authenticated);
Expand All @@ -47,7 +43,7 @@ println!("{}", Sound::new(resource.data.as_slice())?);

// Read data directly into an `io::Write` stream
let mut buffer = Vec::new();
let (flags, content_version, is_secure) = archive.fetch_write("ftstep", &mut buffer)?;
let (flags, content_version, is_secure) = archive.fetch_mut("ftstep", &mut buffer)?;
```

> For more information on how to use the crate, read the [documentation](https://docs.rs/vach) or pass by the [repository](https://github.com/zeskeertwee/vach). Maybe also check out the [CLI](https://crates.io/crates/vach-cli), for a more user-friendly use of `vach`
4 changes: 2 additions & 2 deletions vach/src/global/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ impl Header {
/// Validates a `Header` with a template [ArchiveConfig]
/// ### Errors
/// - (in)validation of magic and archive version
pub fn validate(config: &ArchiveConfig, header: &Header) -> InternalResult {
pub(crate) fn validate(config: &ArchiveConfig, header: &Header) -> InternalResult {
// Validate magic
if header.magic != config.magic {
return Err(InternalError::MalformedArchiveSource(header.magic));
Expand All @@ -163,7 +163,7 @@ impl Header {

/// ### Errors
/// - `io` errors
pub fn from_handle<T: Read>(mut handle: T) -> InternalResult<Header> {
pub(crate) fn from_handle<T: Read>(mut handle: T) -> InternalResult<Header> {
#![allow(clippy::uninit_assumed_init)]
let mut buffer: [u8; Header::BASE_SIZE] = [0u8; Header::BASE_SIZE];

Expand Down
4 changes: 1 addition & 3 deletions vach/src/global/reg_entry.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use crate::global::flags::Flags;

use std::{io::Read, fmt};
use super::result::InternalResult;
use super::{result::InternalResult, flags::Flags};

#[cfg(feature = "crypto")]
use crate::crypto;
Expand Down
Loading

0 comments on commit 3c9d682

Please sign in to comment.