diff --git a/Cargo.toml b/Cargo.toml index fdc5998..e2f9fd1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,6 +74,8 @@ serde_json = { version = "1.0.96", optional = true } simd-json = { version = "0.9.2", optional = true } simd-json-derive = { version = "0.9.2", optional = true } speedy = { version = "0.8.6", optional = true } +savefile = { version = "0.14", optional = true } +savefile-derive = { version = "0.14", optional = true } zstd = "0.12.3" [features] @@ -107,9 +109,12 @@ default = [ "serde_json", "simd-json", "speedy", + "savefile" ] simd-json = ["dep:simd-json", "simd-json-derive"] +savefile = ["dep:savefile", "savefile-derive"] + scale = ["parity-scale-codec", "parity-scale-codec-derive"] [dev-dependencies] diff --git a/benches/bench.rs b/benches/bench.rs index 5035fc6..14be5d7 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -36,6 +36,8 @@ use rust_serialization_benchmark::bench_rkyv; use rust_serialization_benchmark::bench_rmp_serde; #[cfg(feature = "ron")] use rust_serialization_benchmark::bench_ron; +#[cfg(feature = "savefile")] +use rust_serialization_benchmark::bench_savefile; #[cfg(feature = "serde_bare")] use rust_serialization_benchmark::bench_serde_bare; #[cfg(feature = "serde_cbor")] @@ -192,6 +194,9 @@ fn bench_log(c: &mut Criterion) { #[cfg(feature = "ron")] bench_ron::bench(BENCH, c, &data); + #[cfg(feature = "savefile")] + bench_savefile::bench(BENCH, c, &data); + #[cfg(feature = "serde_bare")] bench_serde_bare::bench(BENCH, c, &data); @@ -333,6 +338,9 @@ fn bench_mesh(c: &mut Criterion) { #[cfg(feature = "ron")] bench_ron::bench(BENCH, c, &data); + #[cfg(feature = "savefile")] + bench_savefile::bench(BENCH, c, &data); + #[cfg(feature = "serde_bare")] bench_serde_bare::bench(BENCH, c, &data); @@ -477,6 +485,9 @@ fn bench_minecraft_savedata(c: &mut Criterion) { #[cfg(feature = "ron")] bench_ron::bench(BENCH, c, &data); + #[cfg(feature = "savefile")] + bench_savefile::bench(BENCH, c, &data); + #[cfg(feature = "serde_bare")] bench_serde_bare::bench(BENCH, c, &data); @@ -617,6 +628,9 @@ fn bench_mk48(c: &mut Criterion) { #[cfg(feature = "ron")] bench_ron::bench(BENCH, c, &data); + #[cfg(feature = "savefile")] + bench_savefile::bench(BENCH, c, &data); + #[cfg(feature = "serde_bare")] bench_serde_bare::bench(BENCH, c, &data); diff --git a/src/bench_savefile.rs b/src/bench_savefile.rs new file mode 100644 index 0000000..86e7381 --- /dev/null +++ b/src/bench_savefile.rs @@ -0,0 +1,33 @@ +use criterion::{black_box, Criterion}; +use savefile::{Deserialize, Serialize, WithSchema}; +use std::io::Cursor; + +pub fn bench(name: &'static str, c: &mut Criterion, data: &T) +where + T: Serialize + Deserialize + WithSchema, +{ + let mut group = c.benchmark_group(format!("{}/savefile", name)); + + let mut serialize_buffer = Vec::new(); + group.bench_function("serialize", |b| { + b.iter(|| { + serialize_buffer.clear(); + savefile::save_noschema(black_box(&mut serialize_buffer), 0, black_box(data)).unwrap(); + black_box(()); + }) + }); + + let mut deserialize_buffer = Vec::new(); + savefile::save_noschema(&mut deserialize_buffer, 0, data).unwrap(); + + group.bench_function("deserialize", |b| { + b.iter(|| { + let mut reader = Cursor::new(&deserialize_buffer); + black_box(savefile::load_noschema::(black_box(&mut reader), 0).unwrap()); + }) + }); + + crate::bench_size(name, "savefile", deserialize_buffer.as_slice()); + + group.finish(); +} diff --git a/src/datasets/log/mod.rs b/src/datasets/log/mod.rs index 9928384..c79b4c0 100644 --- a/src/datasets/log/mod.rs +++ b/src/datasets/log/mod.rs @@ -42,6 +42,7 @@ use crate::Generate; derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) )] #[cfg_attr(feature = "rkyv", archive_attr(derive(bytecheck::CheckBytes)))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr( feature = "simd-json", @@ -145,6 +146,7 @@ impl alkahest::Pack
for Address { derive(parity_scale_codec_derive::Encode, parity_scale_codec_derive::Decode) )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct Log { pub address: Address, pub identity: String, @@ -349,6 +351,7 @@ impl alkahest::Pack for &'_ Log { derive(parity_scale_codec_derive::Encode, parity_scale_codec_derive::Decode) )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct Logs { pub logs: Vec, } diff --git a/src/datasets/mesh/mod.rs b/src/datasets/mesh/mod.rs index 6c105c5..b637ec1 100644 --- a/src/datasets/mesh/mod.rs +++ b/src/datasets/mesh/mod.rs @@ -52,6 +52,7 @@ use crate::Generate; )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] #[cfg_attr(feature = "alkahest", derive(alkahest::Schema))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct Vector3 { pub x: f32, pub y: f32, @@ -140,6 +141,7 @@ impl alkahest::Pack for Vector3 { )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] #[cfg_attr(feature = "alkahest", derive(alkahest::Schema))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct Triangle { pub v0: Vector3, pub v1: Vector3, @@ -238,6 +240,7 @@ impl alkahest::Pack for &'_ Triangle { derive(simd_json_derive::Serialize, simd_json_derive::Deserialize) )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct Mesh { pub triangles: Vec, } diff --git a/src/datasets/minecraft_savedata/mod.rs b/src/datasets/minecraft_savedata/mod.rs index 4344e56..8fcf77b 100644 --- a/src/datasets/minecraft_savedata/mod.rs +++ b/src/datasets/minecraft_savedata/mod.rs @@ -53,7 +53,7 @@ use crate::{generate_vec, Generate}; )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] #[cfg_attr(feature = "alkahest", derive(alkahest::Schema))] -#[repr(u8)] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub enum GameType { Survival, Creative, @@ -148,6 +148,7 @@ impl alkahest::Pack for GameType { derive(simd_json_derive::Serialize, simd_json_derive::Deserialize) )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct Item { pub count: i8, pub slot: u8, @@ -265,6 +266,7 @@ impl alkahest::Pack for &'_ Item { )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] #[cfg_attr(feature = "alkahest", derive(alkahest::Schema))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct Abilities { #[cfg_attr(feature = "bitcode", bitcode_hint(expected_range = "0.0..1.0"))] pub walk_speed: f32, @@ -382,6 +384,7 @@ impl alkahest::Pack for Abilities { derive(simd_json_derive::Serialize, simd_json_derive::Deserialize) )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct Entity { pub id: String, #[cfg_attr(feature = "bitcode", bitcode_hint(expected_range = "0.0..1.0"))] @@ -642,6 +645,7 @@ impl alkahest::Pack for &'_ Entity { derive(simd_json_derive::Serialize, simd_json_derive::Deserialize) )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct RecipeBook { pub recipes: Vec, pub to_be_displayed: Vec, @@ -842,6 +846,7 @@ impl alkahest::Pack for &'_ RecipeBook { derive(simd_json_derive::Serialize, simd_json_derive::Deserialize) )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct Player { pub game_type: GameType, pub previous_game_type: GameType, @@ -1287,6 +1292,7 @@ impl alkahest::Pack for &'_ Player { derive(simd_json_derive::Serialize, simd_json_derive::Deserialize) )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct Players { pub players: Vec, } diff --git a/src/datasets/mk48/mod.rs b/src/datasets/mk48/mod.rs index c8097fe..75be3da 100644 --- a/src/datasets/mk48/mod.rs +++ b/src/datasets/mk48/mod.rs @@ -55,7 +55,7 @@ use crate::{generate_vec, Generate}; )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] #[cfg_attr(feature = "alkahest", derive(alkahest::Schema))] -#[repr(u8)] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub enum EntityType { #[cfg_attr(feature = "bitcode", bitcode_hint(frequency = 2.14))] ArleighBurke, @@ -283,6 +283,7 @@ fn generate_velocity(rng: &mut impl Rng) -> i16 { )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] #[cfg_attr(feature = "alkahest", derive(alkahest::Schema))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct Transform { #[cfg_attr(feature = "bitcode", bitcode_hint(expected_range = "0..1"))] pub altitude: i8, @@ -389,6 +390,7 @@ impl alkahest::Pack for Transform { )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] #[cfg_attr(feature = "alkahest", derive(alkahest::Schema))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct Guidance { pub angle: u16, pub submerge: bool, @@ -476,6 +478,7 @@ impl alkahest::Pack for Guidance { derive(simd_json_derive::Serialize, simd_json_derive::Deserialize) )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct Contact { #[cfg_attr(feature = "bitcode", bitcode_hint(expected_range = "0..1"))] pub damage: u8, @@ -678,6 +681,7 @@ impl alkahest::Pack for &'_ Contact { derive(simd_json_derive::Serialize, simd_json_derive::Deserialize) )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct TerrainUpdate { #[cfg_attr(feature = "bitcode", bitcode_hint(gamma))] chunk_id: (i8, i8), @@ -798,6 +802,7 @@ impl alkahest::Pack for &'_ TerrainUpdate { derive(simd_json_derive::Serialize, simd_json_derive::Deserialize) )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct Update { pub contacts: Vec, #[cfg_attr(feature = "bitcode", bitcode_hint(expected_range = "0..5000"))] @@ -951,6 +956,7 @@ impl alkahest::Pack for &'_ Update { derive(simd_json_derive::Serialize, simd_json_derive::Deserialize) )] #[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))] +#[cfg_attr(feature = "savefile", derive(savefile_derive::Savefile))] pub struct Updates { pub updates: Vec, } diff --git a/src/lib.rs b/src/lib.rs index 3f0e11f..4efa1a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,8 @@ pub mod bench_rkyv; pub mod bench_rmp_serde; #[cfg(feature = "ron")] pub mod bench_ron; +#[cfg(feature = "savefile")] +pub mod bench_savefile; #[cfg(feature = "serde_bare")] pub mod bench_serde_bare; #[cfg(feature = "serde_cbor")]