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