protobuf_codegen_no_elision/
message.rs

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