Most convenient approach to serializing ffi objects?

Hi, I’m using a crate (krb5-sys) that provides bindings to a system
library which works reasonably well so far. Now I need to dump some
data to disk, but it’s all C types handled by the library.

Writing serializers manually using serde’s SerializeStruct is
feasible but it’s cumbersome and error-prone so I’d prefer to have
that step automated as much as possible. If it can be avoided I’d
rather not touch the crate though.

Is there a way I have overlooked that I could use auto-generation
with #[derive(serde::Serialize)] et al. for types in a third party
C library? Serde is just what I default to, I’d be open to other
approaches (IDL?) if they save me work. Alternatively, any advice
as to how to remain sane serializing deply nested C structs and
arrays?

I'm guessing the best solution would be for upstream to implement serialization and let users leverage that.

Otherwise you're stuck either writing the serialization code by hand (serde::ser::SerializeStruct) or you could write Rust definitions of each type, slap a #[derive(Serialize, Deserialize)] on them, then manually map from the C types to the Rust types.

I'm not sure how well a code generator would go with generating serialization code by just inspecting the header file. If your struct contains a pointer, it's hard to tell whether that's an owning reference, or whether multiple things point to that same struct, or even if the pointer is actually meant as an array. Reconstructing that sort of relationship just based on the type definitions (i.e. no contextual knowledge of how the library is used) after serializing and deserializing is probably more than a code generator could handle.

I'm guessing the best solution would be for upstream to
implement serialization and let users leverage that.

I don’t think there is a serialization mechanism in MIT Kerberos
apart from keytabs.

Otherwise you're stuck either writing the serialization code by
hand (serde::ser::SerializeStruct) or you could write Rust
definitions of each type, slap a #[derive(Serialize, Deserialize)] on them, then manually map from the C types to the
Rust types.

For the bits I’m using, manual serialization is feasible albeit
tedious.

I'm not sure how well a code generator would go with generating
serialization code by just inspecting the header file. If your
struct contains a pointer, it's hard to tell whether that's an
owning reference, or whether multiple things point to that same
struct, or even if the pointer is actually meant as an array.

IDL allows to express at least some of this. Though “ownership”
in C context needs to be established by contract. That’s all
just hypothetical, of course, as I’m not aware of any interface
definitions for libkrb5.

Thanks for your reply!

1 Like