Code Monkey home page Code Monkey logo

savefile's People

Contributors

avl avatar dimlev avatar dylan-dpc avatar ponaskovas avatar sandarukasa avatar szabgab avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

savefile's Issues

Add example of custom serialization

It would be great to have an example of a custom serialization, using WithSchema, Serialize, and Deserialize. I'd like to serialize an enum that has a PathBuf in it, but it's tricky to figure out how this is supposed to work.

ignore has become a reserved word

It seems the standard Rust test framework now uses the identifier 'ignore' as an attribute.

This means it isn't very wise of Savefile to also use this attribute-name.

All savefile attributes should probably be renamed to contain 'savefile_' as a prefix in their name.

This will be a very breaking change.

I expect to make this change for the 0.4-release.

Fix various inconsistencies in doc

For example, rules for removal of field are wrong.

Some missing words.

There's some nonidiomatic english.

Some of the user facing methods are not documented (save, load).

Some structs which should not be used by user are documented and show prominently in docs.

No hyperlinks to types from text.

Migrate away from failure

Savefile uses the 'failure' crate to do its internal error handling.

This makes the user experience suboptimal, if the user doesn't also use 'failure'.

This should be reworked, so that the Error type used by Savefile implements std::error::Error, presumably making it more compatible with any error handling crate.

Savefile-derive does not support unit structs

Savefile-derive currently fails if applied to a unit struct.

I.e, the following does not compile:

#[derive(Savefile)]
struct MyUnitStruct;

