mod accessor; pub(crate) mod elem; mod option_kind; mod repeated; mod singular; mod tag; pub(crate) mod type_ext; use protobuf::descriptor::field_descriptor_proto::Type; use protobuf::descriptor::*; use protobuf::reflect::ReflectValueRef; use protobuf::reflect::RuntimeFieldType; use protobuf::reflect::Syntax; use protobuf::rt; use protobuf::rt::WireType; use protobuf_parse::camel_case; use protobuf_parse::ProtobufAbsPath; use crate::customize::ctx::CustomizeElemCtx; use crate::customize::rustproto_proto::customize_from_rustproto_for_field; use crate::customize::Customize; use crate::gen::code_writer::CodeWriter; use crate::gen::code_writer::Visibility; use crate::gen::field::elem::field_elem; use crate::gen::field::elem::FieldElem; use crate::gen::field::elem::FieldElemEnum; use crate::gen::field::elem::HowToGetMessageSize; use crate::gen::field::option_kind::OptionKind; use crate::gen::field::repeated::RepeatedField; use crate::gen::field::singular::SingularField; use crate::gen::field::singular::SingularFieldFlag; use crate::gen::field::tag::make_tag; use crate::gen::field::type_ext::TypeExt; use crate::gen::file_and_mod::FileAndMod; use crate::gen::inside::protobuf_crate_path; use crate::gen::map::map_entry; use crate::gen::oneof::OneofField; use crate::gen::protoc_insertion_point::write_protoc_insertion_point_for_field; use crate::gen::rust::ident::RustIdent; use crate::gen::rust::quote::quote_escape_bytes; use crate::gen::rust::quote::quote_escape_str; use crate::gen::rust::snippets::EXPR_NONE; use crate::gen::rust_types_values::PrimitiveTypeVariant; use crate::gen::rust_types_values::RustType; use crate::gen::rust_types_values::RustValueTyped; use crate::gen::scope::FieldWithContext; use crate::gen::scope::MessageWithScope; use crate::gen::scope::RootScope; fn field_type_protobuf_name<'a>(field: &'a FieldDescriptorProto) -> &'a str { if field.has_type_name() { field.type_name() } else { field.type_().protobuf_name() } } #[derive(Clone)] pub struct MapField<'a> { _message: MessageWithScope<'a>, key: FieldElem<'a>, value: FieldElem<'a>, } #[derive(Clone)] pub(crate) enum FieldKind<'a> { // optional or required Singular(SingularField<'a>), // repeated except map Repeated(RepeatedField<'a>), // map Map(MapField<'a>), // part of oneof Oneof(OneofField<'a>), } impl<'a> FieldKind<'a> { pub(crate) fn default( &self, customize: &Customize, reference: &FileAndMod, const_expr: bool, ) -> String { match self { FieldKind::Singular(s) => s.default_value(customize, reference, const_expr), FieldKind::Repeated(r) => r.default(), FieldKind::Oneof(..) => EXPR_NONE.to_owned(), FieldKind::Map(..) => panic!("map fields cannot have field value"), } } } #[derive(Clone)] pub(crate) enum SingularOrOneofField<'a> { Singular(SingularField<'a>), Oneof(OneofField<'a>), } impl<'a> SingularOrOneofField<'a> { fn elem(&self) -> &FieldElem { match self { SingularOrOneofField::Singular(SingularField { ref elem, .. }) => elem, SingularOrOneofField::Oneof(OneofField { ref elem, .. }) => elem, } } // Type of `xxx` function for singular type. pub(crate) fn getter_return_type(&self, reference: &FileAndMod) -> RustType { let elem = self.elem(); if let FieldElem::Enum(ref en) = elem { en.enum_rust_type(reference) } else if elem.is_copy() { elem.rust_storage_elem_type(reference) } else { elem.rust_storage_elem_type(reference).ref_type() } } } // Representation of map entry: key type and value type #[derive(Clone, Debug)] pub struct EntryKeyValue<'a>(FieldElem<'a>, FieldElem<'a>); #[derive(Clone)] pub(crate) struct FieldGen<'a> { syntax: Syntax, pub proto_field: FieldWithContext<'a>, // field name in generated code pub rust_name: RustIdent, pub proto_type: Type, wire_type: WireType, pub kind: FieldKind<'a>, pub generate_accessors: bool, pub generate_getter: bool, customize: Customize, path: Vec, info: Option<&'a SourceCodeInfo>, } impl<'a> FieldGen<'a> { pub(crate) fn parse( field: FieldWithContext<'a>, root_scope: &'a RootScope<'a>, parent_customize: &CustomizeElemCtx<'a>, path: Vec, info: Option<&'a SourceCodeInfo>, ) -> anyhow::Result> { let customize = parent_customize .child( &customize_from_rustproto_for_field(field.field.proto().options.get_or_default()), &field.field, ) .for_elem; let syntax = field.message.scope.file_scope.syntax(); let field_may_have_custom_default_value = syntax == Syntax::Proto2 && field.field.proto().label() != field_descriptor_proto::Label::LABEL_REPEATED && field.field.proto().type_() != Type::TYPE_MESSAGE; let generate_accessors = customize .generate_accessors .unwrap_or(field_may_have_custom_default_value) || field.is_oneof(); let default_generate_getter = generate_accessors || field_may_have_custom_default_value; let generate_getter = customize.generate_getter.unwrap_or(default_generate_getter) || field.is_oneof(); let kind = match field.field.runtime_field_type() { RuntimeFieldType::Map(..) => { let message = root_scope .find_message(&ProtobufAbsPath::from(field.field.proto().type_name())); let (key, value) = map_entry(&message).unwrap(); let key = field_elem(&key, root_scope, &customize); let value = field_elem(&value, root_scope, &customize); FieldKind::Map(MapField { _message: message, key, value, }) } RuntimeFieldType::Repeated(..) => { let elem = field_elem(&field, root_scope, &customize); FieldKind::Repeated(RepeatedField { elem, packed: field.field.proto().options.get_or_default().packed(), }) } RuntimeFieldType::Singular(..) => { let elem = field_elem(&field, root_scope, &customize); if let Some(oneof) = field.oneof() { FieldKind::Oneof(OneofField::parse(&oneof, &field.field, elem, root_scope)) } else { let flag = if field.message.scope.file_scope.syntax() == Syntax::Proto3 && field.field.proto().type_() != field_descriptor_proto::Type::TYPE_MESSAGE && !field.field.proto().proto3_optional() { SingularFieldFlag::WithoutFlag } else { let required = field.field.proto().label() == field_descriptor_proto::Label::LABEL_REQUIRED; let option_kind = match field.field.proto().type_() { field_descriptor_proto::Type::TYPE_MESSAGE => OptionKind::MessageField, _ => OptionKind::Option, }; SingularFieldFlag::WithFlag { required, option_kind, } }; FieldKind::Singular(SingularField { elem, flag }) } } }; Ok(FieldGen { syntax: field.message.message.file_descriptor().syntax(), rust_name: rust_field_name_for_protobuf_field_name(&field.field.name()), proto_type: field.field.proto().type_(), wire_type: WireType::for_type(field.field.proto().type_()), proto_field: field, kind, generate_accessors, generate_getter, customize, path, info, }) } // for message level fn file_and_mod(&self) -> FileAndMod { self.proto_field .message .scope .file_and_mod(self.customize.clone()) } fn tag_size(&self) -> u32 { rt::tag_size(self.proto_field.number() as u32) as u32 } fn is_singular(&self) -> bool { match self.kind { FieldKind::Singular(..) => true, _ => false, } } fn is_repeated_packed(&self) -> bool { match self.kind { FieldKind::Repeated(RepeatedField { packed: true, .. }) => true, _ => false, } } pub(crate) fn elem(&self) -> &FieldElem { match self.kind { FieldKind::Singular(SingularField { ref elem, .. }) => &elem, FieldKind::Repeated(RepeatedField { ref elem, .. }) => &elem, FieldKind::Oneof(OneofField { ref elem, .. }) => &elem, FieldKind::Map(..) => unreachable!(), } } // type of field in struct pub(crate) fn full_storage_type(&self, reference: &FileAndMod) -> RustType { match self.kind { FieldKind::Repeated(ref repeated) => repeated.rust_type(reference), FieldKind::Map(MapField { ref key, ref value, .. }) => RustType::HashMap( Box::new(key.rust_storage_elem_type(reference)), Box::new(value.rust_storage_elem_type(reference)), ), FieldKind::Singular(ref singular) => singular.rust_storage_type(reference), FieldKind::Oneof(..) => unreachable!(), } } // type of `v` in `for v in field` fn full_storage_iter_elem_type(&self, reference: &FileAndMod) -> RustType { if let FieldKind::Oneof(ref oneof) = self.kind { oneof.elem.rust_storage_elem_type(reference) } else { self.full_storage_type(reference).iter_elem_type() } } // suffix `xxx` as in `os.write_xxx_no_tag(..)` fn os_write_fn_suffix(&self) -> &str { self.proto_type.protobuf_name() } fn os_write_fn_suffix_with_unknown_for_enum(&self) -> &str { if self.proto_type == field_descriptor_proto::Type::TYPE_ENUM { "enum_or_unknown" } else { self.os_write_fn_suffix() } } // for field `foo`, type of param of `fn set_foo(..)` fn set_xxx_param_type(&self, reference: &FileAndMod) -> RustType { match self.kind { FieldKind::Singular(SingularField { ref elem, .. }) | FieldKind::Oneof(OneofField { ref elem, .. }) => { elem.rust_set_xxx_param_type(reference) } FieldKind::Repeated(..) | FieldKind::Map(..) => self.full_storage_type(reference), } } // for field `foo`, return type if `fn take_foo(..)` fn take_xxx_return_type(&self, reference: &FileAndMod) -> RustType { self.set_xxx_param_type(reference) } // for field `foo`, return type of `fn mut_foo(..)` fn mut_xxx_return_type(&self, reference: &FileAndMod) -> RustType { RustType::Ref(Box::new(match self.kind { FieldKind::Singular(SingularField { ref elem, .. }) | FieldKind::Oneof(OneofField { ref elem, .. }) => { elem.rust_storage_elem_type(reference) } FieldKind::Repeated(..) | FieldKind::Map(..) => self.full_storage_type(reference), })) } // for field `foo`, return type of `fn foo(..)` fn getter_return_type(&self) -> RustType { let reference = self .proto_field .message .scope .file_and_mod(self.customize.clone()); match &self.kind { FieldKind::Singular(s) => { SingularOrOneofField::Singular(s.clone()).getter_return_type(&reference) } FieldKind::Oneof(o) => { SingularOrOneofField::Oneof(o.clone()).getter_return_type(&reference) } FieldKind::Repeated(RepeatedField { ref elem, .. }) => RustType::Ref(Box::new( RustType::Slice(Box::new(elem.rust_storage_elem_type(&reference))), )), FieldKind::Map(..) => RustType::Ref(Box::new(self.full_storage_type(&reference))), } } // elem data is not stored in heap pub(crate) fn elem_type_is_copy(&self) -> bool { self.proto_type.is_copy() } fn defaut_value_from_proto_float(f: f64, type_name: &str) -> String { if f.is_nan() { format!("::std::{}::NAN", type_name) } else if f.is_infinite() { if f > 0.0 { format!("::std::{}::INFINITY", type_name) } else { format!("::std::{}::NEG_INFINITY", type_name) } } else { format!("{:?}{}", f, type_name) } } fn singular_or_oneof_default_value_from_proto(&self, elem: &FieldElem) -> Option { if !self.proto_field.field.proto().has_default_value() { return None; } let default_value = self.proto_field.field.singular_default_value(); Some(match default_value { ReflectValueRef::Bool(b) => format!("{}", b), ReflectValueRef::I32(v) => format!("{}i32", v), ReflectValueRef::I64(v) => format!("{}i64", v), ReflectValueRef::U32(v) => format!("{}u32", v), ReflectValueRef::U64(v) => format!("{}u64", v), ReflectValueRef::String(v) => quote_escape_str(v), ReflectValueRef::Bytes(v) => quote_escape_bytes(v), ReflectValueRef::F32(v) => Self::defaut_value_from_proto_float(v as f64, "f32"), ReflectValueRef::F64(v) => Self::defaut_value_from_proto_float(v as f64, "f64"), ReflectValueRef::Enum(_e, _v) => { if let &FieldElem::Enum(ref e) = elem { format!("{}", e.default_value_rust_expr(&self.file_and_mod())) } else { unreachable!() } } t => panic!("default value is not implemented for type: {:?}", t), }) } fn default_value_from_proto(&self) -> Option { match self.kind { FieldKind::Oneof(OneofField { ref elem, .. }) | FieldKind::Singular(SingularField { ref elem, .. }) => { self.singular_or_oneof_default_value_from_proto(elem) } _ => unreachable!(), } } fn default_value_from_proto_typed(&self) -> Option { self.default_value_from_proto().map(|v| { let default_value_type = match self.proto_type { field_descriptor_proto::Type::TYPE_STRING => RustType::Ref(Box::new(RustType::Str)), field_descriptor_proto::Type::TYPE_BYTES => { RustType::Ref(Box::new(RustType::Slice(Box::new(RustType::u8())))) } _ => self.full_storage_iter_elem_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ), }; RustValueTyped { value: v, rust_type: default_value_type, } }) } // default value to be returned from `fn xxx` for field `xxx`. fn xxx_default_value_rust(&self) -> String { match self.kind { FieldKind::Singular(..) | FieldKind::Oneof(..) => { self.default_value_from_proto().unwrap_or_else(|| { self.getter_return_type() .default_value(&self.customize, false) }) } _ => unreachable!(), } } // default to be assigned to field fn element_default_value_rust(&self) -> RustValueTyped { match self.kind { FieldKind::Singular(..) | FieldKind::Oneof(..) => { self.default_value_from_proto_typed().unwrap_or_else(|| { self.elem() .rust_storage_elem_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ) .default_value_typed(&self.customize, false) }) } _ => unreachable!(), } } pub(crate) fn reconstruct_def(&self) -> String { let prefix = match (self.proto_field.field.proto().label(), self.syntax) { (field_descriptor_proto::Label::LABEL_REPEATED, _) => "repeated ", (_, Syntax::Proto3) => "", (field_descriptor_proto::Label::LABEL_OPTIONAL, _) => "optional ", (field_descriptor_proto::Label::LABEL_REQUIRED, _) => "required ", }; format!( "{}{} {} = {}", prefix, field_type_protobuf_name(self.proto_field.field.proto()), self.proto_field.name(), self.proto_field.number() ) } pub(crate) fn write_clear(&self, w: &mut CodeWriter) { match self.kind { FieldKind::Oneof(ref o) => { w.write_line(&format!( "self.{} = ::std::option::Option::None;", o.oneof_field_name )); } _ => { let clear_expr = self .full_storage_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ) .clear(&self.self_field(), &self.customize); w.write_line(&format!("{};", clear_expr)); } } } // output code that writes single element to stream pub(crate) fn write_write_element( &self, elem: &FieldElem, w: &mut CodeWriter, os: &str, v: &RustValueTyped, ) { assert!(!self.is_repeated_packed()); elem.write_write_element( self.proto_field.number() as u32, v, &self.file_and_mod(), &self.customize, os, w, ); } fn self_field(&self) -> String { format!("self.{}", self.rust_name) } fn self_field_is_some(&self) -> String { assert!(self.is_singular()); format!("{}.is_some()", self.self_field()) } fn self_field_is_none(&self) -> String { assert!(self.is_singular()); format!("{}.is_none()", self.self_field()) } // field data viewed as Option fn self_field_as_option(&self, elem: &FieldElem, option_kind: OptionKind) -> RustValueTyped { match self.full_storage_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ) { RustType::Option(ref e) if e.is_copy() => { return RustType::Option(e.clone()).value(self.self_field()); } _ => {} }; let as_option_type = option_kind.as_ref_type( elem.rust_storage_elem_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ), ); as_option_type.value(format!("{}.as_ref()", self.self_field())) } pub(crate) fn write_struct_field(&self, w: &mut CodeWriter) { if self.proto_type == field_descriptor_proto::Type::TYPE_GROUP { w.comment(&format!("{}: ", &self.rust_name)); } else { w.all_documentation(self.info, &self.path); write_protoc_insertion_point_for_field(w, &self.customize, &self.proto_field.field); w.field_decl_vis( Visibility::Public, &self.rust_name.to_string(), &self .full_storage_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ) .to_code(&self.customize), ); } } fn write_if_let_self_field_is_some(&self, s: &SingularField, w: &mut CodeWriter, cb: F) where F: Fn(&RustValueTyped, &mut CodeWriter), { match s { SingularField { flag: SingularFieldFlag::WithFlag { option_kind, .. }, ref elem, } => { let var = "v"; let ref_prefix = match elem .rust_storage_elem_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ) .is_copy() { true => "", false => "", }; let as_option = self.self_field_as_option(elem, *option_kind); w.if_let_stmt( &format!("Some({}{})", ref_prefix, var), &as_option.value, |w| { let v = RustValueTyped { value: var.to_owned(), rust_type: as_option.rust_type.elem_type(), }; cb(&v, w); }, ); } SingularField { flag: SingularFieldFlag::WithoutFlag, ref elem, } => match *elem { FieldElem::Primitive(field_descriptor_proto::Type::TYPE_STRING, ..) | FieldElem::Primitive(field_descriptor_proto::Type::TYPE_BYTES, ..) => { w.if_stmt(format!("!{}.is_empty()", self.self_field()), |w| { let v = RustValueTyped { value: self.self_field(), rust_type: self.full_storage_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ), }; cb(&v, w); }); } _ => { w.if_stmt( format!( "{} != {}", self.self_field(), self.full_storage_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()) ) .default_value(&self.customize, false) ), |w| { let v = RustValueTyped { value: self.self_field(), rust_type: self.full_storage_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ), }; cb(&v, w); }, ); } }, } } pub(crate) fn write_if_self_field_is_none(&self, w: &mut CodeWriter, cb: F) where F: Fn(&mut CodeWriter), { let self_field_is_none = self.self_field_is_none(); w.if_stmt(self_field_is_none, cb) } // repeated or singular pub(crate) fn write_for_self_field(&self, w: &mut CodeWriter, varn: &str, cb: F) where F: Fn(&mut CodeWriter, &RustType), { let file_and_mod = self .proto_field .message .scope .file_and_mod(self.customize.clone()); match &self.kind { FieldKind::Oneof(oneof_field) => { let cond = format!( "Some({}(ref {}))", oneof_field.variant_path(&file_and_mod.relative_mod), varn ); w.if_let_stmt( &cond, &format!("self.{}", oneof_field.oneof_field_name), |w| cb(w, &oneof_field.elem.rust_storage_elem_type(&file_and_mod)), ) } _ => { let v_type = self.full_storage_iter_elem_type(&file_and_mod); let self_field = self.self_field(); w.for_stmt(&format!("&{}", self_field), varn, |w| cb(w, &v_type)); } } } fn write_self_field_assign(&self, w: &mut CodeWriter, value: &str) { let self_field = self.self_field(); w.write_line(&format!("{} = {};", self_field, value)); } fn write_self_field_assign_some(&self, w: &mut CodeWriter, s: &SingularField, value: &str) { match s { &SingularField { flag: SingularFieldFlag::WithFlag { option_kind, .. }, .. } => { self.write_self_field_assign(w, &option_kind.wrap_value(value, &self.customize)); } &SingularField { flag: SingularFieldFlag::WithoutFlag, .. } => { self.write_self_field_assign(w, value); } } } fn write_self_field_assign_value_singular( &self, w: &mut CodeWriter, s: &SingularField, value: &RustValueTyped, ) { let SingularField { ref elem, ref flag } = s; let converted = value.into_type( elem.rust_storage_elem_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ) .clone(), &self.customize, ); let wrapped = match flag { SingularFieldFlag::WithoutFlag => converted.value, SingularFieldFlag::WithFlag { option_kind, .. } => { option_kind.wrap_value(&converted.value, &self.customize) } }; self.write_self_field_assign(w, &wrapped); } fn write_self_field_assign_value(&self, w: &mut CodeWriter, value: &RustValueTyped) { match self.kind { FieldKind::Repeated(..) | FieldKind::Map(..) => { let converted = value.into_type( self.full_storage_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ), &self.customize, ); self.write_self_field_assign(w, &converted.value); } FieldKind::Singular(ref s) => { self.write_self_field_assign_value_singular(w, s, value); } FieldKind::Oneof(..) => unreachable!(), } } fn write_self_field_assign_default( &self, field_kind: &SingularOrOneofField, w: &mut CodeWriter, ) { match field_kind { SingularOrOneofField::Oneof(oneof) => { w.write_line(format!( "self.{} = ::std::option::Option::Some({}({}))", oneof.oneof_field_name, oneof.variant_path(&self.proto_field.message.scope.rust_path_to_file()), // TODO: default from .proto is not needed here (?) self.element_default_value_rust() .into_type( self.full_storage_iter_elem_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()) ), &self.customize ) .value )); } SingularOrOneofField::Singular(singular) => { // Note it is different from C++ protobuf, where field is initialized // with default value match singular.flag { SingularFieldFlag::WithFlag { option_kind, .. } => match option_kind { OptionKind::MessageField => { let self_field = self.self_field(); w.write_line(&format!("{}.set_default();", self_field)); } _ => { self.write_self_field_assign_some( w, singular, &self .elem() .rust_storage_elem_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ) .default_value_typed(&self.customize, false) .into_type( singular.elem.rust_storage_elem_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ), &self.customize, ) .value, ); } }, SingularFieldFlag::WithoutFlag => unimplemented!(), } } } } fn self_field_vec_packed_size(&self) -> String { let fn_name = match self.proto_type { Type::TYPE_ENUM => "vec_packed_enum_or_unknown_size", Type::TYPE_SINT32 => "vec_packed_sint32_size", Type::TYPE_SINT64 => "vec_packed_sint64_size", Type::TYPE_INT32 => "vec_packed_int32_size", Type::TYPE_INT64 => "vec_packed_int64_size", Type::TYPE_UINT32 => "vec_packed_uint32_size", Type::TYPE_UINT64 => "vec_packed_uint64_size", Type::TYPE_BOOL => "vec_packed_bool_size", Type::TYPE_FIXED32 => "vec_packed_fixed32_size", Type::TYPE_FIXED64 => "vec_packed_fixed64_size", Type::TYPE_SFIXED32 => "vec_packed_sfixed32_size", Type::TYPE_SFIXED64 => "vec_packed_sfixed64_size", Type::TYPE_FLOAT => "vec_packed_float_size", Type::TYPE_DOUBLE => "vec_packed_double_size", t => unreachable!("{:?}", t), }; format!( "{}::rt::{fn_name}({}, &{})", protobuf_crate_path(&self.customize), self.proto_field.number(), self.self_field() ) } pub(crate) fn clear_field_func(&self) -> String { format!("clear_{}", self.rust_name) } fn write_merge_from_field_message_string_bytes_repeated( &self, r: &RepeatedField, w: &mut CodeWriter, ) { let read_fn = match &r.elem { FieldElem::Message(..) => "read_message", FieldElem::Primitive(Type::TYPE_STRING, PrimitiveTypeVariant::Default) => "read_string", FieldElem::Primitive(Type::TYPE_STRING, PrimitiveTypeVariant::TokioBytes) => { "read_tokio_chars" } FieldElem::Primitive(Type::TYPE_BYTES, PrimitiveTypeVariant::Default) => "read_bytes", FieldElem::Primitive(Type::TYPE_BYTES, PrimitiveTypeVariant::TokioBytes) => { "read_tokio_bytes" } _ => unreachable!("for field {}", self.proto_field.field), }; w.write_line(&format!("self.{}.push(is.{}()?);", self.rust_name, read_fn,)); } fn tag_with_wire_type(&self, wire_type: WireType) -> u32 { make_tag(self.proto_field.number() as u32, wire_type) } fn tag(&self) -> u32 { self.tag_with_wire_type(self.wire_type) } // Write `merge_from` part for this oneof field fn write_merge_from_oneof_case_block(&self, o: &OneofField, w: &mut CodeWriter) { w.case_block(&format!("{}", self.tag()), |w| { let typed = RustValueTyped { value: format!( "{}?", self.proto_type.read("is", o.elem.primitive_type_variant()) ), rust_type: self.full_storage_iter_elem_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ), }; let maybe_boxed = if o.boxed { typed.boxed(&self.customize) } else { typed }; w.write_line(&format!( "self.{} = ::std::option::Option::Some({}({}));", o.oneof_field_name, o.variant_path(&self.proto_field.message.scope.rust_path_to_file()), maybe_boxed.value )); }) } // Write `merge_from` part for this map field fn write_merge_from_map_case_block(&self, map: &MapField, w: &mut CodeWriter) { let MapField { key, value, .. } = map; w.case_block(&format!("{}", self.tag()), |w| { w.write_line(&format!("let len = is.read_raw_varint32()?;",)); w.write_line(&format!("let old_limit = is.push_limit(len as u64)?;")); w.write_line(&format!( "let mut key = ::std::default::Default::default();" )); w.write_line(&format!( "let mut value = ::std::default::Default::default();" )); w.while_block("let Some(tag) = is.read_raw_tag_or_eof()?", |w| { w.match_block("tag", |w| { let key_tag = make_tag(1, WireType::for_type(key.proto_type())); let value_tag = make_tag(2, WireType::for_type(value.proto_type())); w.case_expr( &format!("{key_tag}"), &format!("key = {read}", read = key.read_one_liner()), ); w.case_expr( &format!("{value_tag}"), &format!("value = {read}", read = value.read_one_liner()), ); w.case_expr( "_", &format!( "{protobuf_crate}::rt::skip_field_for_tag(tag, is)?", protobuf_crate = protobuf_crate_path(&self.customize) ), ); }); }); w.write_line(&format!("is.pop_limit(old_limit);")); w.write_line(&format!( "{field}.insert(key, value);", field = self.self_field() )); }); } // Write `merge_from` part for this singular field fn write_merge_from_singular_case_block(&self, s: &SingularField, w: &mut CodeWriter) { w.case_block(&format!("{}", self.tag()), |w| match s.elem { FieldElem::Message(..) => { w.write_line(&format!( "{}::rt::read_singular_message_into_field(is, &mut self.{})?;", protobuf_crate_path(&self.customize), self.rust_name, )); } _ => { let read_proc = s.elem.read_one_liner(); self.write_self_field_assign_some(w, s, &read_proc); } }) } // Write `merge_from` part for this repeated field fn write_merge_from_repeated_case_block(&self, w: &mut CodeWriter) { let field = match self.kind { FieldKind::Repeated(ref field) => field, _ => panic!(), }; match field.elem { FieldElem::Message(..) | FieldElem::Primitive(field_descriptor_proto::Type::TYPE_STRING, ..) | FieldElem::Primitive(field_descriptor_proto::Type::TYPE_BYTES, ..) => { w.case_block(&format!("{}", self.tag()), |w| { self.write_merge_from_field_message_string_bytes_repeated(field, w); }) } FieldElem::Enum(..) => { w.case_block( &format!("{}", self.tag_with_wire_type(WireType::Varint)), |w| { w.write_line(&format!( "self.{}.push(is.read_enum_or_unknown()?);", self.rust_name, )); }, ); w.case_block( &format!("{}", self.tag_with_wire_type(WireType::LengthDelimited)), |w| { w.write_line(&format!( "{}::rt::read_repeated_packed_enum_or_unknown_into(is, &mut self.{})?", protobuf_crate_path(&self.customize), self.rust_name, )); }, ); } _ => { assert_ne!(self.wire_type, WireType::LengthDelimited); w.case_block( &format!("{}", self.tag_with_wire_type(WireType::LengthDelimited)), |w| { w.write_line(&format!( "is.read_repeated_packed_{}_into(&mut self.{})?;", self.proto_type.protobuf_name(), self.rust_name )); }, ); w.case_block(&format!("{}", self.tag()), |w| { w.write_line(&format!( "self.{}.push(is.read_{}()?);", self.rust_name, self.proto_type.protobuf_name(), )); }); } } } /// Write `merge_from` part for this field pub(crate) fn write_merge_from_field_case_block(&self, w: &mut CodeWriter) { match &self.kind { FieldKind::Oneof(oneof) => self.write_merge_from_oneof_case_block(oneof, w), FieldKind::Map(map) => self.write_merge_from_map_case_block(map, w), FieldKind::Singular(ref s) => self.write_merge_from_singular_case_block(s, w), FieldKind::Repeated(..) => self.write_merge_from_repeated_case_block(w), } } pub(crate) fn write_element_size( &self, elem: &FieldElem, w: &mut CodeWriter, item_var: &RustValueTyped, sum_var: &str, ) { assert!(!self.is_repeated_packed()); elem.write_element_size( self.proto_field.number() as u32, item_var, HowToGetMessageSize::Compute, sum_var, &self.customize, w, ); } fn write_write_map_field( &self, key: &FieldElem, value: &FieldElem, os: &str, w: &mut CodeWriter, ) { self.for_each_map_entry(key, value, w, |k, v, w| { w.write_line("let mut entry_size = 0;"); key.write_element_size( 1, k, HowToGetMessageSize::GetCached, "entry_size", &self.customize, w, ); value.write_element_size( 2, v, HowToGetMessageSize::GetCached, "entry_size", &self.customize, w, ); w.write_line(&format!( "{os}.write_raw_varint32({tag})?; // Tag.", tag = make_tag(self.proto_field.number() as u32, WireType::LengthDelimited), )); w.write_line(&format!("{os}.write_raw_varint32(entry_size as u32)?;",)); key.write_write_element(1, k, &self.file_and_mod(), &self.customize, os, w); value.write_write_element(2, v, &self.file_and_mod(), &self.customize, os, w); }); } pub(crate) fn write_message_write_field(&self, os: &str, w: &mut CodeWriter) { match &self.kind { FieldKind::Singular(s @ SingularField { elem, .. }) => { self.write_if_let_self_field_is_some(s, w, |v, w| { self.write_write_element(&elem, w, os, &v); }); } FieldKind::Repeated(RepeatedField { packed: false, elem, .. }) => { self.write_for_self_field(w, "v", |w, v_type| { let v = RustValueTyped { value: "v".to_owned(), rust_type: v_type.clone(), }; self.write_write_element(elem, w, "os", &v); }); } FieldKind::Repeated(RepeatedField { packed: true, .. }) => { w.write_line(&format!( "os.write_repeated_packed_{}({}, &{})?;", self.os_write_fn_suffix_with_unknown_for_enum(), self.proto_field.number(), self.self_field() )); } FieldKind::Map(MapField { key, value, .. }) => { self.write_write_map_field(key, value, os, w) } FieldKind::Oneof(..) => unreachable!(), }; } fn for_each_map_entry( &self, key: &FieldElem, value: &FieldElem, w: &mut CodeWriter, cb: impl FnOnce(&RustValueTyped, &RustValueTyped, &mut CodeWriter), ) { w.for_stmt(&format!("&{}", self.self_field()), "(k, v)", move |w| { let k = RustValueTyped { value: "k".to_owned(), rust_type: key.rust_storage_elem_type(&self.file_and_mod()).wrap_ref(), }; let v = RustValueTyped { value: "v".to_owned(), rust_type: value .rust_storage_elem_type(&self.file_and_mod()) .wrap_ref(), }; cb(&k, &v, w) }); } fn write_compute_map_field_size( &self, sum_var: &str, key: &FieldElem<'a>, value: &FieldElem<'a>, w: &mut CodeWriter, ) { self.for_each_map_entry(key, value, w, |k, v, w| { w.write_line("let mut entry_size = 0;"); key.write_element_size(1, k, HowToGetMessageSize::Compute, "entry_size", &self.customize, w); value.write_element_size(2, v, HowToGetMessageSize::Compute, "entry_size", &self.customize, w); w.write_line(&format!("{sum_var} += {tag_size} + {protobuf_crate}::rt::compute_raw_varint64_size(entry_size) + entry_size", tag_size = self.tag_size(), protobuf_crate = protobuf_crate_path(&self.customize), )); }); } pub(crate) fn write_message_compute_field_size(&self, sum_var: &str, w: &mut CodeWriter) { match &self.kind { FieldKind::Singular(s @ SingularField { elem, .. }) => { self.write_if_let_self_field_is_some(s, w, |v, w| { self.write_element_size(&elem, w, v, sum_var) }); } FieldKind::Repeated(RepeatedField { packed: false, elem, .. }) => { match elem.proto_type().encoded_size() { Some(s) => { let tag_size = self.tag_size(); let self_field = self.self_field(); w.write_line(&format!( "{} += {} * {}.len() as u64;", sum_var, (s + tag_size) as isize, self_field )); } None => { self.write_for_self_field(w, "value", |w, value_type| { self.write_element_size( elem, w, &RustValueTyped { value: "value".to_owned(), rust_type: value_type.clone(), }, sum_var, ); }); } }; } FieldKind::Repeated(RepeatedField { packed: true, .. }) => { let size_expr = self.self_field_vec_packed_size(); w.write_line(&format!("{} += {};", sum_var, size_expr)); } FieldKind::Map(MapField { key, value, .. }) => { self.write_compute_map_field_size(sum_var, key, value, w) } FieldKind::Oneof(..) => unreachable!(), } } fn write_message_field_get_singular_message(&self, s: &SingularField, w: &mut CodeWriter) { match s.flag { SingularFieldFlag::WithoutFlag => unimplemented!(), SingularFieldFlag::WithFlag { option_kind, .. } => { let self_field = self.self_field(); let ref field_type_name = self.elem().rust_storage_elem_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ); w.write_line(option_kind.unwrap_ref_or_else( &format!("{}.as_ref()", self_field), &format!( "<{} as {}::Message>::default_instance()", field_type_name.to_code(&self.customize), protobuf_crate_path(&self.customize), ), )); } } } fn write_message_field_get_singular_enum( &self, flag: SingularFieldFlag, _elem: &FieldElemEnum, w: &mut CodeWriter, ) { match flag { SingularFieldFlag::WithoutFlag => { w.write_line(&format!("self.{}.enum_value_or_default()", self.rust_name)); } SingularFieldFlag::WithFlag { .. } => { w.match_expr(&self.self_field(), |w| { let default_value = self.xxx_default_value_rust(); w.case_expr("Some(e)", &format!("e.enum_value_or({})", default_value)); w.case_expr("None", &format!("{}", default_value)); }); } } } fn write_message_field_get_singular(&self, singular: &SingularField, w: &mut CodeWriter) { let get_xxx_return_type = self.getter_return_type(); match singular.elem { FieldElem::Message(..) => self.write_message_field_get_singular_message(singular, w), FieldElem::Enum(ref en) => { self.write_message_field_get_singular_enum(singular.flag, en, w) } _ => { let get_xxx_default_value_rust = self.xxx_default_value_rust(); let self_field = self.self_field(); match singular { &SingularField { ref elem, flag: SingularFieldFlag::WithFlag { option_kind, .. }, .. } => { if get_xxx_return_type.is_ref().is_some() { let as_option = self.self_field_as_option(elem, option_kind); w.match_expr(&as_option.value, |w| { let v_type = as_option.rust_type.elem_type(); let r_type = self.getter_return_type(); w.case_expr( "Some(v)", v_type.into_target(&r_type, "v", &self.customize), ); let get_xxx_default_value_rust = self.xxx_default_value_rust(); w.case_expr("None", get_xxx_default_value_rust); }); } else { w.write_line(&format!( "{}.unwrap_or({})", self_field, get_xxx_default_value_rust )); } } &SingularField { flag: SingularFieldFlag::WithoutFlag, .. } => { w.write_line( self.full_storage_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ) .into_target( &get_xxx_return_type, &self_field, &self.customize, ), ); } } } } } fn write_message_field_get_oneof(&self, o: &OneofField, w: &mut CodeWriter) { let get_xxx_return_type = SingularOrOneofField::Oneof(o.clone()).getter_return_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ); let OneofField { ref elem, .. } = o; w.match_expr(&format!("self.{}", o.oneof_field_name), |w| { let (refv, vtype) = if !elem.is_copy() { ( "ref v", elem.rust_storage_elem_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ) .ref_type(), ) } else { ( "v", elem.rust_storage_elem_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ), ) }; w.case_expr( format!( "::std::option::Option::Some({}({}))", o.variant_path(&self.proto_field.message.scope.rust_path_to_file()), refv ), vtype.into_target(&get_xxx_return_type, "v", &self.customize), ); w.case_expr("_", self.xxx_default_value_rust()); }); } fn write_message_field_get(&self, w: &mut CodeWriter) { let get_xxx_return_type = self.getter_return_type(); let fn_def = format!( "{}(&self) -> {}", self.rust_name, get_xxx_return_type.to_code(&self.customize) ); w.pub_fn(&fn_def, |w| match self.kind { FieldKind::Oneof(ref o) => { self.write_message_field_get_oneof(o, w); } FieldKind::Singular(ref s) => { self.write_message_field_get_singular(s, w); } FieldKind::Repeated(..) | FieldKind::Map(..) => { let self_field = self.self_field(); w.write_line(&format!("&{}", self_field)); } }); } fn has_has(&self) -> bool { match self.kind { FieldKind::Repeated(..) | FieldKind::Map(..) => false, FieldKind::Singular(SingularField { flag: SingularFieldFlag::WithFlag { .. }, .. }) => true, FieldKind::Singular(SingularField { flag: SingularFieldFlag::WithoutFlag, .. }) => false, FieldKind::Oneof(..) => true, } } fn has_mut(&self) -> bool { match self.kind { FieldKind::Repeated(..) | FieldKind::Map(..) => true, // TODO: string should be public, and mut is not needed FieldKind::Singular(..) | FieldKind::Oneof(..) => !self.elem_type_is_copy(), } } fn has_take(&self) -> bool { match self.kind { FieldKind::Repeated(..) | FieldKind::Map(..) => true, // TODO: string should be public, and mut is not needed FieldKind::Singular(..) | FieldKind::Oneof(..) => !self.elem_type_is_copy(), } } fn has_name(&self) -> RustIdent { RustIdent::new(&format!("has_{}", self.rust_name.get())) } fn set_name(&self) -> RustIdent { RustIdent::new(&format!("set_{}", self.rust_name.get())) } fn mut_name(&self) -> RustIdent { RustIdent::new(&format!("mut_{}", self.rust_name.get())) } fn write_message_field_has(&self, w: &mut CodeWriter) { w.pub_fn( &format!("{}(&self) -> bool", self.has_name()), |w| match self.kind { FieldKind::Oneof(ref oneof) => { w.match_expr(&format!("self.{}", oneof.oneof_field_name), |w| { w.case_expr( format!( "::std::option::Option::Some({}(..))", oneof.variant_path( &self.proto_field.message.scope.rust_path_to_file() ) ), "true", ); w.case_expr("_", "false"); }); } _ => { let self_field_is_some = self.self_field_is_some(); w.write_line(self_field_is_some); } }, ); } fn write_message_field_set(&self, w: &mut CodeWriter) { let set_xxx_param_type = self.set_xxx_param_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ); w.comment("Param is passed by value, moved"); w.pub_fn( &format!( "{}(&mut self, v: {})", self.set_name(), set_xxx_param_type.to_code(&self.customize) ), |w| { let value_typed = RustValueTyped { value: "v".to_owned(), rust_type: set_xxx_param_type.clone(), }; match self.kind { FieldKind::Oneof(ref oneof) => { let v = set_xxx_param_type.into_target( &oneof.rust_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ), "v", &self.customize, ); w.write_line(&format!( "self.{} = ::std::option::Option::Some({}({}))", oneof.oneof_field_name, oneof.variant_path(&self.proto_field.message.scope.rust_path_to_file()), v )); } _ => { self.write_self_field_assign_value(w, &value_typed); } } }, ); } fn write_message_field_mut_singular_with_flag( &self, s: &SingularField, option_kind: OptionKind, w: &mut CodeWriter, ) { let self_field = self.self_field(); match option_kind { OptionKind::MessageField => { w.write_line(&format!("{}.mut_or_insert_default()", self_field)) } OptionKind::Option => { self.write_if_self_field_is_none(w, |w| { self.write_self_field_assign_default( &SingularOrOneofField::Singular(s.clone()), w, ); }); w.write_line(&format!("{}.as_mut().unwrap()", self_field)); } } } fn write_message_field_mut_singular(&self, s: &SingularField, w: &mut CodeWriter) { match s { s @ SingularField { flag: SingularFieldFlag::WithFlag { option_kind, .. }, .. } => self.write_message_field_mut_singular_with_flag(s, *option_kind, w), SingularField { flag: SingularFieldFlag::WithoutFlag, .. } => w.write_line(&format!("&mut {}", self.self_field())), } } fn write_message_field_mut(&self, w: &mut CodeWriter) { let mut_xxx_return_type = self.mut_xxx_return_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ); w.comment("Mutable pointer to the field."); if self.is_singular() { w.comment("If field is not initialized, it is initialized with default value first."); } let fn_def = match mut_xxx_return_type { RustType::Ref(ref param) => format!( "{}(&mut self) -> &mut {}", self.mut_name(), param.to_code(&self.customize) ), _ => panic!( "not a ref: {}", mut_xxx_return_type.to_code(&self.customize) ), }; w.pub_fn(&fn_def, |w| { match self.kind { FieldKind::Repeated(..) | FieldKind::Map(..) => { let self_field = self.self_field(); w.write_line(&format!("&mut {}", self_field)); } FieldKind::Singular(ref s) => { self.write_message_field_mut_singular(s, w); } FieldKind::Oneof(ref o) => { let self_field_oneof = format!("self.{}", o.oneof_field_name); // if oneof does not contain current field w.if_let_else_stmt( &format!( "::std::option::Option::Some({}(_))", o.variant_path(&self.proto_field.message.scope.rust_path_to_file()) )[..], &self_field_oneof[..], |w| { // initialize it with default value w.write_line(&format!( "{} = ::std::option::Option::Some({}({}));", self_field_oneof, o.variant_path(&self.proto_field.message.scope.rust_path_to_file()), self.element_default_value_rust() .into_type( o.rust_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()) ), &self.customize ) .value )); }, ); // extract field w.match_expr(self_field_oneof, |w| { w.case_expr( format!( "::std::option::Option::Some({}(ref mut v))", o.variant_path(&self.proto_field.message.scope.rust_path_to_file()) ), "v", ); w.case_expr("_", "panic!()"); }); } } }); } fn write_message_field_take_oneof(&self, o: &OneofField, w: &mut CodeWriter) { let take_xxx_return_type = self.take_xxx_return_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ); // TODO: replace with if let w.write_line(&format!("if self.{}() {{", self.has_name())); w.indented(|w| { let self_field_oneof = format!("self.{}", o.oneof_field_name); w.match_expr(format!("{}.take()", self_field_oneof), |w| { let value_in_some = o .rust_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ) .value("v".to_owned()); let converted = value_in_some.into_type( self.take_xxx_return_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ), &self.customize, ); w.case_expr( format!( "::std::option::Option::Some({}(v))", o.variant_path(&self.proto_field.message.scope.rust_path_to_file()) ), &converted.value, ); w.case_expr("_", "panic!()"); }); }); w.write_line("} else {"); w.indented(|w| { w.write_line( self.elem() .rust_storage_elem_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ) .default_value_typed(&self.customize, false) .into_type(take_xxx_return_type.clone(), &self.customize) .value, ); }); w.write_line("}"); } fn write_message_field_take_singular(&self, s: &SingularField, w: &mut CodeWriter) { match s { SingularField { ref elem, flag: SingularFieldFlag::WithFlag { option_kind, .. }, } => { if !elem.is_copy() { w.write_line( &option_kind.unwrap_or_else( &format!("{}.take()", self.self_field()), &elem .rust_storage_elem_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ) .default_value(&self.customize, false), ), ); } else { w.write_line(&format!( "{}.take().unwrap_or({})", self.self_field(), self.element_default_value_rust().value )); } } SingularField { flag: SingularFieldFlag::WithoutFlag, .. } => w.write_line(&format!( "::std::mem::replace(&mut {}, {})", self.self_field(), self.full_storage_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()) ) .default_value(&self.customize, false) )), } } fn write_message_field_take(&self, w: &mut CodeWriter) { let take_xxx_return_type = self.take_xxx_return_type( &self .proto_field .message .scope .file_and_mod(self.customize.clone()), ); w.comment("Take field"); w.pub_fn( &format!( "take_{}(&mut self) -> {}", self.rust_name, take_xxx_return_type.to_code(&self.customize) ), |w| match self.kind { FieldKind::Singular(ref s) => self.write_message_field_take_singular(&s, w), FieldKind::Oneof(ref o) => self.write_message_field_take_oneof(o, w), FieldKind::Repeated(..) | FieldKind::Map(..) => { w.write_line(&format!( "::std::mem::replace(&mut self.{}, {})", self.rust_name, take_xxx_return_type.default_value(&self.customize, false) )); } }, ); } pub(crate) fn write_message_single_field_accessors(&self, w: &mut CodeWriter) { if self.generate_accessors || self.generate_getter { w.write_line(""); let reconstruct_def = self.reconstruct_def(); w.comment(&(reconstruct_def + ";")); } if self.generate_getter { w.write_line(""); self.write_message_field_get(w); } if !self.generate_accessors { return; } w.write_line(""); let clear_field_func = self.clear_field_func(); w.pub_fn(&format!("{}(&mut self)", clear_field_func), |w| { self.write_clear(w); }); if self.has_has() { w.write_line(""); self.write_message_field_has(w); } w.write_line(""); self.write_message_field_set(w); if self.has_mut() { w.write_line(""); self.write_message_field_mut(w); } if self.has_take() { w.write_line(""); self.write_message_field_take(w); } } } pub(crate) fn rust_field_name_for_protobuf_field_name(name: &str) -> RustIdent { RustIdent::new(name) } pub(crate) fn rust_variant_name_for_protobuf_oneof_field_name(name: &str) -> RustIdent { let name = camel_case(name); RustIdent::new(&name) }