Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serde support #56

Open
vitvakatu opened this issue Jun 8, 2017 · 0 comments
Open

Serde support #56

vitvakatu opened this issue Jun 8, 2017 · 0 comments
Assignees
Labels

Comments

@vitvakatu
Copy link
Collaborator

It would be nice to have ability to serialize and deserialize storages and pointers with serde. It can be useful in game when you want to save current CGS state. However, it's not easy as I thought before.
Basically, serde isn't a big problem, this test works well after a few lines added:

fn test_serde() {
    #[derive(Serialize, Deserialize)]
    struct Node {
        value: i32,
    }
    let mut storage = Storage::new();
    storage.create(Node { value: 32 });
    storage.create(Node { value: 64 });
    let pointers: Vec<Pointer<Node>> = storage
                                    .iter_all()
                                    .map(|v| storage.pin(&v))
                                    .collect();
    let storage_serialized = serde_json::to_string(&storage).unwrap();
    let storage_deserialized: Storage<Node> = serde_json::from_str(&storage_serialized).unwrap();

    let pointers_serialized = serde_json::to_string(&pointers).unwrap();
    let pointers_deserialized: Vec<Pointer<Node>> = serde_json::from_str(&pointers_serialized).unwrap();

    assert_eq!(storage_deserialized.iter_all().count(), 2);
    assert_eq!(storage_deserialized.iter().count(), 2);
    assert_eq!(storage_deserialized[&pointers_deserialized[0]].value, 32);
}

It's definitely safe to deserialize Storage and pointers. But there is one condition - you must not have any Storage in memory before deserializing.
Each Storage has unique identifier, that is used by pointers to link with specific storage. Identifier is controlled by static AtomicUsize. So, deserialized Storage uses "old" identifier, that isn't valid in the new program state. Pointers to deserialised Storage will be able to retrieve data from user's Storage and vise versa.

How to solve this challenge?

My idea is to provide procedural macro for user-defined structs.
Rough code:

#[derive(FroggySerialize)]
struct MyWorld {
    storage1: Storage<MyType>,
    storage2: Storage<MyAnotherType>,
    pointers: Vec<Pointer>,
    #[serde(skip)] // ability to use serde's attributes
    unnecessary_data: i32,
    necessary_user_data: MyAwesomeType,
}

This macro will provide custom serde::Serialize and serde::Deserialize traits implementation.

  • Serializing
    • sync pending
    • serialize data (we don't even need meta, for example)
  • Deserializing
    • deserialize data
    • update all unique ids both in Storage and Pointer according to current program state
    • deserialize pointers and sync pending
@vitvakatu vitvakatu self-assigned this Jun 8, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant