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