Yeah, this is kinda the cost of not having an encode/decode step. The Haskell implementation (of which I am the primary author) provides a higher-level API with "normal" data types for cases where performance requirements aren't stringent enough to merit the extra burden on the developer. I'm mostly interested in RPC, so I rarely use the low-level API myself...
https://github.com/capnproto/capnproto-rust/blob/master/exam...
https://docs.rs/prost/0.6.1/prost/trait.Message.html#method....
(Ok I couldn't actually find an example for Prost because all you do is create a normal Rust `struct` and call `encode()` on it.)