1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#![feature(format_args_capture)]

use std::fmt::Write;

pub struct Generator;

impl prost_build::ServiceGenerator for Generator {
    fn generate(&mut self, service: Service, buf: &mut String) {
        for m in service.methods {
            eprintln!("{:?}", m);
            let outtype = if m.output_proto_type == ".google.protobuf.Empty" {
                "()".to_string()
            } else {
                format!("Result<{}, ()>", m.output_type)
            };

            let intype = if m.input_proto_type == ".google.protobuf.Empty" {
                "()".to_string()
            } else {
                m.input_type
            };

            // TODO: Fix this crap
            let (out_read, out_write) = if m.output_proto_type == ".google.protobuf.Empty" {
                ("()".to_string(), "()".to_string())
            } else {
                (format!("Ok(<{}>::decode(b).unwrap())", m.output_type),
                 format!("let a: &{o} = res.as_ref().unwrap(); a.encode(b).unwrap()", o = m.output_type)
                )
            };


            let svc_spec = format!("{}.{}.{}", service.package, service.name, m.name);
            let svc_id = crc64::crc64(0, svc_spec.as_bytes());


            write!(buf, r#"
use quix::derive::*;
pub struct {name}(pub {input});

impl actix::Message for {name} {{
    type Result = {res};
}}

impl quix::derive::Service for {name} {{
    const NAME: &'static str = "{svc_spec}";
    const ID: u64 = {svc_id};
    fn write(&self, b: &mut impl bytes::BufMut) -> Result<(), ()> {{
        prost::Message::encode(&self.0, b).map_err(|_| ())
    }}
    fn read(b: impl bytes::Buf) -> Result<Self, ()> {{
        Ok(Self(prost::Message::decode(b).map_err(|_| ())?))
    }}

    fn read_result(b: impl bytes::Buf) -> Result<Self::Result, ()> {{
        Ok({out_read})
    }}

    fn write_result(res: &Self::Result, b: &mut impl bytes::BufMut) -> Result<(), ()> {{
        {out_write};
        Ok(())
    }}
}}

impl From<{input}> for {name} {{
    fn from(a: {input}) -> Self {{
        Self(a)
    }}
}}

impl Into<{input}> for {name} {{
    fn into(self) -> {input} {{
        self.0
    }}
}}

impl ::core::ops::Deref for {name} {{
    type Target = {input};
    fn deref(&self) -> &Self::Target {{
        &self.0
    }}
}}
impl ::core::ops::DerefMut for {name} {{
    fn deref_mut(&mut self) -> &mut Self::Target {{
        &mut self.0
    }}
}}
            "#,
                   name = m.proto_name,
                   res = outtype,
                   input = intype
            ).unwrap();
        }
    }
}

pub use prost_build::*;