1 use protobuf::descriptor::*; 2 use protobuf::descriptorx::*; 3 4 use super::code_writer::*; 5 use super::customize::customize_from_rustproto_for_message; 6 use super::customize::Customize; 7 use super::enums::*; 8 use super::field::*; 9 use super::rust_types_values::*; 10 use inside::protobuf_crate_path; 11 use oneof::OneofGen; 12 use oneof::OneofVariantGen; 13 use serde; 14 15 /// Message info for codegen 16 pub struct MessageGen<'a> { 17 pub(crate) message: &'a MessageWithScope<'a>, 18 pub(crate) root_scope: &'a RootScope<'a>, 19 type_name: String, 20 pub fields: Vec<FieldGen<'a>>, 21 pub lite_runtime: bool, 22 customize: Customize, 23 } 24 25 impl<'a> MessageGen<'a> { new( message: &'a MessageWithScope<'a>, root_scope: &'a RootScope<'a>, customize: &Customize, ) -> MessageGen<'a>26 pub fn new( 27 message: &'a MessageWithScope<'a>, 28 root_scope: &'a RootScope<'a>, 29 customize: &Customize, 30 ) -> MessageGen<'a> { 31 let mut customize = customize.clone(); 32 customize.update_with(&customize_from_rustproto_for_message( 33 message.message.get_options(), 34 )); 35 36 let fields: Vec<_> = message 37 .fields() 38 .into_iter() 39 .map(|field| FieldGen::parse(field, root_scope, &customize)) 40 .collect(); 41 let lite_runtime = customize.lite_runtime.unwrap_or_else(|| { 42 message 43 .get_file_descriptor() 44 .get_options() 45 .get_optimize_for() 46 == FileOptions_OptimizeMode::LITE_RUNTIME 47 }); 48 MessageGen { 49 message: message, 50 root_scope: root_scope, 51 type_name: message.rust_name(), 52 fields: fields, 53 lite_runtime, 54 customize, 55 } 56 } 57 expose_oneof(&self) -> bool58 fn expose_oneof(&self) -> bool { 59 self.customize.expose_oneof.unwrap_or(true) 60 } 61 oneofs(&'a self) -> Vec<OneofGen<'a>>62 fn oneofs(&'a self) -> Vec<OneofGen<'a>> { 63 self.message 64 .oneofs() 65 .into_iter() 66 .map(|oneof| OneofGen::parse(self, oneof, &self.customize)) 67 .collect() 68 } 69 required_fields(&'a self) -> Vec<&'a FieldGen>70 fn required_fields(&'a self) -> Vec<&'a FieldGen> { 71 self.fields 72 .iter() 73 .filter(|f| match f.kind { 74 FieldKind::Singular(ref singular) => singular.flag.is_required(), 75 _ => false, 76 }) 77 .collect() 78 } 79 message_fields(&'a self) -> Vec<&'a FieldGen>80 fn message_fields(&'a self) -> Vec<&'a FieldGen> { 81 self.fields 82 .iter() 83 .filter(|f| f.proto_type == FieldDescriptorProto_Type::TYPE_MESSAGE) 84 .collect() 85 } 86 fields_except_oneof(&'a self) -> Vec<&'a FieldGen>87 fn fields_except_oneof(&'a self) -> Vec<&'a FieldGen> { 88 self.fields.iter().filter(|f| !f.is_oneof()).collect() 89 } 90 fields_except_group(&'a self) -> Vec<&'a FieldGen>91 fn fields_except_group(&'a self) -> Vec<&'a FieldGen> { 92 self.fields 93 .iter() 94 .filter(|f| f.proto_type != FieldDescriptorProto_Type::TYPE_GROUP) 95 .collect() 96 } 97 fields_except_oneof_and_group(&'a self) -> Vec<&'a FieldGen>98 fn fields_except_oneof_and_group(&'a self) -> Vec<&'a FieldGen> { 99 self.fields 100 .iter() 101 .filter(|f| !f.is_oneof() && f.proto_type != FieldDescriptorProto_Type::TYPE_GROUP) 102 .collect() 103 } 104 write_match_each_oneof_variant<F>(&self, w: &mut CodeWriter, cb: F) where F: Fn(&mut CodeWriter, &OneofVariantGen, &str, &RustType),105 fn write_match_each_oneof_variant<F>(&self, w: &mut CodeWriter, cb: F) 106 where 107 F: Fn(&mut CodeWriter, &OneofVariantGen, &str, &RustType), 108 { 109 for oneof in self.oneofs() { 110 w.if_let_stmt( 111 "::std::option::Option::Some(ref v)", 112 &format!("self.{}", oneof.name())[..], 113 |w| { 114 w.match_block("v", |w| { 115 for variant in oneof.variants_except_group() { 116 let ref field = variant.field; 117 let (refv, vtype) = if !field.elem_type_is_copy() { 118 ("ref v", field.elem().rust_storage_type().ref_type()) 119 } else { 120 ("v", field.elem().rust_storage_type()) 121 }; 122 w.case_block(format!("&{}({})", variant.path(), refv), |w| { 123 cb(w, &variant, "v", &vtype); 124 }); 125 } 126 }); 127 }, 128 ); 129 } 130 } 131 write_write_to_with_cached_sizes(&self, w: &mut CodeWriter)132 fn write_write_to_with_cached_sizes(&self, w: &mut CodeWriter) { 133 let sig = format!( 134 "write_to_with_cached_sizes(&self, os: &mut {}::CodedOutputStream<'_>) -> {}::ProtobufResult<()>", 135 protobuf_crate_path(&self.customize), 136 protobuf_crate_path(&self.customize), 137 ); 138 w.def_fn(&sig, |w| { 139 // To have access to its methods but not polute the name space. 140 for f in self.fields_except_oneof_and_group() { 141 f.write_message_write_field(w); 142 } 143 self.write_match_each_oneof_variant(w, |w, variant, v, v_type| { 144 variant.field.write_write_element(w, "os", v, v_type); 145 }); 146 w.write_line("os.write_unknown_fields(self.get_unknown_fields())?;"); 147 w.write_line("::std::result::Result::Ok(())"); 148 }); 149 } 150 write_get_cached_size(&self, w: &mut CodeWriter)151 fn write_get_cached_size(&self, w: &mut CodeWriter) { 152 w.def_fn("get_cached_size(&self) -> u32", |w| { 153 w.write_line("self.cached_size.get()"); 154 }); 155 } 156 write_default_instance(&self, w: &mut CodeWriter)157 fn write_default_instance(&self, w: &mut CodeWriter) { 158 w.def_fn( 159 &format!("default_instance() -> &'static {}", self.type_name), 160 |w| { 161 w.lazy_static_decl_get_simple( 162 "instance", 163 &self.type_name, 164 &format!("{}::new", self.type_name), 165 ); 166 }, 167 ); 168 } 169 write_compute_size(&self, w: &mut CodeWriter)170 fn write_compute_size(&self, w: &mut CodeWriter) { 171 // Append sizes of messages in the tree to the specified vector. 172 // First appended element is size of self, and then nested message sizes. 173 // in serialization order are appended recursively."); 174 w.comment("Compute sizes of nested messages"); 175 // there are unused variables in oneof 176 w.allow(&["unused_variables"]); 177 w.def_fn("compute_size(&self) -> u32", |w| { 178 // To have access to its methods but not polute the name space. 179 w.write_line("let mut my_size = 0;"); 180 for field in self.fields_except_oneof_and_group() { 181 field.write_message_compute_field_size("my_size", w); 182 } 183 self.write_match_each_oneof_variant(w, |w, variant, v, vtype| { 184 variant.field.write_element_size(w, v, vtype, "my_size"); 185 }); 186 w.write_line(&format!( 187 "my_size += {}::rt::unknown_fields_size(self.get_unknown_fields());", 188 protobuf_crate_path(&self.customize) 189 )); 190 w.write_line("self.cached_size.set(my_size);"); 191 w.write_line("my_size"); 192 }); 193 } 194 write_field_accessors(&self, w: &mut CodeWriter)195 fn write_field_accessors(&self, w: &mut CodeWriter) { 196 for f in self.fields_except_group() { 197 w.write_line(""); 198 let reconstruct_def = f.reconstruct_def(); 199 w.comment(&(reconstruct_def + ";")); 200 w.write_line(""); 201 f.write_message_single_field_accessors(w); 202 } 203 } 204 write_impl_self(&self, w: &mut CodeWriter)205 fn write_impl_self(&self, w: &mut CodeWriter) { 206 w.impl_self_block(&self.type_name, |w| { 207 // TODO: new should probably be a part of Message trait 208 w.pub_fn(&format!("new() -> {}", self.type_name), |w| { 209 w.write_line("::std::default::Default::default()"); 210 }); 211 212 self.write_field_accessors(w); 213 }); 214 } 215 write_unknown_fields(&self, w: &mut CodeWriter)216 fn write_unknown_fields(&self, w: &mut CodeWriter) { 217 w.def_fn( 218 "get_unknown_fields(&self) -> &::protobuf::UnknownFields", 219 |w| { 220 w.write_line("&self.unknown_fields"); 221 }, 222 ); 223 w.write_line(""); 224 w.def_fn( 225 "mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields", 226 |w| { 227 w.write_line("&mut self.unknown_fields"); 228 }, 229 ); 230 } 231 write_merge_from(&self, w: &mut CodeWriter)232 fn write_merge_from(&self, w: &mut CodeWriter) { 233 let sig = format!( 234 "merge_from(&mut self, is: &mut {}::CodedInputStream<'_>) -> {}::ProtobufResult<()>", 235 protobuf_crate_path(&self.customize), 236 protobuf_crate_path(&self.customize), 237 ); 238 w.def_fn(&sig, |w| { 239 w.while_block("!is.eof()?", |w| { 240 w.write_line(&format!("let (field_number, wire_type) = is.read_tag_unpack()?;")); 241 w.match_block("field_number", |w| { 242 for f in &self.fields_except_group() { 243 let number = f.proto_field.number(); 244 w.case_block(number.to_string(), |w| { 245 f.write_merge_from_field("wire_type", w); 246 }); 247 } 248 w.case_block("_", |w| { 249 w.write_line(&format!("{}::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;", protobuf_crate_path(&self.customize))); 250 }); 251 }); 252 }); 253 w.write_line("::std::result::Result::Ok(())"); 254 }); 255 } 256 write_descriptor_field(&self, fields_var: &str, field: &FieldGen, w: &mut CodeWriter)257 fn write_descriptor_field(&self, fields_var: &str, field: &FieldGen, w: &mut CodeWriter) { 258 let accessor_fn = field.accessor_fn(); 259 w.write_line(&format!( 260 "{}.push(::protobuf::reflect::accessor::{}(", 261 fields_var, 262 accessor_fn.sig() 263 )); 264 w.indented(|w| { 265 w.write_line(&format!("\"{}\",", field.proto_field.name())); 266 match accessor_fn.style { 267 AccessorStyle::Lambda => { 268 w.write_line(&format!( 269 "|m: &{}| {{ &m.{} }},", 270 self.type_name, field.rust_name 271 )); 272 w.write_line(&format!( 273 "|m: &mut {}| {{ &mut m.{} }},", 274 self.type_name, field.rust_name 275 )); 276 } 277 AccessorStyle::HasGet => { 278 w.write_line(&format!("{}::has_{},", self.type_name, field.rust_name)); 279 w.write_line(&format!("{}::get_{},", self.type_name, field.rust_name)); 280 } 281 } 282 }); 283 w.write_line("));"); 284 } 285 write_descriptor_static(&self, w: &mut CodeWriter)286 fn write_descriptor_static(&self, w: &mut CodeWriter) { 287 w.def_fn( 288 &format!("descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor"), 289 |w| { 290 w.lazy_static_decl_get( 291 "descriptor", 292 "::protobuf::reflect::MessageDescriptor", 293 |w| { 294 let fields = self.fields_except_group(); 295 if fields.is_empty() { 296 w.write_line(&format!("let fields = ::std::vec::Vec::new();")); 297 } else { 298 w.write_line(&format!("let mut fields = ::std::vec::Vec::new();")); 299 } 300 for field in fields { 301 self.write_descriptor_field("fields", field, w); 302 } 303 w.write_line(&format!( 304 "::protobuf::reflect::MessageDescriptor::new::<{}>(", 305 self.type_name 306 )); 307 w.indented(|w| { 308 w.write_line(&format!("\"{}\",", self.type_name)); 309 w.write_line("fields,"); 310 w.write_line("file_descriptor_proto()"); 311 }); 312 w.write_line(")"); 313 }, 314 ); 315 }, 316 ); 317 } 318 write_is_initialized(&self, w: &mut CodeWriter)319 fn write_is_initialized(&self, w: &mut CodeWriter) { 320 w.def_fn(&format!("is_initialized(&self) -> bool"), |w| { 321 // TODO: use single loop 322 323 for f in self.required_fields() { 324 f.write_if_self_field_is_none(w, |w| { 325 w.write_line("return false;"); 326 }); 327 } 328 329 for f in self.message_fields() { 330 if let FieldKind::Map(..) = f.kind { 331 // TODO: check values 332 continue; 333 } 334 335 // TODO: 336 // if message is declared in this file and has no message fields, 337 // we could skip the check here 338 f.write_for_self_field(w, "v", |w, _t| { 339 w.if_stmt("!v.is_initialized()", |w| { 340 w.write_line("return false;"); 341 }); 342 }); 343 } 344 w.write_line("true"); 345 }); 346 } 347 write_impl_message(&self, w: &mut CodeWriter)348 fn write_impl_message(&self, w: &mut CodeWriter) { 349 w.impl_for_block("::protobuf::Message", &self.type_name, |w| { 350 self.write_is_initialized(w); 351 w.write_line(""); 352 self.write_merge_from(w); 353 w.write_line(""); 354 self.write_compute_size(w); 355 w.write_line(""); 356 self.write_write_to_with_cached_sizes(w); 357 w.write_line(""); 358 self.write_get_cached_size(w); 359 w.write_line(""); 360 self.write_unknown_fields(w); 361 w.write_line(""); 362 w.def_fn("as_any(&self) -> &dyn (::std::any::Any)", |w| { 363 w.write_line("self as &dyn (::std::any::Any)"); 364 }); 365 w.def_fn("as_any_mut(&mut self) -> &mut dyn (::std::any::Any)", |w| { 366 w.write_line("self as &mut dyn (::std::any::Any)"); 367 }); 368 w.def_fn( 369 "into_any(self: Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)>", 370 |w| { 371 w.write_line("self"); 372 }, 373 ); 374 w.write_line(""); 375 w.def_fn( 376 "descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor", 377 |w| { 378 w.write_line("Self::descriptor_static()"); 379 }, 380 ); 381 w.write_line(""); 382 w.def_fn(&format!("new() -> {}", self.type_name), |w| { 383 w.write_line(&format!("{}::new()", self.type_name)); 384 }); 385 if !self.lite_runtime { 386 w.write_line(""); 387 self.write_descriptor_static(w); 388 } 389 w.write_line(""); 390 self.write_default_instance(w); 391 }); 392 } 393 write_impl_value(&self, w: &mut CodeWriter)394 fn write_impl_value(&self, w: &mut CodeWriter) { 395 w.impl_for_block("::protobuf::reflect::ProtobufValue", &self.type_name, |w| { 396 w.def_fn( 397 "as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef", 398 |w| w.write_line("::protobuf::reflect::ProtobufValueRef::Message(self)"), 399 ) 400 }) 401 } 402 write_impl_show(&self, w: &mut CodeWriter)403 fn write_impl_show(&self, w: &mut CodeWriter) { 404 w.impl_for_block("::std::fmt::Debug", &self.type_name, |w| { 405 w.def_fn( 406 "fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result", 407 |w| { 408 w.write_line("::protobuf::text_format::fmt(self, f)"); 409 }, 410 ); 411 }); 412 } 413 write_impl_clear(&self, w: &mut CodeWriter)414 fn write_impl_clear(&self, w: &mut CodeWriter) { 415 w.impl_for_block("::protobuf::Clear", &self.type_name, |w| { 416 w.def_fn("clear(&mut self)", |w| { 417 for f in self.fields_except_group() { 418 f.write_clear(w); 419 } 420 w.write_line("self.unknown_fields.clear();"); 421 }); 422 }); 423 } 424 425 #[allow(dead_code)] supports_derive_partial_eq(&self) -> bool426 fn supports_derive_partial_eq(&self) -> bool { 427 // There's stack overflow in the compiler when struct has too many fields 428 // https://github.com/rust-lang/rust/issues/40119 429 self.fields.len() <= 500 430 } 431 write_struct(&self, w: &mut CodeWriter)432 fn write_struct(&self, w: &mut CodeWriter) { 433 let mut derive = vec!["PartialEq", "Clone", "Default"]; 434 if self.lite_runtime { 435 derive.push("Debug"); 436 } 437 w.derive(&derive); 438 serde::write_serde_attr(w, &self.customize, "derive(Serialize, Deserialize)"); 439 w.pub_struct(&self.type_name, |w| { 440 if !self.fields_except_oneof().is_empty() { 441 w.comment("message fields"); 442 for field in self.fields_except_oneof() { 443 if field.proto_type == FieldDescriptorProto_Type::TYPE_GROUP { 444 w.comment(&format!("{}: <group>", &field.rust_name)); 445 } else { 446 let vis = if field.expose_field { 447 Visibility::Public 448 } else { 449 match field.kind { 450 FieldKind::Repeated(..) => Visibility::Default, 451 FieldKind::Singular(SingularField { ref flag, .. }) => { 452 match *flag { 453 SingularFieldFlag::WithFlag { .. } => Visibility::Default, 454 SingularFieldFlag::WithoutFlag => Visibility::Public, 455 } 456 } 457 FieldKind::Map(..) => Visibility::Public, 458 FieldKind::Oneof(..) => unreachable!(), 459 } 460 }; 461 w.field_decl_vis( 462 vis, 463 &field.rust_name, 464 &field.full_storage_type().to_code(&self.customize), 465 ); 466 } 467 } 468 } 469 if !self.oneofs().is_empty() { 470 w.comment("message oneof groups"); 471 for oneof in self.oneofs() { 472 let vis = match self.expose_oneof() { 473 true => Visibility::Public, 474 false => Visibility::Default, 475 }; 476 w.field_decl_vis( 477 vis, 478 oneof.name(), 479 &oneof.full_storage_type().to_code(&self.customize), 480 ); 481 } 482 } 483 w.comment("special fields"); 484 serde::write_serde_attr(w, &self.customize, "serde(skip)"); 485 w.pub_field_decl( 486 "unknown_fields", 487 &format!("{}::UnknownFields", protobuf_crate_path(&self.customize)), 488 ); 489 serde::write_serde_attr(w, &self.customize, "serde(skip)"); 490 w.pub_field_decl( 491 "cached_size", 492 &format!("{}::CachedSize", protobuf_crate_path(&self.customize)), 493 ); 494 }); 495 } 496 write_impl_default_for_amp(&self, w: &mut CodeWriter)497 fn write_impl_default_for_amp(&self, w: &mut CodeWriter) { 498 w.impl_args_for_block( 499 &["'a"], 500 "::std::default::Default", 501 &format!("&'a {}", self.type_name), 502 |w| { 503 w.def_fn(&format!("default() -> &'a {}", self.type_name), |w| { 504 w.write_line(&format!( 505 "<{} as {}::Message>::default_instance()", 506 self.type_name, 507 protobuf_crate_path(&self.customize), 508 )); 509 }); 510 }, 511 ); 512 } 513 write(&self, w: &mut CodeWriter)514 pub fn write(&self, w: &mut CodeWriter) { 515 self.write_struct(w); 516 517 w.write_line(""); 518 self.write_impl_default_for_amp(w); 519 520 for oneof in self.oneofs() { 521 w.write_line(""); 522 oneof.write_enum(w); 523 } 524 525 w.write_line(""); 526 self.write_impl_self(w); 527 w.write_line(""); 528 self.write_impl_message(w); 529 w.write_line(""); 530 self.write_impl_clear(w); 531 if !self.lite_runtime { 532 w.write_line(""); 533 self.write_impl_show(w); 534 } 535 w.write_line(""); 536 self.write_impl_value(w); 537 538 let mut nested_prefix = self.type_name.to_string(); 539 nested_prefix.push_str("_"); 540 541 for nested in &self.message.to_scope().get_messages() { 542 // ignore map entries, because they are not used in map fields 543 if nested.map_entry().is_none() { 544 w.write_line(""); 545 MessageGen::new(nested, self.root_scope, &self.customize).write(w); 546 } 547 } 548 549 for enum_type in &self.message.to_scope().get_enums() { 550 w.write_line(""); 551 let current_file = self.message.get_scope().get_file_descriptor(); 552 EnumGen::new(enum_type, current_file, &self.customize, self.root_scope).write(w); 553 } 554 } 555 } 556