grpc-rs icon indicating copy to clipboard operation
grpc-rs copied to clipboard

Codegen ergonomics: message construction

Open m4b opened this issue 7 years ago • 4 comments

I do a lot of:

// get internal struct from somewhere
let mystruct = GetMyStruct::get();
let mut req = Req::new();
// now convert that struct anually to the request
req.set_foo(mystruct.foo);
req.set_bar(mystruct.bar);

This becomes very tedious, so I have a couple of suggestions:

Constructor with field params

it would be nice if I could have a constructor method like:

let req = Req::with(mystruct.foo, mystruct.bar);

and pass in the message fields as params.

Generic Conversion Trait

Similarly, it would be really great if codegen spit out something like:

trait ConvertInto<T> {
  fn convert_into(t: Self) -> T;
}

impl From<T: ConvertInto<Req>> for Req {
  fn from(t: T) -> Self {
     T::convert_into(t)
  }
}

Or something like that; I think you get the idea.

This way in my crate/upstream clients only have to impl ConvertInto<Req> for their internal datatypes, and can get conversion encapsulated in a single space (and protects refactoring somewhat by shielding struct changes, etc.) by essentially doing:

impl ConvertInto<Req> for Mystruct {
  fn convert_into(t: Mystruct) -> Req {
    let mut req = Req::new();
    req.foo = mystruct.foo;
    req.bar = mystruct.bar;
    req
  }
}
...
// which yields this nice code:
let req = GetMystruct::get().into();

m4b avatar Jan 06 '18 21:01 m4b

Thanks for the suggestion, I believe you can impl From<Mystruct> for Req directly.

BusyJay avatar Jan 07 '18 02:01 BusyJay

Wouldn't I have to do this in the generated code directly, otherwise this violates coherency, no?

m4b avatar Jan 07 '18 02:01 m4b

Lol you're totally right; I forgot it's only coherency at the crate level, not module level :P

Ok so scratch second idea :P

m4b avatar Jan 07 '18 02:01 m4b

As for the first idea, I agree it's a better way to construct messages that have a few fields. However the code for a message is not generated by grpc-rust plugin, it's generated by rust-protobuf plugin. All grpc-rust plugin handles are the service parts. So maybe you want to raise an issue to the the project.

BusyJay avatar Jan 07 '18 03:01 BusyJay