Restricted rust -> proto?

The standard way to use protobuf is something like:

  1. write/edit protobuf file
  2. generate bindings for Rust/GoLang/JVM/...
  3. if need to change, go to 1

In practice this works great if all the used languages are equal class citizens in the project. This is not my situation, where Rust is the 'main' language, and the other languages are 'glue' languages.

The above is inconvenient for two reasons:

  1. the generated protobuf -> Rust struct/enums are not always idiomatic / concise
  2. when editing in Rust, IntelliJ jumps me to the generated Rust code, but then I have to go modify the *.proto file, etc ...

I am wondering if there is a set of crates that works as follows:

  1. instead of a *.proto file, we define the structs / enums in a strict subset of Rust
  2. so the ".proto file" is a ".rs file" but in a strict subset of Rust
  3. the ".proto file" is then generated from this "heavily restricted .rs file"

The benefits here are:

  1. the Rust bindings always feel clean/idiomatic
  2. IntelliJ can jump me to the right files to edit

The downside is that other language bindings are a bit messier, but in this case where Rust = main langauges, other = glue languages, it is an acceptable tradeoff.

Is there any crate that does this? Express protobuf structs in an restricted subset of Rust.

EDIT: Preemptive 'why not use Serde/Json' -- I like static types in the glue languages too.

EDIT 2: I am willing to give up all the versioning / add-remove field benefits of protobuf. My workflow will be something like:

  1. Write Rust code.

  2. Run the "restricted *.rs -> proto -> GoLang / JVM" generator

  3. Fix the GoLang / JVM code.

  4. There is no need to access previously stored protobuf data; nor is there a need to be compatible with anything but the current version of the structs/enums.

So I'm going to not answer the question, but hopefully helpfully.

I would suggest using the protobuf <-> idiomatic rust layer as a great opportunity for Aiming for correctness with types aka Parse, don’t validate. It will always be possible for the caller to provide non-useful protobuf, since the format isn't restricted. So you need to write the logic for that anyway, at which point doing it as the conversion to a custom rust model is great.

That has a bunch of other goodness too, like making it clear that you can change the internal model however you want without worrying, but you need to be back-compatible in changes to the external models.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.