diff --git a/README.md b/README.md index 76cad66..087c85c 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,27 @@ fn main() { # Changelog +## 0.16.2 + +Fixes multiple problems. The most impactful being that 0.16.1 could only be built +using a nightly rust compiler. + +It also provides an optional feature to integrate 'savefile-derive' into 'savefile'. + +Just activate the feature 'derive', and you can then use savefile without an explicit +dependency on 'savefile-derive'. Just do + +```rust +use savefile::prelude::*; + +#[derive(Savefile)] +struct MyStruct { + //... +} +``` +And you're good to go! + + ## 0.16.1 Fix a minor issue where the ```#[savefile_introspect_ignore]``` was not accepted diff --git a/savefile-derive/Cargo.toml b/savefile-derive/Cargo.toml index 460265a..1abbb09 100644 --- a/savefile-derive/Cargo.toml +++ b/savefile-derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "savefile-derive" -version = "0.16.1" +version = "0.16.2" authors = ["Anders Musikka "] description = "Custom derive macros for savefile crate - simple, convenient, fast, versioned, binary serialization/deserialization library." diff --git a/savefile-derive/src/lib.rs b/savefile-derive/src/lib.rs index 20239e8..7ef6862 100644 --- a/savefile-derive/src/lib.rs +++ b/savefile-derive/src/lib.rs @@ -1314,7 +1314,7 @@ fn get_enum_size(attrs: &Vec) -> Option { )] pub fn reprc(_input: proc_macro::TokenStream) -> proc_macro::TokenStream { - panic!("The #[derive(ReprC)] style of unsafe performance opt-in has been changed. Add a #[savefile_unsafe_and_fast] attribute on a new line, after the #[derive(Savefile)] attribute instead.") + panic!("The #[derive(ReprC)] style of unsafe performance opt-in has been removed. The performance gains are now available automatically for any packed struct.") } fn derive_reprc_new(input: DeriveInput) -> TokenStream { diff --git a/savefile-min-build/Cargo.toml b/savefile-min-build/Cargo.toml index 7dc9122..b06a5c6 100644 --- a/savefile-min-build/Cargo.toml +++ b/savefile-min-build/Cargo.toml @@ -6,7 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -savefile = { path = "../savefile", features = [], default-features = false } -savefile-derive = { path = "../savefile-derive" } +savefile = { path = "../savefile", features = ["derive"], default-features = false } diff --git a/savefile-min-build/src/lib.rs b/savefile-min-build/src/lib.rs index 7253a8b..37f14ed 100644 --- a/savefile-min-build/src/lib.rs +++ b/savefile-min-build/src/lib.rs @@ -1,7 +1,9 @@ +use savefile::prelude::*; use std::fmt::Debug; use std::io::{BufWriter, Cursor, Write}; use savefile::{Deserialize, Deserializer, Serialize, Serializer}; + pub fn assert_roundtrip(sample: E) { assert_roundtrip_version(sample, 0) } @@ -24,8 +26,14 @@ pub fn assert_roundtrip_version( assert_eq!(f.position() as usize,f_internal_size); } +#[derive(Savefile,PartialEq,Eq,Debug)] +struct SimpleStruct { + x: u32 +} + #[test] fn it_works() { assert_roundtrip("Test-string".to_string()); assert_roundtrip(42i32); + assert_roundtrip(SimpleStruct{x:42}); } diff --git a/savefile-test/src/lib.rs b/savefile-test/src/lib.rs index eefe5a0..a3230ca 100644 --- a/savefile-test/src/lib.rs +++ b/savefile-test/src/lib.rs @@ -426,6 +426,32 @@ pub fn test_array_string() { assert_roundtrip(arraystr); } +#[test] +pub fn test_array_vec() { + use arrayvec::ArrayVec; + let mut data:ArrayVec = ArrayVec::new(); + assert_roundtrip(data.clone()); + data.push(47); + assert_roundtrip(data.clone()); + data.push(1); + data.push(32); + data.push(49); + assert_roundtrip(data.clone()); +} + +#[test] +pub fn test_array_vec_with_string() { + use arrayvec::ArrayVec; + let mut data:ArrayVec = ArrayVec::new(); + assert_roundtrip(data.clone()); + data.push("hello".to_string()); + assert_roundtrip(data.clone()); + data.push("wonderful".to_string()); + data.push("world".to_string()); + data.push("how ya doing?".to_string()); + assert_roundtrip(data.clone()); +} + #[test] pub fn test_smallvec0() { let mut v = smallvec::SmallVec::<[u8;2]>::new(); @@ -1142,13 +1168,13 @@ struct MySimpleFuzz1 { #[test] pub fn fuzz_regression1() { let mut data:&[u8] = &[0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 8, 3, 0, 3, 0, 64, 0, 0, 0]; - let _ = load_noschema::(&mut data,0); + let _t:Result = load_noschema(&mut data,0); } #[test] pub fn fuzz_regression2() { let mut data:&[u8] = &[0, 0, 0, 0, 3, 11, 0, 254, 2, 1, 252, 255, 254]; - let _ = load_noschema::(&mut data,0); + let _t:Result = load_noschema(&mut data,0); } diff --git a/savefile/Cargo.toml b/savefile/Cargo.toml index 74838e7..95a64d6 100644 --- a/savefile/Cargo.toml +++ b/savefile/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "savefile" -version = "0.16.1" +version = "0.16.2" authors = ["Anders Musikka "] documentation = "https://docs.rs/savefile/" homepage = "https://github.com/avl/savefile/" @@ -37,6 +37,8 @@ compression = ["bzip2"] encryption = ["ring", "rand"] +derive = ["dep:savefile-derive"] + [dependencies] bit-vec = { version = "0.6", optional = true} arrayvec = { version = "0.7", optional = true} @@ -49,9 +51,8 @@ bzip2 = {version = "0.4.4", optional = true} bit-set = {version = "0.5", optional = true} rustc-hash = {version = "1.1", optional = true} memoffset = "0.9" - byteorder = "1.4" - +savefile-derive = {path="../savefile-derive",version = "=0.16.2", optional = true } [dev-dependencies] savefile-derive = { path="../savefile-derive" } diff --git a/savefile/src/lib.rs b/savefile/src/lib.rs index 165cea7..7d11865 100644 --- a/savefile/src/lib.rs +++ b/savefile/src/lib.rs @@ -785,6 +785,8 @@ extern crate core; extern crate memoffset; +#[cfg(feature="derive")] +extern crate savefile_derive; /// This object represents an error in deserializing or serializing /// an item. @@ -1526,17 +1528,17 @@ impl<'a, W:Write+'a> Serializer<'a, W> { pub unsafe fn raw_write_region(&mut self, full: &T, t1: &T1, t2: &T2, version: u32) -> Result<(), SavefileError> { assert!(T1::repr_c_optimization_safe(version).is_yes()); assert!(T2::repr_c_optimization_safe(version).is_yes()); - unsafe { - let base = full as *const T as *const u8; - let totlen = std::mem::size_of::(); - let p1 = (t1 as *const T1 as *const u8) as usize; - let p2 = (t2 as *const T2 as *const u8) as usize; - let start = p1 - (base as usize); - let end = (p2 - (base as usize)) + std::mem::size_of::(); - let full_slice = std::slice::from_raw_parts(base, totlen); - Ok(self.writer.write_all(&full_slice[start..end])?) - } + + let base = full as *const T as *const u8; + let totlen = std::mem::size_of::(); + let p1 = (t1 as *const T1 as *const u8) as usize; + let p2 = (t2 as *const T2 as *const u8) as usize; + let start = p1 - (base as usize); + let end = (p2 - (base as usize)) + std::mem::size_of::(); + let full_slice = std::slice::from_raw_parts(base, totlen); + Ok(self.writer.write_all(&full_slice[start..end])?) + } /// Creata a new serializer. /// Don't use this function directly, use the [crate::save] function instead. @@ -3774,7 +3776,7 @@ impl Serialize for bit_vec::BitVec { serializer.write_usize(l)?; let storage = self.storage(); let rawbytes_ptr = storage.as_ptr() as *const u8; - let rawbytes :&[u8] = unsafe{slice::from_raw_parts(rawbytes_ptr,4*storage.len())}; + let rawbytes :&[u8] = unsafe{std::slice::from_raw_parts(rawbytes_ptr,4*storage.len())}; serializer.write_usize(rawbytes.len()|(1<<63))?; serializer.write_bytes(&rawbytes)?; Ok(()) @@ -3799,7 +3801,7 @@ impl Deserialize for bit_vec::BitVec { let storage = ret.storage_mut(); storage.resize(num_words, 0); let storage_ptr = storage.as_ptr() as *mut u8; - let storage_bytes:&mut [u8] = slice::from_raw_parts_mut(storage_ptr,4*num_words); + let storage_bytes:&mut [u8] = std::slice::from_raw_parts_mut(storage_ptr,4*num_words); deserializer.read_bytes_to_buf(storage_bytes)?; ret.set_len(numbits); } @@ -4160,7 +4162,7 @@ fn regular_deserialize_vec(deserializer: &mut Deserializer Deserialize for Vec { fn deserialize(deserializer: &mut Deserializer) -> Result { if unsafe{T::repr_c_optimization_safe(deserializer.file_version)}.is_false() { - Ok(regular_deserialize_vec::(deserializer)?) + Ok(regular_deserialize_vec(deserializer)?) } else { use std::mem; @@ -4228,13 +4230,13 @@ impl WithSchema for VecDeque { impl ReprC for VecDeque {} impl Serialize for VecDeque { fn serialize(&self, serializer: &mut Serializer) -> Result<(), SavefileError> { - regular_serialize_vecdeque::(self, serializer) + regular_serialize_vecdeque(self, serializer) } } impl Deserialize for VecDeque { fn deserialize(deserializer: &mut Deserializer) -> Result { - Ok(regular_deserialize_vecdeque::(deserializer)?) + Ok(regular_deserialize_vecdeque(deserializer)?) } } @@ -4628,26 +4630,16 @@ impl Introspect for arrayvec::ArrayVec< } } -#[cfg(all(feature = "nightly", feature="arrayvec"))] -impl ReprC for arrayvec::ArrayVec {} - - -#[cfg(all(feature = "nightly", feature="arrayvec"))] -impl Serialize for arrayvec::ArrayVec { - default fn serialize(&self, serializer: &mut Serializer) -> Result<(), SavefileError> { - regular_serialize_vec(self, serializer) +#[cfg(feature="arrayvec")] +impl ReprC for arrayvec::ArrayVec { + unsafe fn repr_c_optimization_safe(version: u32) -> IsReprC { + V::repr_c_optimization_safe(version) } } -#[cfg(all(not(feature = "nightly"), feature="arrayvec"))] -impl Serialize for arrayvec::ArrayVec { - fn serialize(&self, serializer: &mut Serializer) -> Result<(), SavefileError> { - regular_serialize_vec(self, serializer) - } -} -#[cfg(all(feature = "nightly", feature="arrayvec"))] -impl Serialize for arrayvec::ArrayVec { +#[cfg(feature="arrayvec")] +impl Serialize for arrayvec::ArrayVec { fn serialize(&self, serializer: &mut Serializer) -> Result<(), SavefileError> { unsafe { if V::repr_c_optimization_safe(serializer.version).is_false() { @@ -4663,31 +4655,8 @@ impl Serialize for arrayvec::ArrayVe } } } -#[cfg(all(feature = "nightly", feature="arrayvec"))] -impl Deserialize for arrayvec::ArrayVec { - default fn deserialize(deserializer: &mut Deserializer) -> Result, SavefileError> { - let mut ret = arrayvec::ArrayVec::new(); - let l = deserializer.read_usize()?; - for _ in 0..l { - ret.push(V::deserialize(deserializer)?); - } - Ok(ret) - } -} -#[cfg(all(not(feature = "nightly"), feature="arrayvec"))] -impl Deserialize for arrayvec::ArrayVec { - fn deserialize(deserializer: &mut Deserializer) -> Result, SavefileError> { - let mut ret = arrayvec::ArrayVec::new(); - let l = deserializer.read_usize()?; - for _ in 0..l { - ret.push(V::deserialize(deserializer)?); - } - Ok(ret) - } -} - -#[cfg(all(feature = "nightly", feature="arrayvec"))] +#[cfg(feature="arrayvec")] impl Deserialize for arrayvec::ArrayVec { fn deserialize(deserializer: &mut Deserializer) -> Result, SavefileError> { let mut ret = arrayvec::ArrayVec::new(); @@ -4775,7 +4744,6 @@ use std::fmt::{Debug, Display, Formatter}; use std::marker::PhantomData; use std::path::{PathBuf, Path}; use std::ptr::NonNull; -use std::slice; use std::sync::Arc; diff --git a/savefile/src/prelude.rs b/savefile/src/prelude.rs index 628b9f0..48b0a7b 100644 --- a/savefile/src/prelude.rs +++ b/savefile/src/prelude.rs @@ -9,3 +9,12 @@ pub use memoffset::span_of; #[cfg(feature="ring")] pub use super::{CryptoReader, CryptoWriter, save_encrypted_file, load_encrypted_file}; + +#[cfg(feature="derive")] +pub use savefile_derive::Savefile; +#[cfg(feature="derive")] +pub use savefile_derive::SavefileNoIntrospect; +#[cfg(feature="derive")] +pub use savefile_derive::SavefileIntrospectOnly; +#[cfg(feature="derive")] +pub use savefile_derive::ReprC;