"Serializing" such a struct is of course super-simple (since it's stateless). So this should be supported. It's just a mistake.

Future incompatibility with Rust RFC 3373: Avoid non-local definitions in functions

Rust RFC 3373: Avoid non-local definitions in functions was accepted and it's implementation at rust-lang/rust#120393 found that this crate would be affected by it.

To be more precise users of this crate would be affected by it, in the form of a warn-by-default lint: non_local_definitions. This is because the derive macros from this crate use impl in a local context, const _IMPL_SAVEFILE_REPRC_FOR_???:

#[allow(non_upper_case_globals)]
const #dummy_const: () = {

Fortunately a simple fix exist for this crate, by using a const-anon instead of named one:

         #[allow(non_upper_case_globals)]
-        const #dummy_const: () = {
+        const _: () = {

Be-aware, there are many instances of this pattern in the code, don't forget to replace them all.


I would suggest applying some form of the patch above as well as releasing a patch version of this crate, as to have a fix available for users as soon as possible.

cc @avl

Deriving a struct that has a reference to another derived struct

Hello, I want to have a reference to another derived struct. For example

#[derive(Savefile)]
pub struct A {
  pub hello: String,
}

#[derive(Savefile)]
pub struct B<'a> {
  pub world: &'a A,
}

What I get is the trait `savefile::Deserialize<'_>` is not implemented for `&'a LedPattern and the same error for the rest of the required traits.

Any pointers?

More features in stable

Here are some of the features cited at the top of the main library file

#![allow(incomplete_features)]
#![cfg_attr(feature = "nightly", feature(test))]
#![cfg_attr(feature = "nightly", feature(specialization))]
#![cfg_attr(feature = "nightly", feature(integer_atomics))]
#![cfg_attr(feature = "nightly", feature(const_generics))]

However, integer_atomics have been stabilized in Rust 1.34 and from what I've seen, min_const_generics is sufficient to have Serialize impls for arrays. And it has been stabilized in Rust 1.51.
I'd also be interested to know where test feature is used in the code as I couldn't find it.

Attributes should be reworked

Savefile uses a whole lot of attributes right now, all with the prefix 'savefile_' in their names.

It would probably be better if instead the attribute was called 'savefile', and then different arguments to this single attribute were used.

This would be a breaking change without a huge tangible benefit. There are a few ways forward

  • Just do the change, increasing the semver major version.
  • Add the new attribute in parallel with the old ones, and deprecate the old ones in the next major version.

Savefile's preparation of the data to then write it into a file should be multi-threaded

I am working with really large files and multi-threading can really help me out if implemented into Savefile.
I'm not really sure just how Savefile does the preparation of the data before writing it into a file because I have not read the code, but I imagine it would be really simple using the rayon crate.

Saving the files in the computer currently takes about 5-10 minutes as they are really large, so multithreading could REALLY improve this for saving and loading these types of files multiple times. Perhaps even you could make that optional somehow, some kind of feature that contains a save_file_par(...) function that could work.

savefile-derive uses symbols from callers scope

savefile-derive should probably always derive the traits from the savefile crate, even if the caller has:

1: Not imported the symbols from the savefile crate
2: Created their own symbols with colliding names, like a Serialize trait, for instance.

I think there are probably bugs here right now.

Support `#[derive(Savefile)]` on structs with unconstrained generic parameters

The following code:

#[derive(Savefile)]
struct Foo<T> {
    pub bar: T
}

yields errors, that T doesn't implement Serialize, Deserialize, etc., but this should be possible - implementation, that works only when T fulfills the constraints should be derived.

Eg. in following code:

#[derive(Clone)]
struct Foo<T> {
    pub bar: T
}

Clone derive macro generates this implementation: impl<T: core::clone::Clone> core::clone::Clone for Foo<T> { /*... */} where T is constrained in the implementation instead of erroring out. Savefile derive macro should behave similarly.

Benefits

  • There are lots of traits, that must be implemented, so the constraints are a lot of boilerplate. The need for them would be removed
  • Possibility to use some of the Savefile-derived structs with generic arguments, that cannot be "savefiled" in cases one doesn't intend to save it to a file, while other times, one might want to use the same generic struct with "savefilable" generic arguments and save it to a file

Version 0.4.0 does not read all encrypted files correctly

There's a bug that means that if the read of the file isn't chunked exactly the same way as the write, random junk will be read.

I'm unsure what the consequences are in practice, but since I believe no one is using 0.4.0, the solution is simply to upgrade to 0.4.1.

0.4.1 has a stronger test bench, hopefully meaning there are no similar bugs in 0.4.1.

Saving external structs

Given

#[derive(Clone, Debug, Default, Savefile)]
enum ControAction {
  ..
}

#[derive(Clone, Debug, Default, Savefile)]
struct ControllerConfig {
  input_map: InputMap<ControAction>
  // input_map: Vec<KeyCode, ControlAction>
}

// Where
// KeyCode is from https://docs.rs/bevy/latest/bevy/input/keyboard/enum.KeyCode.html
// InputMap is from https://docs.rs/leafwing-input-manager/0.5.2/leafwing_input_manager/input_map/struct.InputMap.html

I couldn't find a way to save structs which invole external structs and got various erros from my attempts.

# for  input_map: InputMap<ControAction>
the trait `_IMPL_SAVEFILE_SERIALIZE_FOR_SaveData::_savefile::Serialize` is not implemented for `InputMap<ControlAction>`

# for input_map: Vec<KeyCode, ControlAction>
the trait `_IMPL_SAVEFILE_SERIALIZE_FOR_SaveData::_savefile::Serialize` is not implemented for `std::vec::Vec<(bevy::prelude::KeyCode, ControlAction)>`
the trait `WithSchema` is not implemented for `bevy::prelude::KeyCode`

Is saving external structs supported?

Unreasonable stack usage when deserializing arrays

Hello again.

I have noticed that when savefile is deserializing arrays, it uses the stack in unreasonable amounts, making it effectively impossible to use in spawned threads without setting an abnormally large stack size.

A minimal example:

#![feature(bench_black_box)]

std::thread::Builder::new()
    .stack_size(2 * 1024 * 1024)
    .spawn(|| {
        println!(
            "[u64; 16_000]: {} bytes",
            std::mem::size_of::<[u64; 16_000]>()
        );

        savefile::save_file("debug.savefile", 0, &[0u64; 16_000]).unwrap();

        println!("Saved, loading after 1 second.");
        std::thread::sleep(std::time::Duration::from_secs(1));

        let y: [u64; 16_000] = savefile::load_file("debug.savefile", 0).unwrap();

        std::hint::black_box(y);
    })
    .unwrap();

std::thread::park();

In the example, I spawn a thread with a 2 MiB stack size, which should be more than enough, considering the array we're dealing with, as it will show when running, is barely 128 000 bytes.
Serializing the array works fine, no issues, but the deserialization results in a stack overflow (at least on my machine).

Is this expected behaviour?

Does serialization of custom type need to implement "introspect"?

I am using savefile 0.8.3 on win10. With the official example, I modified a little like this:

use std::collections::VecDeque;

use savefile::prelude::*;
#[macro_use]
extern crate savefile_derive;
pub struct MyPathBuf {
    path: String,
}

use savefile::prelude::*;
impl WithSchema for MyPathBuf {
    fn schema(_version: u32) -> Schema {
        Schema::Primitive(SchemaPrimitive::schema_string)
    }
}
impl Serialize for MyPathBuf {
    fn serialize<'a>(&self, serializer: &mut Serializer<'a>) -> Result<(), SavefileError> {
        self.path.serialize(serializer)
    }
}
impl Deserialize for MyPathBuf {
    fn deserialize(deserializer: &mut Deserializer) -> Result<Self, SavefileError> {
        Ok(MyPathBuf {
            path: String::deserialize(deserializer)?,
        })
    }
}

