#[proto_message]Expand description
Implements protobuf schema and validation features for a rust struct.
This macro will implement the following:
- Clone
- PartialEq
prost::MessageProtoMessageAsProtoTypeMessagePathValidatedMessageCelValue(if thecelfeature 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 thecheck_validatorsmethod and panics on failure. - A test that checks if the oneof tags used in this message (if there are any) are correct.
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
Protosuffix will be generated (i.e. MyMsg -> MyMsgProto) and these traits and methods will target that. An impl forProxiedMessagewill also be generated. - The proxy will implement
MessageProxy.
To learn more about proxied implementations, visit the dedicated section.
§Examples
use protify::*;
proto_package!(MY_PKG, name = "my_pkg");
define_proto_file!(MY_FILE, name = "my_file.proto", package = MY_PKG);
#[proto_message]
pub struct Msg {
pub id: i32,
}
// Generates the `ProxiedMsgProto` struct
#[proto_message(proxied)]
pub struct ProxiedMsg {
pub id: i32,
}
fn main() {
// `MessageProxy` and `ProxiedMessage` methods
let msg = ProxiedMsgProto::default();
let proxy = msg.into_proxy();
let msg_again = proxy.into_message();
}§Macro attributes
proxied- Type: Ident
- Example:
#[proto_message(proxied)] - Description: Creates a proxied message
§Container attributes:
-
file- Type: Ident
- Example:
#[proto(file = MY_FILE)] - Description:
Assigns a specific file to this item. By default, the
module_pathwill be inherited from the target file, and can be overridden with themodule_pathattribute. For more info about how to manage proto files, visit the dedicated section.
-
module_path- Type: literal string or
module_path! - Example:
#[proto(module_path = core::module_path!())]or#[proto(module_path = "module::path")] - Description:
Overrides the
module_pathfor this item, which is otherwise inherited by the assigned proto file. For more info about how to manage proto files, visit the dedicated section.
- Type: literal string or
-
derive- Type: list of Paths
- Example:
#[proto(derive(Copy))] - Description:
In case of a proxied impl, it specifies derives to apply to the Proto message.
Shorthand for
#[proto(attr(derive(..)))]
-
attr- Type: MetaList
- Example:
#[proto(attr(serde(default)))] - Description:
Forwards the given metas to the proto struct.
In the example above, the proto struct would receive the attribute as
#[serde(default)].
-
reserved_numbers- Type: list of individual numbers or closed ranges
- Example:
#[proto(reserved_numbers(1, 2..10, 5000..MAX))] - Description:
Specifies the reserved numbers for the given message. These will be skipped when automatically generating tags for each field, and copied as such in the proto files output. In order to reserve up to the maximum tag range, use the
MAXident as shown above.
-
reserved_names- Type: list of strings
- Example:
#[proto(reserved_names("abc", "deg"))] - Description: Specifies the reserved names for the given message
-
options- Type: Expr
- Example:
#[proto(options = vec![ my_option_1() ])] - Description:
Specifies the options for the given message. It must resolve to an implementor of IntoIterator<Item =
ProtoOption>.
-
name- Type: string
- Example:
#[proto(name = "abc")] - Description: Specifies the name of the message. Overrides the default behaviour, which uses the name of the struct.
-
parent_message- Type: Ident
- Example:
#[proto(parent_message = MyMsg)] - Description: Specifies the parent message of a nested message.
-
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.
-
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 struct but not the proto message, you can use
#[deprecated]along with#[proto(deprecated = false)]. Vice versa, you can deprecate the proto message 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 default validators for the given message. These will be executed inside the message’s own
validatemethod, and whenever the message is used as a field in another message, along with the validators defined for each field. If a closure if used, the defaultCelValidatorbuilder will be passed as the argument, and the validator will be cached in a static Lazy. If another expression is used, it must resolve to an implementor ofValidatorfor the message.
-
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. Thecheck_validatorswill still be generated and be available for manual testing.
§Field 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 theProtosuffix and not the proxy itself. Only available for proxied impls. -default: allows the message to be used without being wrapped inOption. In this case, the default conversion from proto for the field will useDefault::default()if the field isNonein 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
nameattribute 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 theProtosuffix and not the proxy itself. Only available for proxied impls.default: allows the oneof to be used without being wrapped inOption. In this case, the default conversion from proto for the field will use [Default::default()] if the field isNonein 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, andNameOfOneofProto::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
validatemethod. 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 theOneofValidator). If another expression is used, it must resolve to an implementor ofValidatorfor 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.