Skip to main content

ReadXDR

Derive Macro ReadXDR 

Source
#[derive(ReadXDR)]
{
    // Attributes available to this derive:
    #[xdr]
    #[xdrs]
}
Expand description

Derives the ReadXDR trait for a struct or enum.

This macro generates an implementation that deserializes the type from XDR format. All field types must implement ReadXDR.

§Attributes

  • #[xdr(from_type = "Type")] - Deserialize to the intermediate type “Type” before converting into the target type via Into.
  • #[xdr(via = "Type")] - Same as above (also implies into_type).
  • #[xdr(default_variant)] - On an enum variant (which must be the trailing variant): mark it as the union’s default arm. Discriminants that match no other variant decode to this variant, with the wire discriminant stored in its first field (which must be i32). Without a default variant, unknown discriminants fail with a decode error.
  • #[xdr(crate = "path::to::xdrs")] - Override the path to the xdrs crate (useful when re-exporting from another crate).

§Limitations

  • No recursive types. XDR decoding is not self-describing; a recursive type will loop at runtime. The macro does not detect or reject recursion. In particular, #[xdr(from_type = "Self")] is an infinite loop — the generated impl reads a Self and converts it into Self (a no-op), re-entering the same decoder until the stack overflows. The surrogate type must always be a distinct, non-recursive type.
  • All field types must be deserializable. Every field (or the surrogate type, when using from_type/via) must independently satisfy ReadXDR. The macro copies the input type’s generic bounds verbatim — it does not infer or propagate trait bounds required by a surrogate type’s own generic parameters. For example, #[xdr(from_type = "VecM<T, 8>")] on a generic Wrapper<T> will not automatically add T: ReadXDR; you must supply the bound yourself.
  • Borrowed fields need a general lifetime implementation. A custom field type Borrowed<'a> must implement ReadXDR<'r> whenever 'r: 'a, just like the built-in borrowed types. Implementing only ReadXDR<'a> for Borrowed<'a> does not suffice for in-place decoding: the field’s type is fixed behind a mutable pointer, so the compiler cannot shorten the returned value’s lifetime at the assignment site. Use impl<'r: 'a, 'a> ReadXDR<'r> for Borrowed<'a>.
  • The lifetime name '_r is reserved. The generated ReadXDR impl uses '_r as its reader lifetime. A type deriving ReadXDR must not declare a generic lifetime parameter with that same name; choose another name for user-defined lifetimes.