kf_protocol_derive/lib.rs
1extern crate proc_macro;
2
3mod api;
4mod ast;
5mod de;
6mod ser;
7mod util;
8
9use self::api::generate_request_traits;
10use self::api::parse_and_generate_api;
11use self::de::generate_decode_trait_impls;
12use self::de::generate_default_trait_impls;
13use self::ser::generate_encode_trait_impls;
14
15use proc_macro::TokenStream;
16use syn::parse_macro_input;
17
18/// Custom derive for decoding structure or enum from bytes using Kafka protocol format.
19/// This assumes all fields implement kafka decode traits.
20///
21/// # Examples
22///
23/// ```
24/// use kf_protocol::Decoder;
25/// use kf_protocol::derive::Decode;
26///
27/// #[derive(Decode)]
28/// pub struct SimpleRecord {
29/// val: u8
30/// }
31///
32/// let data = [
33/// 0x04
34/// ];
35///
36/// let record = SimpleRecord::decode_from(&mut Cursor::new(&data),0).expect("decode");
37/// assert_eq!(record.val,4);
38///
39/// ```
40///
41///
42/// Decode applies to either Struct of Enum. For enum, it implements `TryFrom` trait.
43/// Currently it only supports integer variants.
44///
45/// So this works
46///
47/// ```
48/// #[derive(Decode)]
49/// pub enum ThreeChoice {
50/// First = 1,
51/// Second = 2,
52/// Third = 3
53/// }
54/// ```
55///
56/// Also, enum without integer literal works as well
57/// ```
58/// #[derive(Decode)]
59/// pub enum ThreeChoice {
60/// First,
61/// Second,
62/// Third
63/// }
64/// ```
65///
66/// In this case, 1 is decoded as First, 2 as Second, 3 as Third.
67///
68/// Currently, mixing enum variants are not supported.
69///
70///
71/// Decode support container and field level attributes.
72/// Container level applies to struct.
73/// For field attributes
74/// * `#[varint]` force decode using varint format.
75/// * `#fluvio_kf(min_version = <version>)]` decodes only if version is equal or greater than min_version
76/// * `#fluvio_kf(max_version = <version>)]`decodes only if version is less or equal than max_version
77///
78#[proc_macro_derive(Decode, attributes(varint, fluvio_kf))]
79pub fn kf_decode(tokens: TokenStream) -> TokenStream {
80 let input = parse_macro_input![tokens as ast::DeriveItem];
81 let expanded = generate_decode_trait_impls(&input);
82
83 expanded.into()
84}
85
86/// Custom derive for encoding structure or enum to bytes using Kafka protocol format.
87/// This assumes all fields(or enum variants) implement kafka encode traits.
88///
89/// # Examples
90///
91/// ```
92/// use kf_protocol::Encoder;
93/// use kf_protocol::derive::Encode;
94///
95/// #[derive(Encode)]
96/// pub struct SimpleRecord {
97/// val: u8
98/// }
99///
100/// let data = vec![];
101///
102/// let record = SimpleRecord { val: 4};
103/// recprd.encode(&mut data,0);
104///
105/// assert_eq!(data[0],4);
106///
107/// ```
108///
109///
110/// Encode applys to either Struct of Enum.
111///
112///
113/// Encode respects version attributes. See Decode derive.
114///
115///
116///
117#[proc_macro_derive(Encode, attributes(varint, fluvio_kf))]
118pub fn kf_encode(tokens: TokenStream) -> TokenStream {
119 let input = parse_macro_input![tokens as ast::DeriveItem];
120 let expanded = generate_encode_trait_impls(&input);
121
122 expanded.into()
123}
124
125#[proc_macro]
126pub fn kf_api(tokens: TokenStream) -> TokenStream {
127 let inputs = parse_macro_input![tokens as syn::DeriveInput];
128
129 let expanded = parse_and_generate_api(&inputs);
130 expanded.into()
131}
132
133/// Custom derive for implementing Request trait.
134/// This derives requires `fluvio_kf`
135///
136/// # Examples
137///
138/// ```
139/// use kf_protocol::derive::Decode;
140/// use kf_protocol::derive::Encode;
141/// use kf_protocol::api::Request;
142/// use kf_protocol::derive::RequestApi;
143///
144/// #[fluvio_kf(default,api_min_version = 5, api_max_version = 6, api_key = 10, response = "SimpleResponse")]
145/// #[derive(Request,Encode,Decode,Default)]
146/// pub struct SimpleRequest {
147/// val: u8
148/// }
149///
150///
151/// #[derive(Encode,Decode,Default)]
152/// #[fluvio_kf(default)]
153/// pub struct TestResponse {
154/// pub value: i8,
155/// }
156///
157/// ```
158///
159/// RequestApi derives respects following attributes in `fluvio_kf`
160///
161/// * `api_min_version`: min version that API supports. This is required
162/// * `api_max_version`: max version that API supports. This is optional.
163/// * `api_key`: API number. This is required
164/// * `response`: Response struct. This is required
165///
166#[proc_macro_derive(RequestApi, attributes(varint, fluvio_kf))]
167pub fn kf_request(tokens: TokenStream) -> TokenStream {
168 let inputs = parse_macro_input![tokens as syn::DeriveInput];
169
170 let expanded = generate_request_traits(&inputs);
171 expanded.into()
172}
173
174/// Custom derive for generating default structure
175///
176///
177/// Example:
178///
179/// ```
180/// #[derive(KfDefault)]
181/// #[fluvio_kf(default)]
182/// pub struct SimpleRecord {
183/// #[fluvio_kf(default = "-1" )]
184/// val: u8
185/// }
186///
187/// let record = SimpleRecord::default;
188/// assert_eq!(record.val,-1);
189/// ```
190///
191/// `default` assignment can be any Rust expression.
192#[proc_macro_derive(KfDefault, attributes(fluvio_kf))]
193pub fn kf_default(tokens: TokenStream) -> TokenStream {
194 let input = parse_macro_input![tokens as ast::DeriveItem];
195 let expanded = generate_default_trait_impls(&input);
196
197 expanded.into()
198}