#[derive(Savefile)]
struct Player {
    name: String,
    strength: u32,
    inventory: VecDeque<MyPathBuf>, //Vec<String>,
}

fn main() {
    let player = Player {
        name: "Steve".to_string(),
        strength: 42,
        // inventory: Vec::with_capacity(100),
        inventory: VecDeque::with_capacity(100),
    };
}

But it raised error like --- the trait bound MyPathBuf: Introspectis not satisfied required because of the requirements on the impl ofIntrospectforVecDequerequired for the cast to the object typedyn Introspect``

Does it mean I need to implement "introspect"? If so , how?

Put dependencies behind features

"Don't pay for what you don't use"
Bzip2 is good, but packaging a full bzip2 encoder/decoder even if you don't use compression is a bit cumbersome.
Same goes for encryption for example.

I suggest putting theses behind conditional features.
Cargo's default features can be use to keep backward's compatibility.

memory allocation of 11159284083750323767 bytes failedAborted (core dumped)

I have this corrupted file, that I'm trying to load using the following code:

let map_loader = load_encrypted_file("./tgr/7.bin", 0, "mykeyhere");

Loading this file causes the following error:

memory allocation of 11159284083750323767 bytes failedAborted (core dumped)

It seems to me this should throw an error and not cause a core dump.

EDIT. It looks any binary file will cause this. I used dd if=/dev/urandom of=7.bin bs=1024 count=3 to make one, and it core dumped like above

Implement the default_trait tag

#[default_trait="TraitName"] is not implemented yet.

This is a way to be able to provide arbitrary default values of complex types, to fields which did not exist in older versions of protocol.

Stack-overflow for recursive data-structures

Savefile does not presently support recursive data-structures.

To be precise, the problem is with the schema-function. The schema-function tries to provide a simple tree which describes the data format. However, this fails if the data is recursive in nature.

Consider this data structure:

struct TreeNode(u32, Vec<TreeNode>);

The schema for TreeNode is basically a tuple of (u32,[TreeNode]). But savefile will try to evaluate the schema down to primitives, and will thus evaluate the schema of TreeNode again, yielding (u32,[(u32,[TreeNode])]), then (u32,[(u32,[(u32,[TreeNode])])]) etc in infinity.

Savefile is previously documented as not supporting cyclic data structures. But as now discovered, any recursive data structure, even without actual cycles, causes problems.

I can see 3 possible ways forward:

1: Just document that recursive data structures are not supported. Possibly add some sort of recursion-limit to detect the problem.

2: Add support for recursive data structures.

3: Possibly add full support for serializing/deserializing arbitrary graphs, including graphs with cycles

Encryption?

Any thoughts on adding an encryption layer? I'm not thinking anything fancy, just simple symmetrical encryption with a preshared key.

I'm inquiring because I'm going to try to use this for state dumps of my applications (and in the future use this to transfer data between applications and datacenters) and encryption natively would remove complexity from my future plans.

Something like this (assuming your demo code):

save_encrypted_file("save.bin", 0, player, "my symmetrical key is this").unwrap();

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.