google-apis-rs / google-cloud-rs

Asynchronous Rust bindings for Google Cloud Platform APIs.
176 stars 48 forks source link

Figure out mechanism to easily convert to/from Datastore values #2

Closed Hirevo closed 4 years ago

Hirevo commented 4 years ago

Datastore support got merged (#1), and exposes the datastore::Value type as the form for the Datastore's data.
We need a way to easily convert user types to and from Datastore types.

Currently, a few types can be converted into their datastore::Value equivalents by using the Into<datastore::Value> trait:

use gcp::datastore::Value;

let name = "some-name".into::<Value>();
let age = 21.into::<Value>();

assert_eq!(name, Value::StringValue(String::from("some-name")));
assert_eq!(age, Value::IntegerValue(21));

Possible solutions:

Hirevo commented 4 years ago

Very happy to say that we finally have a very smooth solution for working with Datastore values.

We introduced the gcp::datastore::{FromValue, IntoValue} traits to allow conversion to and from gcp::datastore::Value and provided implementation for common types from std.

But we also needed a way to make these conversions easy for user-defined types to fully solve this issue and this is where the new gcp-derive crate comes in.

gcp-derive provides #[derive(..)] proc-macros for IntoValue and FromValue to allow any user-defined type to have these easy conversions enabled.

So, you can just do this and everything just works:

use gcp::datastore::{FromValue, IntoValue};

#[derive(FromValue, IntoValue)]
pub struct Foo {
    bar: String,
    baz: i64,
    qux: bool,
}

fn main() {
    let foo = Foo { bar: String::from("test"), baz: 42, qux: true };
    println!("original: {:?}", foo);

    let value = foo.into_value();
    println!("converted: {:?}", value);

    let recovered = Foo::from_value(value);
    println!("recovered: {:?}", recovered);
}