diff options
Diffstat (limited to 'src/enums.rs')
-rw-r--r-- | src/enums.rs | 377 |
1 files changed, 0 insertions, 377 deletions
diff --git a/src/enums.rs b/src/enums.rs deleted file mode 100644 index ec3444e..0000000 --- a/src/enums.rs +++ /dev/null @@ -1,377 +0,0 @@ -use std::collections::HashSet; - -use file_descriptor::file_descriptor_proto_expr; -use inside::protobuf_crate_path; -use protobuf::descriptor::*; -use protobuf_name::ProtobufAbsolutePath; -use rust_types_values::type_name_to_rust_relative; -use scope::EnumWithScope; -use scope::RootScope; -use scope::WithScope; -use serde; -use CodeWriter; - -use crate::customize::customize_from_rustproto_for_enum; -use crate::Customize; - -#[derive(Clone)] -pub struct EnumValueGen { - proto: EnumValueDescriptorProto, - enum_rust_name: String, - variant_rust_name: String, -} - -impl EnumValueGen { - fn parse( - proto: &EnumValueDescriptorProto, - enum_rust_name: &str, - variant_rust_name: &str, - ) -> EnumValueGen { - EnumValueGen { - proto: proto.clone(), - enum_rust_name: enum_rust_name.to_string(), - variant_rust_name: variant_rust_name.to_string(), - } - } - - // enum value - fn number(&self) -> i32 { - self.proto.get_number() - } - - // name of enum variant in generated rust code - fn rust_name_inner(&self) -> String { - self.variant_rust_name.clone() - } - - pub fn rust_name_outer(&self) -> String { - let mut r = String::new(); - r.push_str(&self.enum_rust_name); - r.push_str("::"); - r.push_str(&self.rust_name_inner()); - r - } -} - -pub(crate) struct EnumGen<'a> { - enum_with_scope: &'a EnumWithScope<'a>, - type_name: String, - lite_runtime: bool, - customize: Customize, -} - -impl<'a> EnumGen<'a> { - pub fn new( - enum_with_scope: &'a EnumWithScope<'a>, - current_file: &FileDescriptorProto, - customize: &Customize, - root_scope: &RootScope, - ) -> EnumGen<'a> { - let rust_name = if enum_with_scope.get_scope().get_file_descriptor().get_name() - == current_file.get_name() - { - // field type is a message or enum declared in the same file - enum_with_scope.rust_name().to_string() - } else { - type_name_to_rust_relative( - &ProtobufAbsolutePath::from(enum_with_scope.name_absolute()), - current_file, - false, - root_scope, - customize, - ) - .to_string() - }; - let lite_runtime = customize.lite_runtime.unwrap_or_else(|| { - enum_with_scope - .get_scope() - .get_file_descriptor() - .get_options() - .get_optimize_for() - == FileOptions_OptimizeMode::LITE_RUNTIME - }); - - let mut customize = customize.clone(); - customize.update_with(&customize_from_rustproto_for_enum( - enum_with_scope.en.options.as_ref().unwrap_or_default(), - )); - - EnumGen { - enum_with_scope, - type_name: rust_name, - lite_runtime, - customize, - } - } - - fn allow_alias(&self) -> bool { - self.enum_with_scope.en.get_options().get_allow_alias() - } - - fn values_all(&self) -> Vec<EnumValueGen> { - let mut r = Vec::new(); - for p in self.enum_with_scope.values() { - r.push(EnumValueGen::parse( - &p.proto, - &self.type_name, - p.rust_name().get(), - )); - } - r - } - - pub fn values_unique(&self) -> Vec<EnumValueGen> { - let mut used = HashSet::new(); - let mut r = Vec::new(); - for p in self.enum_with_scope.values() { - // skipping non-unique enums - // TODO: should support it - if !used.insert(p.proto.get_number()) { - continue; - } - r.push(EnumValueGen::parse( - p.proto, - &self.type_name, - p.rust_name().get(), - )); - } - r - } - - // find enum value by name - pub fn value_by_name(&'a self, name: &str) -> EnumValueGen { - let v = self.enum_with_scope.value_by_name(name); - EnumValueGen::parse(v.proto, &self.type_name, v.rust_name().get()) - } - - pub fn write(&self, w: &mut CodeWriter) { - self.write_struct(w); - if self.allow_alias() { - w.write_line(""); - self.write_impl_eq(w); - w.write_line(""); - self.write_impl_hash(w); - } - w.write_line(""); - self.write_impl_enum(w); - w.write_line(""); - self.write_impl_copy(w); - w.write_line(""); - self.write_impl_default(w); - w.write_line(""); - self.write_impl_value(w); - } - - fn write_struct(&self, w: &mut CodeWriter) { - let mut derive = Vec::new(); - derive.push("Clone"); - if !self.allow_alias() { - derive.push("PartialEq"); - } - derive.push("Eq"); - derive.push("Debug"); - if !self.allow_alias() { - derive.push("Hash"); - } else { - w.comment("Note: you cannot use pattern matching for enums with allow_alias option"); - } - w.derive(&derive); - serde::write_serde_attr( - w, - &self.customize, - "derive(::serde::Serialize, ::serde::Deserialize)", - ); - if let Some(ref ren) = self.customize.serde_rename_all { - let attr = format!("serde(rename_all = \"{}\")", ren); - serde::write_serde_attr(w, &self.customize, &attr); - } - let ref type_name = self.type_name; - w.expr_block(&format!("pub enum {}", type_name), |w| { - for value in self.values_all() { - if self.allow_alias() { - w.write_line(&format!( - "{}, // {}", - value.rust_name_inner(), - value.number() - )); - } else { - w.write_line(&format!( - "{} = {},", - value.rust_name_inner(), - value.number() - )); - } - } - }); - } - - fn write_fn_value(&self, w: &mut CodeWriter) { - w.def_fn("value(&self) -> i32", |w| { - if self.allow_alias() { - w.match_expr("*self", |w| { - for value in self.values_all() { - w.case_expr(value.rust_name_outer(), format!("{}", value.number())); - } - }); - } else { - w.write_line("*self as i32") - } - }); - } - - fn write_impl_enum(&self, w: &mut CodeWriter) { - let ref type_name = self.type_name; - w.impl_for_block( - &format!("{}::ProtobufEnum", protobuf_crate_path(&self.customize)), - &format!("{}", type_name), - |w| { - self.write_fn_value(w); - - w.write_line(""); - let ref type_name = self.type_name; - w.def_fn( - &format!( - "from_i32(value: i32) -> ::std::option::Option<{}>", - type_name - ), - |w| { - w.match_expr("value", |w| { - let values = self.values_unique(); - for value in values { - w.write_line(&format!( - "{} => ::std::option::Option::Some({}),", - value.number(), - value.rust_name_outer() - )); - } - w.write_line(&format!("_ => ::std::option::Option::None")); - }); - }, - ); - - w.write_line(""); - w.def_fn(&format!("values() -> &'static [Self]"), |w| { - w.write_line(&format!("static values: &'static [{}] = &[", type_name)); - w.indented(|w| { - for value in self.values_all() { - w.write_line(&format!("{},", value.rust_name_outer())); - } - }); - w.write_line("];"); - w.write_line("values"); - }); - - if !self.lite_runtime { - w.write_line(""); - w.def_fn( - &format!( - "enum_descriptor_static() -> &'static {}::reflect::EnumDescriptor", - protobuf_crate_path(&self.customize) - ), - |w| { - w.lazy_static_decl_get( - "descriptor", - &format!( - "{}::reflect::EnumDescriptor", - protobuf_crate_path(&self.customize) - ), - &self.customize, - |w| { - let ref type_name = self.type_name; - w.write_line(&format!( - "{}::reflect::EnumDescriptor::new_pb_name::<{}>(\"{}\", {})", - protobuf_crate_path(&self.customize), - type_name, - self.enum_with_scope.name_to_package(), - file_descriptor_proto_expr(&self.enum_with_scope.scope) - )); - }, - ); - }, - ); - } - }, - ); - } - - fn write_impl_value(&self, w: &mut CodeWriter) { - w.impl_for_block( - &format!( - "{}::reflect::ProtobufValue", - protobuf_crate_path(&self.customize) - ), - &format!("{}", self.type_name), - |w| { - w.def_fn( - &format!( - "as_ref(&self) -> {}::reflect::ReflectValueRef", - protobuf_crate_path(&self.customize) - ), - |w| { - w.write_line(&format!( - "{}::reflect::ReflectValueRef::Enum({}::ProtobufEnum::descriptor(self))", - protobuf_crate_path(&self.customize), - protobuf_crate_path(&self.customize) - )) - }, - ) - }, - ) - } - - fn write_impl_copy(&self, w: &mut CodeWriter) { - w.impl_for_block("::std::marker::Copy", &self.type_name, |_w| {}); - } - - fn write_impl_eq(&self, w: &mut CodeWriter) { - assert!(self.allow_alias()); - w.impl_for_block( - "::std::cmp::PartialEq", - &format!("{}", self.type_name), - |w| { - w.def_fn("eq(&self, other: &Self) -> bool", |w| { - w.write_line(&format!( - "{}::ProtobufEnum::value(self) == {}::ProtobufEnum::value(other)", - protobuf_crate_path(&self.customize), - protobuf_crate_path(&self.customize) - )); - }); - }, - ); - } - - fn write_impl_hash(&self, w: &mut CodeWriter) { - assert!(self.allow_alias()); - w.impl_for_block("::std::hash::Hash", &format!("{}", self.type_name), |w| { - w.def_fn("hash<H : ::std::hash::Hasher>(&self, state: &mut H)", |w| { - w.write_line(&format!( - "state.write_i32({}::ProtobufEnum::value(self))", - protobuf_crate_path(&self.customize) - )); - }); - }); - } - - fn write_impl_default(&self, w: &mut CodeWriter) { - let first_value = &self.enum_with_scope.values()[0]; - if first_value.proto.get_number() != 0 { - // This warning is emitted only for proto2 - // (because in proto3 first enum variant number is always 0). - // `Default` implemented unconditionally to simplify certain - // generic operations, e. g. reading a map. - // Also, note that even in proto2 some operations fallback to - // first enum value, e. g. `get_xxx` for unset field, - // so this implementation is not completely unreasonable. - w.comment("Note, `Default` is implemented although default value is not 0"); - } - w.impl_for_block("::std::default::Default", &self.type_name, |w| { - w.def_fn("default() -> Self", |w| { - w.write_line(&format!( - "{}::{}", - &self.type_name, - &first_value.rust_name() - )) - }); - }); - } -} |