diff --git a/prost-build/src/code_generator.rs b/prost-build/src/code_generator.rs index f4d8df9a5..69a80ed3c 100644 --- a/prost-build/src/code_generator.rs +++ b/prost-build/src/code_generator.rs @@ -700,6 +700,38 @@ impl<'a> CodeGenerator<'a> { self.push_indent(); self.buf.push_str("}\n"); // End of as_str_name() + self.push_indent(); + self.buf + .push_str("/// Creates an enum from field names used in the ProtoBuf definition.\n"); + + self.push_indent(); + self.buf + .push_str("pub fn from_str_name(value: &str) -> ::core::option::Option {\n"); + self.depth += 1; + + self.push_indent(); + self.buf.push_str("match value {\n"); + self.depth += 1; + + for variant in variant_mappings.iter() { + self.push_indent(); + self.buf.push_str("\""); + self.buf.push_str(variant.proto_name); + self.buf.push_str("\" => Some(Self::"); + self.buf.push_str(&variant.generated_variant_name); + self.buf.push_str("),\n"); + } + self.push_indent(); + self.buf.push_str("_ => None,\n"); + + self.depth -= 1; + self.push_indent(); + self.buf.push_str("}\n"); // End of match + + self.depth -= 1; + self.push_indent(); + self.buf.push_str("}\n"); // End of from_str_name() + self.path.pop(); self.depth -= 1; self.push_indent(); diff --git a/prost-types/src/compiler.rs b/prost-types/src/compiler.rs index 675ebb036..81cdcfa55 100644 --- a/prost-types/src/compiler.rs +++ b/prost-types/src/compiler.rs @@ -161,5 +161,13 @@ pub mod code_generator_response { Feature::Proto3Optional => "FEATURE_PROTO3_OPTIONAL", } } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "FEATURE_NONE" => Some(Self::None), + "FEATURE_PROTO3_OPTIONAL" => Some(Self::Proto3Optional), + _ => None, + } + } } } diff --git a/prost-types/src/protobuf.rs b/prost-types/src/protobuf.rs index 6bd39520c..0a05bbd66 100644 --- a/prost-types/src/protobuf.rs +++ b/prost-types/src/protobuf.rs @@ -253,6 +253,30 @@ pub mod field_descriptor_proto { Type::Sint64 => "TYPE_SINT64", } } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "TYPE_DOUBLE" => Some(Self::Double), + "TYPE_FLOAT" => Some(Self::Float), + "TYPE_INT64" => Some(Self::Int64), + "TYPE_UINT64" => Some(Self::Uint64), + "TYPE_INT32" => Some(Self::Int32), + "TYPE_FIXED64" => Some(Self::Fixed64), + "TYPE_FIXED32" => Some(Self::Fixed32), + "TYPE_BOOL" => Some(Self::Bool), + "TYPE_STRING" => Some(Self::String), + "TYPE_GROUP" => Some(Self::Group), + "TYPE_MESSAGE" => Some(Self::Message), + "TYPE_BYTES" => Some(Self::Bytes), + "TYPE_UINT32" => Some(Self::Uint32), + "TYPE_ENUM" => Some(Self::Enum), + "TYPE_SFIXED32" => Some(Self::Sfixed32), + "TYPE_SFIXED64" => Some(Self::Sfixed64), + "TYPE_SINT32" => Some(Self::Sint32), + "TYPE_SINT64" => Some(Self::Sint64), + _ => None, + } + } } #[derive( Clone, @@ -284,6 +308,15 @@ pub mod field_descriptor_proto { Label::Repeated => "LABEL_REPEATED", } } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "LABEL_OPTIONAL" => Some(Self::Optional), + "LABEL_REQUIRED" => Some(Self::Required), + "LABEL_REPEATED" => Some(Self::Repeated), + _ => None, + } + } } } /// Describes a oneof. @@ -561,6 +594,15 @@ pub mod file_options { OptimizeMode::LiteRuntime => "LITE_RUNTIME", } } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "SPEED" => Some(Self::Speed), + "CODE_SIZE" => Some(Self::CodeSize), + "LITE_RUNTIME" => Some(Self::LiteRuntime), + _ => None, + } + } } } #[allow(clippy::derive_partial_eq_without_eq)] @@ -737,6 +779,15 @@ pub mod field_options { CType::StringPiece => "STRING_PIECE", } } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "STRING" => Some(Self::String), + "CORD" => Some(Self::Cord), + "STRING_PIECE" => Some(Self::StringPiece), + _ => None, + } + } } #[derive( Clone, @@ -770,6 +821,15 @@ pub mod field_options { JsType::JsNumber => "JS_NUMBER", } } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "JS_NORMAL" => Some(Self::JsNormal), + "JS_STRING" => Some(Self::JsString), + "JS_NUMBER" => Some(Self::JsNumber), + _ => None, + } + } } } #[allow(clippy::derive_partial_eq_without_eq)] @@ -878,6 +938,15 @@ pub mod method_options { IdempotencyLevel::Idempotent => "IDEMPOTENT", } } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "IDEMPOTENCY_UNKNOWN" => Some(Self::IdempotencyUnknown), + "NO_SIDE_EFFECTS" => Some(Self::NoSideEffects), + "IDEMPOTENT" => Some(Self::Idempotent), + _ => None, + } + } } } /// A message representing a option the parser does not recognize. This only @@ -1384,6 +1453,31 @@ pub mod field { Kind::TypeSint64 => "TYPE_SINT64", } } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "TYPE_UNKNOWN" => Some(Self::TypeUnknown), + "TYPE_DOUBLE" => Some(Self::TypeDouble), + "TYPE_FLOAT" => Some(Self::TypeFloat), + "TYPE_INT64" => Some(Self::TypeInt64), + "TYPE_UINT64" => Some(Self::TypeUint64), + "TYPE_INT32" => Some(Self::TypeInt32), + "TYPE_FIXED64" => Some(Self::TypeFixed64), + "TYPE_FIXED32" => Some(Self::TypeFixed32), + "TYPE_BOOL" => Some(Self::TypeBool), + "TYPE_STRING" => Some(Self::TypeString), + "TYPE_GROUP" => Some(Self::TypeGroup), + "TYPE_MESSAGE" => Some(Self::TypeMessage), + "TYPE_BYTES" => Some(Self::TypeBytes), + "TYPE_UINT32" => Some(Self::TypeUint32), + "TYPE_ENUM" => Some(Self::TypeEnum), + "TYPE_SFIXED32" => Some(Self::TypeSfixed32), + "TYPE_SFIXED64" => Some(Self::TypeSfixed64), + "TYPE_SINT32" => Some(Self::TypeSint32), + "TYPE_SINT64" => Some(Self::TypeSint64), + _ => None, + } + } } /// Whether a field is optional, required, or repeated. #[derive( @@ -1421,6 +1515,16 @@ pub mod field { Cardinality::Repeated => "CARDINALITY_REPEATED", } } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "CARDINALITY_UNKNOWN" => Some(Self::Unknown), + "CARDINALITY_OPTIONAL" => Some(Self::Optional), + "CARDINALITY_REQUIRED" => Some(Self::Required), + "CARDINALITY_REPEATED" => Some(Self::Repeated), + _ => None, + } + } } } /// Enum type definition. @@ -1495,6 +1599,14 @@ impl Syntax { Syntax::Proto3 => "SYNTAX_PROTO3", } } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "SYNTAX_PROTO2" => Some(Self::Proto2), + "SYNTAX_PROTO3" => Some(Self::Proto3), + _ => None, + } + } } /// Api is a light-weight descriptor for an API Interface. /// @@ -2072,6 +2184,13 @@ impl NullValue { NullValue::NullValue => "NULL_VALUE", } } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "NULL_VALUE" => Some(Self::NullValue), + _ => None, + } + } } /// A Timestamp represents a point in time independent of any time zone or local /// calendar, encoded as a count of seconds and fractions of seconds at diff --git a/tests/src/lib.rs b/tests/src/lib.rs index a9818d682..65d393c36 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -550,6 +550,34 @@ mod tests { ); } + #[test] + fn test_enum_from_string() { + use default_enum_value::{ERemoteClientBroadcastMsg, PrivacyLevel}; + + assert_eq!( + Some(PrivacyLevel::One), + PrivacyLevel::from_str_name("PRIVACY_LEVEL_ONE") + ); + assert_eq!( + Some(PrivacyLevel::Two), + PrivacyLevel::from_str_name("PRIVACY_LEVEL_TWO") + ); + assert_eq!( + Some(PrivacyLevel::PrivacyLevelThree), + PrivacyLevel::from_str_name("PRIVACY_LEVEL_PRIVACY_LEVEL_THREE") + ); + assert_eq!( + Some(PrivacyLevel::PrivacyLevelprivacyLevelFour), + PrivacyLevel::from_str_name("PRIVACY_LEVELPRIVACY_LEVEL_FOUR") + ); + assert_eq!(None, PrivacyLevel::from_str_name("PRIVACY_LEVEL_FIVE")); + + assert_eq!( + Some(ERemoteClientBroadcastMsg::KERemoteClientBroadcastMsgDiscovery), + ERemoteClientBroadcastMsg::from_str_name("k_ERemoteClientBroadcastMsgDiscovery") + ); + } + #[test] fn test_default_string_escape() { let msg = default_string_escape::Person::default();