doctorn / obake Goto Github PK
View Code? Open in Web Editor NEWVersioned data-structures for Rust
License: Apache License 2.0
Versioned data-structures for Rust
License: Apache License 2.0
The main use I'd have for this crate is to version config files (as described in the readme) but there doesn't currently appear to be a mechanism for attempting to attempt to parse as any version (in order to then upgrade it).
Currently it requires something along the lines of:
let x: Foo = toml::from_str(content)
.map(<Foo as obake::Versioned>::Versioned::Foo_v0_2_0)
.or_else(|_| {
toml::from_str(content)
.map(<Foo as obake::Versioned>::Versioned::Foo_v0_1_0)
})?
.into();
This ofc gets a bit repetitive (the above is only 2 versions!) and while it would require a bit of special-casing, it'd be preferable for the above to be possible to derive serde traits for the Versioned enum.
Alternatively you could provide a mechanism for running a function polymorphic over its return type over each version in sequence until one returns Ok
.
This could look something like:
let x = Foo::for_all_versions(toml::from_str)(content)?;
Also worth noting (as I'm sure you're away) that if you derive serde traits for the enum using #[obake(derive(Serialize, Deserialize))]
it will ofc expect you to describe an version such as:
[Foo_v0_1_0]
foo = 'foo'
baz = 'x'
I am trying to remove the field
#[derive(Deserialize, Serialize, Debug, PartialEq)]
#[obake::versioned]
#[obake(version("0.1.0"))]
#[obake(version("0.2.0"))]
pub struct Test {
#[obake(cfg("0.1.0"))]
pub foo: u16,
pub bar: Vec<u16>,
}
impl From<Test!["0.1.0"]> for Test!["0.2.0"] {
fn from(this: Test!["0.1.0"]) -> Self {
Self { bar: this.bar }
}
}
The error is
15 | pub foo: u16,
| ^^^ `Test_v0_2_0` does not have this field
|
= note: all struct fields are already assigned
Currently it doesn't seem to be possible to determine current version of a struct given a reference to a struct (clone() is not an option for the struct I have).
I believe it would be desirable to provide an alias such as:
pub type AnyVersion<T> = <T as obake::Versioned>::Versioned;
reasoning:
Willing to PR such a change but didn't want to so without first seeing if it's desirable. Name is just the first thing I thought of and ultimately not important if you have one in mind.
Hi! This library is so useful, but I'm failing to use it with serde_json
. I've tried the following way:
use serde_json::json;
use obake;
#[obake::versioned]
#[obake(version("0.1.0"))]
#[obake(version("0.2.0"))]
#[obake(version("0.3.0"))]
#[obake(derive(Debug, PartialEq, serde::Serialize, serde::Deserialize))]
#[obake(serde(untagged))]
#[derive(Debug, Default, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
struct Character {
name: String,
age: u32,
#[obake(cfg(">=0.2.0"))]
height: f32,
#[obake(cfg(">=0.3.0"))]
weight: f32,
}
impl From<Character!["0.1.0"]> for Character!["0.2.0"] {
fn from(old: Character!["0.1.0"]) -> Self {
Self {
name: old.name,
age: old.age,
..Default::default()
}
}
}
impl From<Character!["0.2.0"]> for Character!["0.3.0"] {
fn from(old: Character!["0.2.0"]) -> Self {
Self {
name: old.name,
age: old.age,
height: old.height,
..Default::default()
}
}
}
fn main() {}
#[cfg(test)]
mod tests {
use serde_json::json;
use crate::*;
#[test]
fn from_2_to_3() {
let freeza_ser = serde_json::to_string_pretty(&json!({
"name": "Freeza",
"age": 32,
"height": 1.53,
})).unwrap();
dbg!(&freeza_ser);
let freeza: VersionedCharacter = serde_json::from_str(&freeza_ser).unwrap();
dbg!(&freeza);
let freeza: Character = freeza.into();
dbg!(&freeza);
let freeza_expected = Character {
name: "Freeza".into(),
age: 32,
height: 1.53,
weight: 0.,
};
assert_eq!(&freeza_expected, &freeza);
}
}
The output is:
failures:
---- tests::from_2_to_3 stdout ----
[src/main.rs:56] &freeza_ser = "{\n \"age\": 32,\n \"height\": 1.53,\n \"name\": \"Freeza\"\n}"
[src/main.rs:59] &freeza = Character_v0_1_0(
Character_v0_1_0 {
name: "Freeza",
age: 32,
},
)
[src/main.rs:61] &freeza = Character_v0_3_0 {
name: "Freeza",
age: 32,
height: 0.0,
weight: 0.0,
}
thread 'tests::from_2_to_3' panicked at 'assertion failed: `(left == right)`
left: `Character_v0_3_0 { name: "Freeza", age: 32, height: 1.53, weight: 0.0 }`,
right: `Character_v0_3_0 { name: "Freeza", age: 32, height: 0.0, weight: 0.0 }`', src/main.rs:69:9
So, the current behavior is that serde_json::from_str::<VersionedCharacter>(&freeza_ser)
is deserializing into the first version, and I want it to deserialize like the following:
fn character_parser(serialized_data: &String) -> Character {
if let Ok(data) = serde_json::from_str::<Character!["0.3.0"]>(&serialized_data) {
return data;
}
if let Ok(data) = serde_json::from_str::<Character!["0.2.0"]>(&serialized_data) {
let data: Character!["0.3.0"] = data.into();
return data;
}
if let Ok(data) = serde_json::from_str::<Character!["0.1.0"]>(&serialized_data) {
let data: Character!["0.2.0"] = data.into();
let data: Character!["0.3.0"] = data.into();
return data;
}
return Character::default();
}
Am I missing something crucial here? Is there any way for this lib to implement that parsing automatically?
Thank you!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.