Skip to content

Commit

Permalink
Release 0.17 (#50)
Browse files Browse the repository at this point in the history
Release 0.17
  • Loading branch information
avl authored May 1, 2024
1 parent c79c08a commit 21b9b64
Show file tree
Hide file tree
Showing 19 changed files with 418 additions and 267 deletions.
34 changes: 31 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 30 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
![build](https://github.com/avl/savefile/actions/workflows/rust.yml/badge.svg)

**Having trouble with new version 0.17? - See upgrade guide further down in this document!**

# Introduction to Savefile

Savefile is a crate to effortlessly serialize rust structs and enums. It uses
Expand Down Expand Up @@ -74,7 +76,7 @@ fn main() {
# Changelog


## 0.17.0 (to be released, betas available)
## 0.17.0

This is a big change! With 0.17 Savefile gains yet another major function: Support for
making dynamically loaded plugins. I.e, a mechanism to allow rust code to be divided
Expand All @@ -84,16 +86,24 @@ across library boundaries.
Using this feature requires using the crate 'savefile-abi'. Regular use of savefile
can continue as usual.

The dataformat for schemas has changed, but in a backward compatible way.

Version 0.17.0-beta.11 is, as can be seen from the name, a beta. There will be bugs.
The data format for schemas has changed, but in a backward compatible way. I.e, savefile
0.17 can still read data saved by 0.16 and earlier. However, 0.16 can't read data
saved by 0.17.

Another thing in 0.17.0: We're starting to use 'release-plz' to manage releases.
Hopefully this will make the releases more professional, with correct git tags, git releases etc.

Also, 0.17 can now sometimes dramtically optimize reading sequences of enums. This will work
for enums that have #[repr(u8)] or similar, provided the type contains no padding.

Yet another upgrade is that Savefile now supports enums with more than 256 variants!

### Upgrade guide from 0.16 -> 0.17

Unfortunately 0.17 is quite a big release. Some changes will be required to upgrade.

Here is a short guide:

1: Schemas have been expanded.

1.1: Schema::Vector takes a 2nd parameter. Just set it to 'VecOrStringLayout::Unknown' or `VecOrStringLayout::default()`.
Expand All @@ -111,7 +121,11 @@ enums. If you ever need an enum to have more than 65536 fields, set it to 4.
most data types. Only smart pointers, containers, Box etc need ot use this, to guard against
recursion. See documentation of WithSchemaContext.

1.6: Several savefile trait implementations have now gained 'static-bounds. For example,
1.6: The 'ReprC'-trait has been renamed to 'Packed'. It is identical in every other way.
Upgrading is as simple as a search-and-replace.


1.7: Several savefile trait implementations have now gained 'static-bounds. For example,
Box<T>, Vec<T> and many more now require T:'static. There was no such bound before, but
since references cannot be deserialized, it was still typically not possible to deserialize
anything containing a reference.
Expand All @@ -126,19 +140,6 @@ is the contents of containers such as Box, Vec etc. The reason is that the new r
support needs to be able to create TypeIds, and this is only possible for objects with
'static lifetime.

## 0.17.0-beta.13

Major improvements. Better diagnostics. Support for returning Box<Fn(..)>.

## 0.17.0-beta.10

Tentative support for fast serialization/deserialization of enums. May be buggy!

## 0.17.0-beta.9

Fixed bug where schema of slices was not serialized correctly. Introduced in 0.17, so
only present in beta releases.


## 0.16.5

Expand Down Expand Up @@ -237,7 +238,7 @@ Note! It might in some situations be necessary to use `#[repr(C)]` to get the sp
The 0.14 release contained some bugs. It was actually impossible to serialize
collections containing many standard types. This is fixed in 0.14.3.

## 0.14 Major changes to ReprC-system
## 0.14 Major changes to Packed (previously 'ReprC')-system

One of the strong points of Savefile is the support for very quickly serializing
and deserializing vectors of simple copy-datatypes.
Expand Down Expand Up @@ -265,7 +266,7 @@ pub struct Example {
}
```

The old solution implemented a marker trait 'ReprC' for the type. Then, Savefile relied on
The old solution implemented a marker trait 'Packed' for the type. Then, Savefile relied on
specialization to be able to serialize vectors and arrays of these types much faster
by simply copying large regions of bytes.

Expand All @@ -275,15 +276,16 @@ land in stable rust.

Because of this, we are now bringing the speedups to stable, by abandoning specialization!

We are now implementing ReprC for _all_ types, and then just returning false for types
which don't support the optimization.
We are now implementing 'Packed' (previously known as 'ReprC') for _all_ types, and then
just returning false for types which don't support the optimization.

This has some drawbacks. Previously, ReprC was an unsafe trait. It wasn't mandatory, but
if you knew what you were doing you could get extra performance, under responsibility.
This has some drawbacks. Previously, ReprC (early name of 'Packed') was an unsafe trait.
It wasn't mandatory, but if you knew what you were doing you could get extra performance,
under responsibility.

But now, ReprC is to be implemented by all types. And we don't want it to be necessary to use
But now, Packed is to be implemented by all types. And we don't want it to be necessary to use
unsafe code to be able to use Savefile. However, to the user of Savefile, there isn't much
difference, except the ReprC trait always being derived, and another way being used to opt-in
difference, except the Packed trait always being derived, and another way being used to opt-in
to the unsafe but performant optimization.

I don't know of a way to require 'unsafe' keyword to a derive macro, so we use a deliberately
Expand Down Expand Up @@ -518,6 +520,8 @@ Savefile is now usable with a stable compiler, not just nightly.

When run on stable, the following features stop working:

NOTE! The below is old information, no longer at all valid from 0.16 and onward.

* The whole 'ReprC' subsystem. This means serialization of byte arrays
(or other small copy-types) is not as fast as it could be. The slow-down
can be several orders of magnitude.
Expand Down
6 changes: 3 additions & 3 deletions compile_tests/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions savefile-abi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "savefile-abi"
version = "0.17.0-beta.15"
version = "0.17.0"
edition = "2021"
authors = ["Anders Musikka <[email protected]>"]
documentation = "https://docs.rs/savefile-abi/"
Expand All @@ -16,7 +16,7 @@ keywords = ["dylib", "dlopen", "ffi"]
license = "MIT/Apache-2.0"

[dependencies]
savefile = { path="../savefile", version = "=0.17.0-beta.15" }
savefile-derive = { path="../savefile-derive", version = "=0.17.0-beta.15" }
savefile = { path="../savefile", version = "=0.17.0" }
savefile-derive = { path="../savefile-derive", version = "=0.17.0" }
byteorder = "1.4"
libloading = "0.8"
2 changes: 1 addition & 1 deletion savefile-derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "savefile-derive"
version = "0.17.0-beta.15"
version = "0.17.0"
authors = ["Anders Musikka <[email protected]>"]

description = "Custom derive macros for savefile crate - simple, convenient, fast, versioned, binary serialization/deserialization library."
Expand Down
2 changes: 1 addition & 1 deletion savefile-derive/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ pub(crate) fn compile_time_size(typ: &Type) -> Option<(usize /*size*/, usize /*a
if let Some(itemsize_align) = itemsize_align {
if itemsize_align != (cursize, curalign) {
// All items not the same size and have same alignment. Otherwise: Might be padding issues.
return None; //It could conceivably still be reprC, safe, but we're conservative here.
return None; //It could conceivably still be packed, but we're conservative here.
}
} else {
itemsize_align = Some((cursize, curalign));
Expand Down
2 changes: 1 addition & 1 deletion savefile-derive/src/deserialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ pub fn savefile_derive_crate_deserialize(input: DeriveInput) -> TokenStream {
let extra_where = get_extra_where_clauses(
&generics,
where_clause,
quote! {_savefile::prelude::Deserialize + _savefile::prelude::ReprC},
quote! {_savefile::prelude::Deserialize + _savefile::prelude::Packed},
);

let deserialize = quote_spanned! {defspan=>
Expand Down
32 changes: 16 additions & 16 deletions savefile-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#![allow(clippy::collapsible_match)]
#![allow(clippy::single_match)]

//! This crate allows automatic derivation of the Savefile-traits: Serialize, Deserialize, WithSchema, ReprC and Introspect .
//! This crate allows automatic derivation of the Savefile-traits: Serialize, Deserialize, WithSchema, Packed and Introspect .
//! The documentation for this is found in the Savefile crate documentation.
extern crate proc_macro;
Expand Down Expand Up @@ -52,7 +52,7 @@ fn implement_fields_serialize(
let local_serializer = quote_spanned! { defspan => local_serializer};

let reprc = quote! {
_savefile::prelude::ReprC
_savefile::prelude::Packed
};

let mut deferred_reprc: Option<(usize /*align*/, Vec<TokenStream>)> = None;
Expand Down Expand Up @@ -256,7 +256,7 @@ pub fn savefile_abi_exportable(
let uses = quote_spanned! { defspan =>
extern crate savefile;
extern crate savefile_abi;
use savefile::prelude::{ReprC, Schema, SchemaPrimitive, WithSchema, WithSchemaContext, get_schema, Serializer, Serialize, Deserializer, Deserialize, SavefileError, deserialize_slice_as_vec, ReadBytesExt,LittleEndian,AbiMethodArgument, AbiMethod, AbiMethodInfo,AbiTraitDefinition};
use savefile::prelude::{Packed, Schema, SchemaPrimitive, WithSchema, WithSchemaContext, get_schema, Serializer, Serialize, Deserializer, Deserialize, SavefileError, deserialize_slice_as_vec, ReadBytesExt,LittleEndian,AbiMethodArgument, AbiMethod, AbiMethodInfo,AbiTraitDefinition};
use savefile_abi::{parse_return_value_impl,abi_result_receiver,abi_boxed_trait_receiver, FlexBuffer, AbiExportable, TraitObject, PackagedTraitObject, Owning, AbiErrorMsg, RawAbiCallResult, AbiConnection, AbiConnectionMethod, AbiProtocol, abi_entry_light};
use std::collections::HashMap;
use std::mem::MaybeUninit;
Expand Down Expand Up @@ -646,7 +646,7 @@ pub fn savefile(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
const #dummy_const: () = {
extern crate savefile as _savefile;
use std::mem::MaybeUninit;
use savefile::prelude::ReprC;
use savefile::prelude::Packed;

#w
#r
Expand Down Expand Up @@ -695,7 +695,7 @@ pub fn savefile_no_introspect(input: proc_macro::TokenStream) -> proc_macro::Tok
const #dummy_const: () = {
extern crate savefile as _savefile;
use std::mem::MaybeUninit;
use savefile::prelude::ReprC;
use savefile::prelude::Packed;

#w
#r
Expand Down Expand Up @@ -736,10 +736,10 @@ fn implement_reprc_hardcoded_false(name: syn::Ident, generics: syn::Generics) ->
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let extra_where = get_extra_where_clauses(&generics, where_clause, quote! {_savefile::prelude::WithSchema});
let reprc = quote_spanned! {defspan=>
_savefile::prelude::ReprC
_savefile::prelude::Packed
};
let isreprc = quote_spanned! {defspan=>
_savefile::prelude::IsReprC
_savefile::prelude::IsPacked
};
quote! {

Expand All @@ -762,15 +762,15 @@ fn implement_reprc_struct(
expect_fast: bool,
) -> TokenStream {
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let extra_where = get_extra_where_clauses(&generics, where_clause, quote! {_savefile::prelude::ReprC});
let extra_where = get_extra_where_clauses(&generics, where_clause, quote! {_savefile::prelude::Packed});

let span = proc_macro2::Span::call_site();
let defspan = proc_macro2::Span::call_site();
let reprc = quote_spanned! {defspan=>
_savefile::prelude::ReprC
_savefile::prelude::Packed
};
let isreprc = quote_spanned! {defspan=>
_savefile::prelude::IsReprC
_savefile::prelude::IsPacked
};
let offsetof = quote_spanned! {defspan=>
_savefile::prelude::offset_of
Expand Down Expand Up @@ -980,7 +980,7 @@ fn get_enum_size(attrs: &[syn::Attribute], actual_variants: usize) -> EnumSize {
}
#[proc_macro_error]
#[proc_macro_derive(
ReprC,
Packed,
attributes(
savefile_versions,
savefile_versions_as,
Expand All @@ -990,7 +990,7 @@ fn get_enum_size(attrs: &[syn::Attribute], actual_variants: usize) -> EnumSize {
)
)]
pub fn reprc(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
abort_call_site!("The #[derive(ReprC)] style of unsafe performance opt-in has been removed. The performance gains are now available automatically for any packed struct.")
abort_call_site!("The #[derive(Packed)] 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 {
let name = input.ident;
Expand Down Expand Up @@ -1110,12 +1110,12 @@ fn derive_reprc_new(input: DeriveInput) -> TokenStream {
let defspan = proc_macro2::Span::call_site();
let generics = input.generics;
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let extra_where = get_extra_where_clauses(&generics, where_clause, quote! {_savefile::prelude::ReprC});
let extra_where = get_extra_where_clauses(&generics, where_clause, quote! {_savefile::prelude::Packed});
let reprc = quote_spanned! { defspan=>
_savefile::prelude::ReprC
_savefile::prelude::Packed
};
let isreprc = quote_spanned! {defspan=>
_savefile::prelude::IsReprC
_savefile::prelude::IsPacked
};

if conditions.is_empty() {
Expand All @@ -1135,7 +1135,7 @@ fn derive_reprc_new(input: DeriveInput) -> TokenStream {
let mut reprc_condition = vec![];
for typ in unique_field_types {
reprc_condition.push(quote!(
<#typ as ReprC>::repr_c_optimization_safe(file_version).is_yes()
<#typ as Packed>::repr_c_optimization_safe(file_version).is_yes()
));
}

Expand Down
Loading

0 comments on commit 21b9b64

Please sign in to comment.