Open htuch opened 4 years ago
I looked at this briefly using the cxx library for the interop. You can see my attempt here.
The problems I encountered:
Buffer::Instance
) into Rust and allow methods to be called on them, every virtual function would need a corresponding free function that is implemented in C++ and calls the virtual function. So there would need to be a Buffer_Instance_add_string_view
free function that just called Buffer::Instance::add
. And each one would need a different name since Rust doesn't support function overloading.Thanks @akonradi. FWIW my view is we should avoid C++ interop for now and just stick with C which I think should be not that bad for some initial use cases.
Yeah to be fair, C++ interop isn't a thing because there's no C++ ABI. Everybody just uses C as the lowest common denominator, including Rust. cxx generates bindings in both languages that, at the bottom, use C-style FFI calls, but allow passing things like std::unique_ptr, which has ownership semantics. IMO Rust's lifetime enforcement doesn't offer you much if you're limited to passing ints and raw pointers across.
One other "problem" I encountered, at least for Google, is that any non-trivial Rust usage is going to require either pulling in external crates or duplicating a bunch of functionality that Envoy already has or depends on in C++, but in Rust. That's going to increase the size of Envoy's trusted codebase significantly.
We should be clear about what we expect to gain in each case. Having wrappers that allow implementing filter extensions in other languages including Rust seems a nice thing to have.
Having to jump through C callback APIs in codec dispatch if we attempt to write protocol parsers in Rust seems as brittle as the current interaction between Envoy code and C-based parsers like http-parser and nghttp2.
I use https://github.com/dtolnay/cxx with Bazel. It works fine. If you want to use external cargo crates, you'll end up using cargo-raze anyway.
This little patch shows you how to update in-tree cargo deps for use with cxx
and Bazel:
https://github.com/dtolnay/cxx/pull/59/files#diff-c0a5305a356389c2faccfb74e002f153
I'd also like to make sure we have clear goals for each use case. I'm excited to get rust in, and it sounds very possible given the state of tooling. But I'd hate to end up in a place where we end up we use rust in perhaps not the best scenario and people just see it as "that thing that's annoying to deal with, or we have to do $X in C interface cause rust needs it :sigh: ".
Ideally we'd start with very high visibility, low friction to many contributor places where rust would work well. Particularly I'm thinking of parsers/headermap. These would also really put rust through the paces forcing us to figure out a sane interface at the beginning. While filters would be nice I feel like the chance to cause churn for people is a bit higher, and if someone really wants it they can use WASM filters where lots of tooling has been developed already.
Yeah, I agree that the Wasm Nullvm and Rust are likely the ideal filter integration point for extensions. @PiotrSikora @jplevyak do you have any pointers on how folks would be able to get started writing NullVm Rust filters?
Interesting take from Chrome on C++ interop: https://www.chromium.org/Home/chromium-security/memory-safety/rust-and-c-interoperability
The NullVm is nice because it works around the issues that Chrome would be facing as it already has a language level translator including explicit memory management and ownership transfers.
We would have to create a NullVM SDK for rust. This wouldn't be that hard as most of the work from the C++ NullVM code could be repurposed transparently. There is a bit of code required in the "VM runtime" which is different and will have to be written specifically to support rust, in particular the code which registers the in-VM Context and RootContext factories.
@PiotrSikora what is your take on this. How much work do you think it would be?
FWIW here, we are already able to write extensions in Rust via Wasm NullVm mechanism: https://github.com/mathetake/proxy-wasm-rust-nullvm and link them statically.
I'm opening this as a top-level tracking issue for some initial possible projects for incrementally introducing Rust to Envoy. The idea is to benefit from the memory safety and ecosystem growth in Rust while retaining high performance, without boiling the ocean. Given Rust's use in places such as Mozilla, Tor, Linkerd and Linux kernel, it seems to make sense to scope out what we can achieve here.
Any use of Rust in Envoy will need to navigate build system (i.e. Bazel) and FFI integration. Some initial projects that could be possible:
More advanced uses in the future could include: