pajamax_build/lib.rs
1//! `pajamax-build` compiles .proto files via `prost` and generates service
2//! stubs and proto definitions for use with [`pajamax`](https://docs.rs/pajamax).
3//!
4//! # Usage
5//!
6//! The usage is very similar to that of Tonic.
7//!
8//! 1. Import `pajamax` and `pajamax-build` in your Cargo.toml:
9//!
10//! ```toml
11//! [dependencies]
12//! pajamax = "0.3"
13//! prost = "0.1"
14//!
15//! [build-dependencies]
16//! pajamax-build = "0.3"
17//! ```
18//!
19//! 2. Call `pajamax-build` in build.rs:
20//!
21//! ```rust,ignore
22//! fn main() -> Result<(), Box<dyn std::error::Error>> {
23//! pajamax_build::compile_protos_in_local(&["proto/helloworld.proto"], &["."])?;
24//! Ok(())
25//! }
26//! ```
27//!
28//! If your want more options, call `prost_build` directly with `PajamaxGen`:
29//!
30//! ```rust,ignore
31//! fn main() -> Result<(), Box<dyn std::error::Error>> {
32//! prost_build::Config::new()
33//! // add your options here
34//! .service_generator(Box::new(pajamax_build::PajamaxGen::Local))
35//! .compile_protos(&["proto/helloworld.proto"], &["."])
36//! }
37//! ```
38//!
39//! 3. Call `pajamax` in your source code. See the local-mode example
40//! [`helloworld`](https://github.com/WuBingzheng/pajamax/tree/main/examples/src/helloworld.rs)
41//! and dispatch-mode example [`dict-store`](https://github.com/WuBingzheng/pajamax/tree/main/examples/src/dict_store.rs)
42//! for details.
43
44use std::path::Path;
45
46mod dispatch_mode;
47mod local_mode;
48
49/// Specify the services to be compiled in local-mode or dispatch-mode.
50///
51/// Generally you can call the `compile_protos_*` APIs which swap this enum.
52/// You need to use this enum only if you need more `prost` options.
53pub enum PajamaxGen {
54 /// All in local-mode.
55 Local,
56 /// All in dispatch-mode.
57 Dispatch,
58 /// The listed in local-mode while others in dispatch-mode.
59 ListLocal(Vec<&'static str>),
60 /// The listed in dispatch-mode while others in local-mode.
61 ListDispatch(Vec<&'static str>),
62 /// List local-mode and dispatch-mode both.
63 ListBoth {
64 local_svcs: Vec<&'static str>,
65 dispatch_svcs: Vec<&'static str>,
66 },
67}
68
69impl prost_build::ServiceGenerator for PajamaxGen {
70 fn generate(&mut self, service: prost_build::Service, buf: &mut String) {
71 let name = &service.name.as_str();
72 let is_local_mode = match self {
73 PajamaxGen::Local => true,
74 PajamaxGen::Dispatch => false,
75 PajamaxGen::ListLocal(svcs) => svcs.contains(&name),
76 PajamaxGen::ListDispatch(svcs) => !svcs.contains(&name),
77 PajamaxGen::ListBoth {
78 local_svcs,
79 dispatch_svcs,
80 } => {
81 if local_svcs.contains(&service.name.as_str()) {
82 true
83 } else if dispatch_svcs.contains(&service.name.as_str()) {
84 false
85 } else {
86 return;
87 }
88 }
89 };
90
91 if is_local_mode {
92 local_mode::generate(service, buf);
93 } else {
94 dispatch_mode::generate(service, buf);
95 }
96 }
97}
98
99/// Complie protofile. Build all services as local-mode.
100pub fn compile_protos_in_local(
101 protos: &[impl AsRef<Path>],
102 includes: &[impl AsRef<Path>],
103) -> std::io::Result<()> {
104 prost_build::Config::new()
105 .service_generator(Box::new(PajamaxGen::Local))
106 .compile_protos(protos, includes)
107}
108
109/// Complie protofile. Build all services as dispatch-mode.
110pub fn compile_protos_in_dispatch(
111 protos: &[impl AsRef<Path>],
112 includes: &[impl AsRef<Path>],
113) -> std::io::Result<()> {
114 prost_build::Config::new()
115 .service_generator(Box::new(PajamaxGen::Dispatch))
116 .compile_protos(protos, includes)
117}
118
119/// Complie protofile. Build some services as local-mode and others as dispatch-mode.
120pub fn compile_protos_list_local(
121 protos: &[impl AsRef<Path>],
122 includes: &[impl AsRef<Path>],
123 local_svcs: Vec<&'static str>,
124) -> std::io::Result<()> {
125 prost_build::Config::new()
126 .service_generator(Box::new(PajamaxGen::ListLocal(local_svcs)))
127 .compile_protos(protos, includes)
128}
129
130/// Complie protofile. Build some services as dispatch-mode and others as local-mode.
131pub fn compile_protos_list_dispatch(
132 protos: &[impl AsRef<Path>],
133 includes: &[impl AsRef<Path>],
134 dispatch_svcs: Vec<&'static str>,
135) -> std::io::Result<()> {
136 prost_build::Config::new()
137 .service_generator(Box::new(PajamaxGen::ListDispatch(dispatch_svcs)))
138 .compile_protos(protos, includes)
139}
140
141/// Complie protofile. Build some services as local-mode and some as dispatch-mode.
142pub fn compile_protos_list_both(
143 protos: &[impl AsRef<Path>],
144 includes: &[impl AsRef<Path>],
145 local_svcs: Vec<&'static str>,
146 dispatch_svcs: Vec<&'static str>,
147) -> std::io::Result<()> {
148 prost_build::Config::new()
149 .service_generator(Box::new(PajamaxGen::ListBoth {
150 local_svcs,
151 dispatch_svcs,
152 }))
153 .compile_protos(protos, includes)
154}