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}