Derive Macro Protocol

Source
#[derive(Protocol)]
{
    // Attributes available to this derive:
    #[async_proto]
}
Expand description

Implements the Protocol trait for this type.

By default, the network representation is very simple:

  • Attempting to read an enum with no variants errors immediately, without waiting for data to appear on the stream.
  • For non-empty enums, the representation starts with the discriminant (a number representing the variant), starting with 0 for the first variant declared and so on.
    • For enums with up to 256 variants, the discriminant is represented as a u8. For enums with 257 to 65536 variants, as a u16, and so on.
  • Then follow the Protocol representations of any fields of the struct or variant, in the order declared.

This representation can waste bandwidth for some types, e.g. structs with multiple bool fields. For those, you may want to implement Protocol manually.

§Attributes

This macro’s behavior can be modified using attributes. Multiple attributes can be specified as #[async_proto(attr1, attr2, ...)] or #[async_proto(attr1)] #[async_proto(attr2)] .... The following attributes are available:

  • #[async_proto(as_string)]: Implements Protocol for this type by converting from and to a string using the FromStr and ToString traits. The FromStr error type must implement Into<ReadErrorKind>.
    • #[async_proto(map_err = ...)]: Removes the requirement for the FromStr error type to implement Into<ReadErrorKind> and instead uses the given expression (which should be an FnOnce(<T as FromStr>::Err) -> ReadErrorKind) to convert the error.
  • #[async_proto(attr(...))]: Adds the given attribute(s) to the Protocol implementation. For example, the implementation can be documented using #[async_proto(attr(doc = "..."))]. May be specified multiple times.
  • #[async_proto(via = Proxy)]: Implements Protocol for this type (let’s call it T) in terms of another type (Proxy in this case) instead of using the variant- and field-based representation described above. &'a T must implement TryInto<Proxy> for all 'a, with an Error type that implements Into<WriteErrorKind>, and Proxy must implement Protocol and TryInto<T>, with an Error type that implements Into<ReadErrorKind>.
    • #[async_proto(clone)]: Replaces the requirement for &'a T to implement TryInto<Proxy> with requirements for T to implement Clone and TryInto<Proxy>.
    • #[async_proto(map_err = ...)]: Removes the requirement for <Proxy as TryInto<T>>::Error to implement Into<ReadErrorKind> and instead uses the given expression (which should be an FnOnce(<Proxy as TryInto<T>>::Error) -> ReadErrorKind) to convert the error.
  • #[async_proto(where(...))]: Overrides the bounds for the generated Protocol implementation. The default is to require Protocol + Send + Sync + 'static for each type parameter of this type.

§Field attributes

Additionally, the following attributes can be set on struct or enum fields, rather than the entire type for which Protocol is being derived:

  • #[async_proto(max_len = ...)]: Can be used on a field implementing the LengthPrefixed trait to limit the allowable length. Note that this alters the network representation of the length prefix (with a max_len of up to 255, the length is represented as a u8; with a max_len of 256 to 65535, as a u16; and so on), so adding/removing/changing this attribute may break protocol compatibility.

§Compile errors

  • This macro can’t be used with unions.