TLDR: there are stable APIs for encoding and decoding FIDL domain objects without necessarily involving calling a FIDL method in a protocol and/or sending them down a channel.
The new C++ bindings and the Rust bindings now offer standalone usage of FIDL encoding and decoding. The bindings have always been able to encode/decode FIDL messages, but those APIs needed some tweaks to promote maximum evolvability and updatability, before we can support them long term. The details are spelled out in RFC-120 if you're interested.
The recommended way to encode and decode FIDL domain objects is to use persistence APIs. This works for non-resource structs, unions, and tables:
In Rust they're called fidl::encoding::persist and fidl::encoding::unpersist. See reference.
In the new C++ bindings they're called fidl::Persist and fidl::Unpersist / fidl::InplaceUnpersist, the latter depending on whether one would like to decode into natural types or wire types. See reference for wire types and natural types.
We have written a realistic example project that shows how to use this feature to build a key-value store. Prospective applications include storing FIDL domain objects in a file or sending them in a VMO. Please check them out if that matches your use case!
If you would like to send domain objects with handles in them (and necessarily resource types), the usual option would be via a FIDL protocol. However, sometimes that may not be possible such as during bootstrapping. In this case, you may use the underlying standalone encoding/decoding API, which also supports handles:
In Rust they're called fidl::encoding::standalone_encode and fidl::encoding::standalone_decode. See reference.
In the new C++ bindings they're called fidl::Encode and fidl::Decode / fidl::InplaceDecode, the latter depending on whether one would like to decode into natural types or wire types. See reference for wire types and natural types.
In order to version the FIDL wire format used in the message, standalone encoding produces FIDL wire format metadata in addition to the encoded bytes and handles. Providing all three to standalone decoding would recover the original domain object. By contrast, the persistence APIs automatically attach the wire format metadata at the beginning of the bytes, so it is more ergonomic and safer. Note that this means data resulting from persistence APIs cannot be directly supplied to standalone decoding and vice versa, unless one is careful about extracting the wire format metadata. When in doubt, always use one set of APIs or the other.
You may reach us at fidl...@fuchsia.dev.