• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
2 
3 // Copyright (c) 2016, Stepan Koltsov
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the
7 // "Software"), to deal in the Software without restriction, including
8 // without limitation the rights to use, copy, modify, merge, publish,
9 // distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so, subject to
11 // the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 
24 use std::collections::HashMap;
25 use std::io::Write;
26 
27 use protobuf::compiler_plugin;
28 use protobuf::descriptor::*;
29 use protobuf::descriptorx::*;
30 
31 struct CodeWriter<'a> {
32     writer: &'a mut (dyn Write + 'a),
33     indent: String,
34 }
35 
36 impl<'a> CodeWriter<'a> {
new(writer: &'a mut dyn Write) -> CodeWriter<'a>37     pub fn new(writer: &'a mut dyn Write) -> CodeWriter<'a> {
38         CodeWriter {
39             writer,
40             indent: "".to_string(),
41         }
42     }
43 
write_line<S: AsRef<str>>(&mut self, line: S)44     pub fn write_line<S: AsRef<str>>(&mut self, line: S) {
45         (if line.as_ref().is_empty() {
46             self.writer.write_all(b"\n")
47         } else {
48             let s: String = [self.indent.as_ref(), line.as_ref(), "\n"].concat();
49             self.writer.write_all(s.as_bytes())
50         })
51         .unwrap();
52     }
53 
write_generated(&mut self)54     pub fn write_generated(&mut self) {
55         self.write_line("// This file is generated. Do not edit");
56         self.write_generated_common();
57     }
58 
write_generated_common(&mut self)59     fn write_generated_common(&mut self) {
60         // https://secure.phabricator.com/T784
61         self.write_line("// @generated");
62 
63         self.write_line("");
64         self.comment("https://github.com/Manishearth/rust-clippy/issues/702");
65         self.write_line("#![allow(unknown_lints)]");
66         self.write_line("#![allow(clippy::all)]");
67         self.write_line("");
68         self.write_line("#![allow(box_pointers)]");
69         self.write_line("#![allow(dead_code)]");
70         self.write_line("#![allow(missing_docs)]");
71         self.write_line("#![allow(non_camel_case_types)]");
72         self.write_line("#![allow(non_snake_case)]");
73         self.write_line("#![allow(non_upper_case_globals)]");
74         self.write_line("#![allow(trivial_casts)]");
75         self.write_line("#![allow(unsafe_code)]");
76         self.write_line("#![allow(unused_imports)]");
77         self.write_line("#![allow(unused_results)]");
78     }
79 
indented<F>(&mut self, cb: F) where F: Fn(&mut CodeWriter),80     pub fn indented<F>(&mut self, cb: F)
81     where
82         F: Fn(&mut CodeWriter),
83     {
84         cb(&mut CodeWriter {
85             writer: self.writer,
86             indent: format!("{}    ", self.indent),
87         });
88     }
89 
90     #[allow(dead_code)]
commented<F>(&mut self, cb: F) where F: Fn(&mut CodeWriter),91     pub fn commented<F>(&mut self, cb: F)
92     where
93         F: Fn(&mut CodeWriter),
94     {
95         cb(&mut CodeWriter {
96             writer: self.writer,
97             indent: format!("// {}", self.indent),
98         });
99     }
100 
block<F>(&mut self, first_line: &str, last_line: &str, cb: F) where F: Fn(&mut CodeWriter),101     pub fn block<F>(&mut self, first_line: &str, last_line: &str, cb: F)
102     where
103         F: Fn(&mut CodeWriter),
104     {
105         self.write_line(first_line);
106         self.indented(cb);
107         self.write_line(last_line);
108     }
109 
expr_block<F>(&mut self, prefix: &str, cb: F) where F: Fn(&mut CodeWriter),110     pub fn expr_block<F>(&mut self, prefix: &str, cb: F)
111     where
112         F: Fn(&mut CodeWriter),
113     {
114         self.block(&format!("{} {{", prefix), "}", cb);
115     }
116 
impl_self_block<S: AsRef<str>, F>(&mut self, name: S, cb: F) where F: Fn(&mut CodeWriter),117     pub fn impl_self_block<S: AsRef<str>, F>(&mut self, name: S, cb: F)
118     where
119         F: Fn(&mut CodeWriter),
120     {
121         self.expr_block(&format!("impl {}", name.as_ref()), cb);
122     }
123 
pub_struct<S: AsRef<str>, F>(&mut self, name: S, cb: F) where F: Fn(&mut CodeWriter),124     pub fn pub_struct<S: AsRef<str>, F>(&mut self, name: S, cb: F)
125     where
126         F: Fn(&mut CodeWriter),
127     {
128         self.expr_block(&format!("pub struct {}", name.as_ref()), cb);
129     }
130 
pub_trait<F>(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter),131     pub fn pub_trait<F>(&mut self, name: &str, cb: F)
132     where
133         F: Fn(&mut CodeWriter),
134     {
135         self.expr_block(&format!("pub trait {}", name), cb);
136     }
137 
field_entry(&mut self, name: &str, value: &str)138     pub fn field_entry(&mut self, name: &str, value: &str) {
139         self.write_line(&format!("{}: {},", name, value));
140     }
141 
field_decl(&mut self, name: &str, field_type: &str)142     pub fn field_decl(&mut self, name: &str, field_type: &str) {
143         self.write_line(&format!("{}: {},", name, field_type));
144     }
145 
comment(&mut self, comment: &str)146     pub fn comment(&mut self, comment: &str) {
147         if comment.is_empty() {
148             self.write_line("//");
149         } else {
150             self.write_line(&format!("// {}", comment));
151         }
152     }
153 
fn_def(&mut self, sig: &str)154     pub fn fn_def(&mut self, sig: &str) {
155         self.write_line(&format!("fn {};", sig));
156     }
157 
fn_block<F>(&mut self, public: bool, sig: &str, cb: F) where F: Fn(&mut CodeWriter),158     pub fn fn_block<F>(&mut self, public: bool, sig: &str, cb: F)
159     where
160         F: Fn(&mut CodeWriter),
161     {
162         if public {
163             self.expr_block(&format!("pub fn {}", sig), cb);
164         } else {
165             self.expr_block(&format!("fn {}", sig), cb);
166         }
167     }
168 
pub_fn<F>(&mut self, sig: &str, cb: F) where F: Fn(&mut CodeWriter),169     pub fn pub_fn<F>(&mut self, sig: &str, cb: F)
170     where
171         F: Fn(&mut CodeWriter),
172     {
173         self.fn_block(true, sig, cb);
174     }
175 }
176 
177 use super::util::{self, fq_grpc, to_snake_case, MethodType};
178 
179 struct MethodGen<'a> {
180     proto: &'a MethodDescriptorProto,
181     service_name: String,
182     service_path: String,
183     root_scope: &'a RootScope<'a>,
184 }
185 
186 impl<'a> MethodGen<'a> {
new( proto: &'a MethodDescriptorProto, service_name: String, service_path: String, root_scope: &'a RootScope<'a>, ) -> MethodGen<'a>187     fn new(
188         proto: &'a MethodDescriptorProto,
189         service_name: String,
190         service_path: String,
191         root_scope: &'a RootScope<'a>,
192     ) -> MethodGen<'a> {
193         MethodGen {
194             proto,
195             service_name,
196             service_path,
197             root_scope,
198         }
199     }
200 
input(&self) -> String201     fn input(&self) -> String {
202         format!(
203             "super::{}",
204             self.root_scope
205                 .find_message(self.proto.get_input_type())
206                 .rust_fq_name()
207         )
208     }
209 
output(&self) -> String210     fn output(&self) -> String {
211         format!(
212             "super::{}",
213             self.root_scope
214                 .find_message(self.proto.get_output_type())
215                 .rust_fq_name()
216         )
217     }
218 
method_type(&self) -> (MethodType, String)219     fn method_type(&self) -> (MethodType, String) {
220         match (
221             self.proto.get_client_streaming(),
222             self.proto.get_server_streaming(),
223         ) {
224             (false, false) => (MethodType::Unary, fq_grpc("MethodType::Unary")),
225             (true, false) => (
226                 MethodType::ClientStreaming,
227                 fq_grpc("MethodType::ClientStreaming"),
228             ),
229             (false, true) => (
230                 MethodType::ServerStreaming,
231                 fq_grpc("MethodType::ServerStreaming"),
232             ),
233             (true, true) => (MethodType::Duplex, fq_grpc("MethodType::Duplex")),
234         }
235     }
236 
service_name(&self) -> String237     fn service_name(&self) -> String {
238         to_snake_case(&self.service_name)
239     }
240 
name(&self) -> String241     fn name(&self) -> String {
242         to_snake_case(self.proto.get_name())
243     }
244 
fq_name(&self) -> String245     fn fq_name(&self) -> String {
246         format!("\"{}/{}\"", self.service_path, &self.proto.get_name())
247     }
248 
const_method_name(&self) -> String249     fn const_method_name(&self) -> String {
250         format!(
251             "METHOD_{}_{}",
252             self.service_name().to_uppercase(),
253             self.name().to_uppercase()
254         )
255     }
256 
write_definition(&self, w: &mut CodeWriter)257     fn write_definition(&self, w: &mut CodeWriter) {
258         let head = format!(
259             "const {}: {}<{}, {}> = {} {{",
260             self.const_method_name(),
261             fq_grpc("Method"),
262             self.input(),
263             self.output(),
264             fq_grpc("Method")
265         );
266         let pb_mar = format!(
267             "{} {{ ser: {}, de: {} }}",
268             fq_grpc("Marshaller"),
269             fq_grpc("pb_ser"),
270             fq_grpc("pb_de")
271         );
272         w.block(&head, "};", |w| {
273             w.field_entry("ty", &self.method_type().1);
274             w.field_entry("name", &self.fq_name());
275             w.field_entry("req_mar", &pb_mar);
276             w.field_entry("resp_mar", &pb_mar);
277         });
278     }
279 
280     // Method signatures
unary(&self, method_name: &str) -> String281     fn unary(&self, method_name: &str) -> String {
282         format!(
283             "{}(&self, req: &{}) -> {}<{}>",
284             method_name,
285             self.input(),
286             fq_grpc("Result"),
287             self.output()
288         )
289     }
290 
unary_opt(&self, method_name: &str) -> String291     fn unary_opt(&self, method_name: &str) -> String {
292         format!(
293             "{}_opt(&self, req: &{}, opt: {}) -> {}<{}>",
294             method_name,
295             self.input(),
296             fq_grpc("CallOption"),
297             fq_grpc("Result"),
298             self.output()
299         )
300     }
301 
unary_async(&self, method_name: &str) -> String302     fn unary_async(&self, method_name: &str) -> String {
303         format!(
304             "{}_async(&self, req: &{}) -> {}<{}<{}>>",
305             method_name,
306             self.input(),
307             fq_grpc("Result"),
308             fq_grpc("ClientUnaryReceiver"),
309             self.output()
310         )
311     }
312 
unary_async_opt(&self, method_name: &str) -> String313     fn unary_async_opt(&self, method_name: &str) -> String {
314         format!(
315             "{}_async_opt(&self, req: &{}, opt: {}) -> {}<{}<{}>>",
316             method_name,
317             self.input(),
318             fq_grpc("CallOption"),
319             fq_grpc("Result"),
320             fq_grpc("ClientUnaryReceiver"),
321             self.output()
322         )
323     }
324 
client_streaming(&self, method_name: &str) -> String325     fn client_streaming(&self, method_name: &str) -> String {
326         format!(
327             "{}(&self) -> {}<({}<{}>, {}<{}>)>",
328             method_name,
329             fq_grpc("Result"),
330             fq_grpc("ClientCStreamSender"),
331             self.input(),
332             fq_grpc("ClientCStreamReceiver"),
333             self.output()
334         )
335     }
336 
client_streaming_opt(&self, method_name: &str) -> String337     fn client_streaming_opt(&self, method_name: &str) -> String {
338         format!(
339             "{}_opt(&self, opt: {}) -> {}<({}<{}>, {}<{}>)>",
340             method_name,
341             fq_grpc("CallOption"),
342             fq_grpc("Result"),
343             fq_grpc("ClientCStreamSender"),
344             self.input(),
345             fq_grpc("ClientCStreamReceiver"),
346             self.output()
347         )
348     }
349 
server_streaming(&self, method_name: &str) -> String350     fn server_streaming(&self, method_name: &str) -> String {
351         format!(
352             "{}(&self, req: &{}) -> {}<{}<{}>>",
353             method_name,
354             self.input(),
355             fq_grpc("Result"),
356             fq_grpc("ClientSStreamReceiver"),
357             self.output()
358         )
359     }
360 
server_streaming_opt(&self, method_name: &str) -> String361     fn server_streaming_opt(&self, method_name: &str) -> String {
362         format!(
363             "{}_opt(&self, req: &{}, opt: {}) -> {}<{}<{}>>",
364             method_name,
365             self.input(),
366             fq_grpc("CallOption"),
367             fq_grpc("Result"),
368             fq_grpc("ClientSStreamReceiver"),
369             self.output()
370         )
371     }
372 
duplex_streaming(&self, method_name: &str) -> String373     fn duplex_streaming(&self, method_name: &str) -> String {
374         format!(
375             "{}(&self) -> {}<({}<{}>, {}<{}>)>",
376             method_name,
377             fq_grpc("Result"),
378             fq_grpc("ClientDuplexSender"),
379             self.input(),
380             fq_grpc("ClientDuplexReceiver"),
381             self.output()
382         )
383     }
384 
duplex_streaming_opt(&self, method_name: &str) -> String385     fn duplex_streaming_opt(&self, method_name: &str) -> String {
386         format!(
387             "{}_opt(&self, opt: {}) -> {}<({}<{}>, {}<{}>)>",
388             method_name,
389             fq_grpc("CallOption"),
390             fq_grpc("Result"),
391             fq_grpc("ClientDuplexSender"),
392             self.input(),
393             fq_grpc("ClientDuplexReceiver"),
394             self.output()
395         )
396     }
397 
write_client(&self, w: &mut CodeWriter)398     fn write_client(&self, w: &mut CodeWriter) {
399         let method_name = self.name();
400         match self.method_type().0 {
401             // Unary
402             MethodType::Unary => {
403                 w.pub_fn(&self.unary_opt(&method_name), |w| {
404                     w.write_line(&format!(
405                         "self.client.unary_call(&{}, req, opt)",
406                         self.const_method_name()
407                     ));
408                 });
409                 w.write_line("");
410 
411                 w.pub_fn(&self.unary(&method_name), |w| {
412                     w.write_line(&format!(
413                         "self.{}_opt(req, {})",
414                         method_name,
415                         fq_grpc("CallOption::default()")
416                     ));
417                 });
418                 w.write_line("");
419 
420                 w.pub_fn(&self.unary_async_opt(&method_name), |w| {
421                     w.write_line(&format!(
422                         "self.client.unary_call_async(&{}, req, opt)",
423                         self.const_method_name()
424                     ));
425                 });
426                 w.write_line("");
427 
428                 w.pub_fn(&self.unary_async(&method_name), |w| {
429                     w.write_line(&format!(
430                         "self.{}_async_opt(req, {})",
431                         method_name,
432                         fq_grpc("CallOption::default()")
433                     ));
434                 });
435             }
436 
437             // Client streaming
438             MethodType::ClientStreaming => {
439                 w.pub_fn(&self.client_streaming_opt(&method_name), |w| {
440                     w.write_line(&format!(
441                         "self.client.client_streaming(&{}, opt)",
442                         self.const_method_name()
443                     ));
444                 });
445                 w.write_line("");
446 
447                 w.pub_fn(&self.client_streaming(&method_name), |w| {
448                     w.write_line(&format!(
449                         "self.{}_opt({})",
450                         method_name,
451                         fq_grpc("CallOption::default()")
452                     ));
453                 });
454             }
455 
456             // Server streaming
457             MethodType::ServerStreaming => {
458                 w.pub_fn(&self.server_streaming_opt(&method_name), |w| {
459                     w.write_line(&format!(
460                         "self.client.server_streaming(&{}, req, opt)",
461                         self.const_method_name()
462                     ));
463                 });
464                 w.write_line("");
465 
466                 w.pub_fn(&self.server_streaming(&method_name), |w| {
467                     w.write_line(&format!(
468                         "self.{}_opt(req, {})",
469                         method_name,
470                         fq_grpc("CallOption::default()")
471                     ));
472                 });
473             }
474 
475             // Duplex streaming
476             MethodType::Duplex => {
477                 w.pub_fn(&self.duplex_streaming_opt(&method_name), |w| {
478                     w.write_line(&format!(
479                         "self.client.duplex_streaming(&{}, opt)",
480                         self.const_method_name()
481                     ));
482                 });
483                 w.write_line("");
484 
485                 w.pub_fn(&self.duplex_streaming(&method_name), |w| {
486                     w.write_line(&format!(
487                         "self.{}_opt({})",
488                         method_name,
489                         fq_grpc("CallOption::default()")
490                     ));
491                 });
492             }
493         };
494     }
495 
write_service(&self, w: &mut CodeWriter)496     fn write_service(&self, w: &mut CodeWriter) {
497         let req_stream_type = format!("{}<{}>", fq_grpc("RequestStream"), self.input());
498         let (req, req_type, resp_type) = match self.method_type().0 {
499             MethodType::Unary => ("req", self.input(), "UnarySink"),
500             MethodType::ClientStreaming => ("stream", req_stream_type, "ClientStreamingSink"),
501             MethodType::ServerStreaming => ("req", self.input(), "ServerStreamingSink"),
502             MethodType::Duplex => ("stream", req_stream_type, "DuplexSink"),
503         };
504         let sig = format!(
505             "{}(&mut self, ctx: {}, {}: {}, sink: {}<{}>)",
506             self.name(),
507             fq_grpc("RpcContext"),
508             req,
509             req_type,
510             fq_grpc(resp_type),
511             self.output()
512         );
513         w.fn_def(&sig);
514     }
515 
write_bind(&self, w: &mut CodeWriter)516     fn write_bind(&self, w: &mut CodeWriter) {
517         let add = match self.method_type().0 {
518             MethodType::Unary => "add_unary_handler",
519             MethodType::ClientStreaming => "add_client_streaming_handler",
520             MethodType::ServerStreaming => "add_server_streaming_handler",
521             MethodType::Duplex => "add_duplex_streaming_handler",
522         };
523         w.block(
524             &format!(
525                 "builder = builder.{}(&{}, move |ctx, req, resp| {{",
526                 add,
527                 self.const_method_name()
528             ),
529             "});",
530             |w| {
531                 w.write_line(&format!("instance.{}(ctx, req, resp)", self.name()));
532             },
533         );
534     }
535 }
536 
537 struct ServiceGen<'a> {
538     proto: &'a ServiceDescriptorProto,
539     methods: Vec<MethodGen<'a>>,
540 }
541 
542 impl<'a> ServiceGen<'a> {
new( proto: &'a ServiceDescriptorProto, file: &FileDescriptorProto, root_scope: &'a RootScope, ) -> ServiceGen<'a>543     fn new(
544         proto: &'a ServiceDescriptorProto,
545         file: &FileDescriptorProto,
546         root_scope: &'a RootScope,
547     ) -> ServiceGen<'a> {
548         let service_path = if file.get_package().is_empty() {
549             format!("/{}", proto.get_name())
550         } else {
551             format!("/{}.{}", file.get_package(), proto.get_name())
552         };
553         let methods = proto
554             .get_method()
555             .iter()
556             .map(|m| {
557                 MethodGen::new(
558                     m,
559                     util::to_camel_case(proto.get_name()),
560                     service_path.clone(),
561                     root_scope,
562                 )
563             })
564             .collect();
565 
566         ServiceGen { proto, methods }
567     }
568 
service_name(&self) -> String569     fn service_name(&self) -> String {
570         util::to_camel_case(self.proto.get_name())
571     }
572 
client_name(&self) -> String573     fn client_name(&self) -> String {
574         format!("{}Client", self.service_name())
575     }
576 
write_client(&self, w: &mut CodeWriter)577     fn write_client(&self, w: &mut CodeWriter) {
578         w.write_line("#[derive(Clone)]");
579         w.pub_struct(&self.client_name(), |w| {
580             w.field_decl("client", "::grpcio::Client");
581         });
582 
583         w.write_line("");
584 
585         w.impl_self_block(&self.client_name(), |w| {
586             w.pub_fn("new(channel: ::grpcio::Channel) -> Self", |w| {
587                 w.expr_block(&self.client_name(), |w| {
588                     w.field_entry("client", "::grpcio::Client::new(channel)");
589                 });
590             });
591 
592             for method in &self.methods {
593                 w.write_line("");
594                 method.write_client(w);
595             }
596             w.pub_fn(
597                 "spawn<F>(&self, f: F) where F: ::futures::Future<Output = ()> + Send + 'static",
598                 |w| {
599                     w.write_line("self.client.spawn(f)");
600                 },
601             )
602         });
603     }
604 
write_server(&self, w: &mut CodeWriter)605     fn write_server(&self, w: &mut CodeWriter) {
606         w.pub_trait(&self.service_name(), |w| {
607             for method in &self.methods {
608                 method.write_service(w);
609             }
610         });
611 
612         w.write_line("");
613 
614         let s = format!(
615             "create_{}<S: {} + Send + Clone + 'static>(s: S) -> {}",
616             to_snake_case(&self.service_name()),
617             self.service_name(),
618             fq_grpc("Service")
619         );
620         w.pub_fn(&s, |w| {
621             w.write_line("let mut builder = ::grpcio::ServiceBuilder::new();");
622             for method in &self.methods[0..self.methods.len() - 1] {
623                 w.write_line("let mut instance = s.clone();");
624                 method.write_bind(w);
625             }
626 
627             w.write_line("let mut instance = s;");
628             self.methods[self.methods.len() - 1].write_bind(w);
629 
630             w.write_line("builder.build()");
631         });
632     }
633 
write_method_definitions(&self, w: &mut CodeWriter)634     fn write_method_definitions(&self, w: &mut CodeWriter) {
635         for (i, method) in self.methods.iter().enumerate() {
636             if i != 0 {
637                 w.write_line("");
638             }
639 
640             method.write_definition(w);
641         }
642     }
643 
write(&self, w: &mut CodeWriter)644     fn write(&self, w: &mut CodeWriter) {
645         self.write_method_definitions(w);
646         w.write_line("");
647         self.write_client(w);
648         w.write_line("");
649         self.write_server(w);
650     }
651 }
652 
gen_file( file: &FileDescriptorProto, root_scope: &RootScope, ) -> Option<compiler_plugin::GenResult>653 fn gen_file(
654     file: &FileDescriptorProto,
655     root_scope: &RootScope,
656 ) -> Option<compiler_plugin::GenResult> {
657     if file.get_service().is_empty() {
658         return None;
659     }
660 
661     let base = protobuf::descriptorx::proto_path_to_rust_mod(file.get_name());
662 
663     let mut v = Vec::new();
664     {
665         let mut w = CodeWriter::new(&mut v);
666         w.write_generated();
667 
668         for service in file.get_service() {
669             w.write_line("");
670             ServiceGen::new(service, file, root_scope).write(&mut w);
671         }
672     }
673 
674     Some(compiler_plugin::GenResult {
675         name: base + "_grpc.rs",
676         content: v,
677     })
678 }
679 
gen( file_descriptors: &[FileDescriptorProto], files_to_generate: &[String], ) -> Vec<compiler_plugin::GenResult>680 pub fn gen(
681     file_descriptors: &[FileDescriptorProto],
682     files_to_generate: &[String],
683 ) -> Vec<compiler_plugin::GenResult> {
684     let files_map: HashMap<&str, &FileDescriptorProto> =
685         file_descriptors.iter().map(|f| (f.get_name(), f)).collect();
686 
687     let root_scope = RootScope { file_descriptors };
688 
689     let mut results = Vec::new();
690 
691     for file_name in files_to_generate {
692         let file = files_map[&file_name[..]];
693 
694         if file.get_service().is_empty() {
695             continue;
696         }
697 
698         results.extend(gen_file(file, &root_scope).into_iter());
699     }
700 
701     results
702 }
703 
protoc_gen_grpc_rust_main()704 pub fn protoc_gen_grpc_rust_main() {
705     compiler_plugin::plugin_main(gen);
706 }
707