Skip to main content

proto_oneof

Attribute Macro proto_oneof 

Source
#[proto_oneof]
Expand description

Implements protobuf schema and validation features for a rust enum.

This macro will implement the following:

  • Clone
  • PartialEq
  • prost::Oneof
  • ProtoOneof
  • ValidatedOneof
  • CelOneof (if the cel feature is enabled)
  • A method called check_validators (compiled only with #[cfg(test)]) for verifying the correctness of the validators used in it
  • (If the skip_checks(validators) attribute is not used) A test that calls the check_validators method and panics on failure.

If the impl is not proxied, these traits and methods will target the struct directly.

If the impl is proxied:

  • A new struct with a Proto suffix will be generated (i.e. MyOneof -> MyOneofProto) and these traits and methods will target that. An impl for ProxiedOneof will also be generated.
  • The proxy will implement OneofProxy.

To learn more about proxied implementations, visit the dedicated section.

ℹ️ NOTE: In protify, oneofs are reusable. This means that tags must be set manually for each of the variants, and that the name of the oneof will be the name of the field in the message where it’s used. To learn more about oneofs, visit the reusing oneofs section.

§Examples

use protify::*;

#[proto_oneof]
pub enum NormalOneof {
	// Tags must be set manually!
	#[proto(tag = 1)]
	A(i32),
	#[proto(tag = 2)]
	B(u32),
}

// Generates `ProxiedOneofProto` as the proto-facing version
#[proto_oneof(proxied)]
pub enum ProxiedOneof {
	#[proto(tag = 1)]
	A(i32),
	#[proto(tag = 2)]
	B(u32),
}

fn main() {
	use protify::*;

	// `ProxiedOneof` and `OneofProxy` methods
	let oneof = ProxiedOneofProto::A(1);
	let proxy = oneof.into_proxy();
	let oneof_again = proxy.into_oneof();
}

§Macro attributes

  • proxied
    • Type: Ident
    • Example: #[proto_oneof(proxied)]
    • Description: Creates a proxied oneof

§Container attributes:

  • derive

    • Type: list of Paths
    • Example: #[proto(derive(Copy))]
    • Description: In case of a proxied impl, it specifies derives to apply to the Proto oneof. Shorthand for #[proto(attr(derive(..)))]
  • attr

    • Type: MetaList
    • Example: #[proto(attr(serde(default)))]
    • Description: Forwards the given metas to the proto oneof. In the example above, the proto oneof would receive the attribute as #[serde(default)].
  • options

    • Type: Expr
    • Example: #[proto(options = vec![ my_option_1() ])]
    • Description: Specifies the options for the given oneof. It must resolve to an implementor of IntoIterator<Item = ProtoOption>.
  • from_proto

    • Type: function Path or closure
    • Example: #[proto(from_proto = my_convert_fn)] or #[proto(from_proto = |v| v.some_method())]
    • Description: Overrides the automatically generated conversion from proto to proxy.
  • into_proto

    • Type: function Path or closure
    • Example: #[proto(into_proto = my_convert_fn)] or #[proto(into_proto = |v| v.some_method())]
    • Description: Overrides the automatically generated conversion from proxy to proto.
  • validate

    • Type: Expr, or bracketed list of Exprs
    • Example: #[proto(validate = [ CustomValidator, *STATIC_VALIDATOR ])]
    • Description: Defines the default validators for the given oneof. These will be executed inside the oneof’s own validate method, and whenever the oneof in another message, along with the validators defined for each variant. The expressions is it must resolve to an implementor of Validator for the oneof.
  • skip_checks

    • Type: list of Idents
    • Example: #[proto(skip_checks(validators))]
    • Description: Disables the generation of tests. Currently, the allowed values are:
      • validators: disables the automatic generation of a test that checks the validity of the validators used by the message. The check_validators method will still be generated and be available for manual testing.

§Variant attributes

§Type Attribute

In most cases, the specific protobuf type of the field will be automatically inferred, if primitive types are used.

For special int types (such as sfixed32 or sint32), bytes, oneofs, enums and messages, it may be necessary to specify these manually.

For the scalar types, you can simply use their protobuf name (sint32, bytes), whereas for oneofs, enums and messages there are a set of special attributes.

  • message

    • Type: Ident or MetaList
    • Example: #[proto(message)] or #[proto(message(default, proxied))]
    • Description: This can be used just as a plain ident to signal that the target type is an unproxied message. Otherwise, these other attributes can be used inside parentheses: - proxied: specifies that the message is proxied, so that the proto item will contain the proxied message with the Proto suffix and not the proxy itself. Only available for proxied impls. - default: allows the message to be used without being wrapped in Option. In this case, the default conversion from proto for the field will use Default::default() if the field is None in the proto item. Only available for proxied impls. - boxed: marks the message as boxed. Automatically inferred in most cases. - (any other path): this path will be assumed to be a custom proxy for the given message. Only available for proxied impls.
  • oneof

    • Type: MetaList

    • Example: #[proto(oneof(tags(1, 2), default, proxied))]

    • Description: Marks the field as a oneof. Since oneofs are reusable, this will generate a new oneof in the output proto file belonging to the specific message where it’s being used, which will have the snake_case name of the field, or a custom name if the name attribute is used.

      All the validators being defined on the oneof will be used, and the extra ones used for this specific field will only apply to the containing message.

      All the schema settings of the original oneof such as options will be retained, and the extra ones set on the field will apply only to the specific oneof being generated for this message.

      Unlike other fields, the tags for a given oneof must be set manually, and they must match the tags of the oneof precisely. The macro will automatically generate a test that checks the accuracy of the tags.

      For more information, visit [reusing oneofs].

      Other supported attributes are:

      • proxied: specifies that the oneof is proxied, so that the proto message will contain the proxied oneof with the Proto suffix and not the proxy itself. Only available for proxied impls.
      • default: allows the oneof to be used without being wrapped in Option. In this case, the default conversion from proto for the field will use Default::default() if the field is None in the proto item. Default should be implemented for the target oneof. Only available for proxied impls.
      • (any other path): this path will be assumed to be a custom proxy for the given oneof. Only available for proxied impls.
  • enum_

    • Type: Ident or MetaList
    • Example: #[proto(enum_)] or #[proto(enum_(MyEnum))]
    • Description: Specifies that the field is a proto enum. In proxied impls, the path to the specific enum should be inferred automatically, but in direct impls, the path should be specified inside parentheses.

§Cardinality Attributes

The cardinality of the field should be inferred automatically in most cases from the given type (BTreeMap/HashMap -> map, Vec -> repeated, Option -> optional (except for messages)), but if it’s not, then it can be specified as follows:

  • repeated -> repeated(target_type_as_above)
  • optional -> optional(target_type_as_above)
  • map -> map(key_type_as_above, value_type_as_above)

§Other Attributes

  • ignore

    • Type: Ident
    • Example: #[proto(ignore)]
    • Description: Excludes the field from the proto item (only valid in proxied impls). By default, the conversion from proto to proxy for this field will use Default::default() for message fields, and NameOfOneofProto::default() for oneof variants.
  • attr

    • Type: list of Metas
    • Example: #[proto(attr(default))]
    • Description: Forwards the given metas to the proto field. In the example above, the target field would receive the attribute as #[default].
  • options

    • Type: Expr
    • Example: #[proto(options = vec![ my_option_1() ])]
    • Description: Specifies the options for the given field. It must resolve to an implementor of IntoIterator<Item = ProtoOption>.
  • name

    • Type: string
    • Example: #[proto(name = "abc")]
    • Description: Specifies the name of the field. Overrides the default behaviour, which uses the snake_case name of the field, escaping any leading r# or trailing _.
  • from_proto

    • Type: function Path or closure
    • Example: #[proto(from_proto = my_convert_fn)] or #[proto(from_proto = |v| OtherType { val: v.val })]
    • Description: Overrides the automatically generated conversion from proto to proxy. If the field is marked with ignore, a closure cannot be used.
  • into_proto

    • Type: function Path or closure
    • Example: #[proto(into_proto = my_convert_fn)] or #[proto(into_proto = |v| OtherType { val: v.val })]
    • Description: Overrides the automatically generated conversion from proxy to proto.
  • deprecated

    • Type: Ident
    • Example: #[proto(deprecated = false)] or #[deprecated]
    • Description: Marks the message as deprecated. The proto output will reflect this setting. If for some reason you want to deprecate the rust field but not the proto field, you can use #[deprecated] along with #[proto(deprecated = false)]. Vice versa, you can deprecate the proto field only by using #[proto(deprecated = true)]
  • validate

    • Type: closure or expression, or a list of them surrounded by brackets

    • Example: #[proto(validate = |v| v.cel(my_cel_rule))] or #[proto(validate = [ CustomValidator, *STATIC_VALIDATOR ])]

    • Description: Defines the validators for the given field. These will be executed inside the container’s own validate method. If a closure if used, the default validator builder for the given type will be passed as the argument, and the validator will be cached in a static Lazy (except for the OneofValidator). If another expression is used, it must resolve to an implementor of Validator for the target type.

      NOTE: For messages (or vectors/maps of such messages) and oneofs that have their own validators, they will be triggered even if no field validator is specified.

  • tag

    • Type: number
    • Example: #[proto(tag = 1)]
    • Description: Sets the protobuf tag for the given field. Tags are mandatory for oneof variants, but not for messages, where they can be automatically generated.