1use proc_macro::TokenStream;
9use quote::quote;
10
11const WIT_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/wit");
15
16#[proc_macro_attribute]
18pub fn intercept(_attr: TokenStream, item: TokenStream) -> TokenStream {
19 let func = syn::parse_macro_input!(item as syn::ItemFn);
20 let func_name = &func.sig.ident;
21
22 quote!(
27 #func
28 mod __kiwi_intercept {
29 mod bindings {
30 #![allow(missing_docs)]
31 ::kiwi_sdk::wit_bindgen::generate!({
32 path: #WIT_PATH,
33 world: "intercept-hook",
34 runtime_path: "::kiwi_sdk::wit_bindgen::rt",
35 });
36 }
37
38 struct Kiwi;
39
40 impl bindings::Guest for Kiwi {
41 fn intercept(ctx: self::bindings::kiwi::kiwi::intercept_types::Context) -> self::bindings::kiwi::kiwi::intercept_types::Action {
42 super::#func_name(ctx.into()).into()
43 }
44 }
45
46 impl From<self::bindings::kiwi::kiwi::intercept_types::Context> for ::kiwi_sdk::hook::intercept::Context {
47 fn from(value: self::bindings::kiwi::kiwi::intercept_types::Context) -> Self {
48 Self {
49 auth: value.auth.map(|raw| {
50 ::kiwi_sdk::hook::intercept::AuthCtx {
51 raw,
52 }
53 }),
54 connection: value.connection.into(),
55 event: value.event.into(),
56 }
57 }
58 }
59
60 impl From<self::bindings::kiwi::kiwi::intercept_types::EventCtx> for ::kiwi_sdk::hook::intercept::EventCtx {
61 fn from(value: self::bindings::kiwi::kiwi::intercept_types::EventCtx) -> Self {
62 match value {
63 self::bindings::kiwi::kiwi::intercept_types::EventCtx::Kafka(ctx) => Self::Kafka(ctx.into()),
64 self::bindings::kiwi::kiwi::intercept_types::EventCtx::Counter(ctx) => Self::Counter(ctx.into()),
65 }
66 }
67 }
68
69 impl From<self::bindings::kiwi::kiwi::intercept_types::CounterEventCtx> for ::kiwi_sdk::hook::intercept::CounterEventCtx {
70 fn from(value: self::bindings::kiwi::kiwi::intercept_types::CounterEventCtx) -> Self {
71 Self {
72 source_id: value.source_id,
73 count: value.count,
74 }
75 }
76 }
77
78 impl From<self::bindings::kiwi::kiwi::intercept_types::KafkaEventCtx> for ::kiwi_sdk::hook::intercept::KafkaEventCtx {
79 fn from(value: self::bindings::kiwi::kiwi::intercept_types::KafkaEventCtx) -> Self {
80 let timestamp: Option<i64> = value.timestamp.map(|t| t.try_into().expect("timestamp conversion must not fail"));
81 let partition: i32 = value.partition.try_into().expect("partition conversion must not fail");
82 let offset: i64 = value.offset.try_into().expect("offset conversion must not fail");
83
84 Self {
85 payload: value.payload,
86 topic: value.topic,
87 timestamp,
88 partition,
89 offset,
90 }
91 }
92 }
93
94 impl From<self::bindings::kiwi::kiwi::intercept_types::ConnectionCtx> for ::kiwi_sdk::hook::intercept::ConnectionCtx {
95 fn from(value: self::bindings::kiwi::kiwi::intercept_types::ConnectionCtx) -> Self {
96 match value {
97 self::bindings::kiwi::kiwi::intercept_types::ConnectionCtx::Websocket(ctx) => Self::WebSocket(ctx.into()),
98 }
99 }
100 }
101
102 impl From<self::bindings::kiwi::kiwi::intercept_types::Websocket> for ::kiwi_sdk::hook::intercept::WebSocketConnectionCtx {
103 fn from(value: self::bindings::kiwi::kiwi::intercept_types::Websocket) -> Self {
104 Self {
105 addr: value.addr,
106 }
107 }
108 }
109
110 impl From<::kiwi_sdk::hook::intercept::Action> for self::bindings::kiwi::kiwi::intercept_types::Action {
111 fn from(value: ::kiwi_sdk::hook::intercept::Action) -> Self {
112 match value {
113 ::kiwi_sdk::hook::intercept::Action::Forward => Self::Forward,
114 ::kiwi_sdk::hook::intercept::Action::Discard => Self::Discard,
115 ::kiwi_sdk::hook::intercept::Action::Transform(payload) => Self::Transform(payload.into()),
116 }
117 }
118 }
119
120 impl From<::kiwi_sdk::hook::intercept::TransformedPayload> for self::bindings::kiwi::kiwi::intercept_types::TransformedPayload {
121 fn from(value: ::kiwi_sdk::hook::intercept::TransformedPayload) -> Self {
122 match value {
123 ::kiwi_sdk::hook::intercept::TransformedPayload::Kafka(payload) => Self::Kafka(payload),
124 ::kiwi_sdk::hook::intercept::TransformedPayload::Counter(count) => Self::Counter(count),
125 }
126 }
127 }
128
129 bindings::export!(Kiwi with_types_in bindings);
130 }
131 )
132 .into()
133}
134
135#[proc_macro_attribute]
137pub fn authenticate(_attr: TokenStream, item: TokenStream) -> TokenStream {
138 let func = syn::parse_macro_input!(item as syn::ItemFn);
139 let func_name = &func.sig.ident;
140
141 quote!(
144 #func
145 mod __kiwi_authenticate {
146 mod bindings {
147 #![allow(missing_docs)]
148 ::kiwi_sdk::wit_bindgen::generate!({
149 path: #WIT_PATH,
150 world: "authenticate-hook",
151 runtime_path: "::kiwi_sdk::wit_bindgen::rt",
152 with: {
153 "wasi:http/outgoing-handler@0.2.0": ::kiwi_sdk::wit::wasi::http::outgoing_handler,
154 "wasi:http/types@0.2.0": ::kiwi_sdk::wit::wasi::http::types,
155 "wasi:clocks/monotonic-clock@0.2.0": ::kiwi_sdk::wit::wasi::clocks::monotonic_clock,
156 "wasi:io/poll@0.2.0": ::kiwi_sdk::wit::wasi::io::poll,
157 "wasi:io/streams@0.2.0": ::kiwi_sdk::wit::wasi::io::streams,
158 "wasi:io/error@0.2.0": ::kiwi_sdk::wit::wasi::io::error,
159 },
160 });
161 }
162
163 struct Kiwi;
164
165 impl bindings::Guest for Kiwi {
166 fn authenticate(incoming: self::bindings::kiwi::kiwi::authenticate_types::HttpRequest) -> self::bindings::kiwi::kiwi::authenticate_types::Outcome {
167 super::#func_name(incoming.into()).into()
168 }
169 }
170
171 impl From<::kiwi_sdk::hook::authenticate::Outcome> for self::bindings::kiwi::kiwi::authenticate_types::Outcome {
172 fn from(value: ::kiwi_sdk::hook::authenticate::Outcome) -> Self {
173 match value {
174 ::kiwi_sdk::hook::authenticate::Outcome::Authenticate => Self::Authenticate,
175 ::kiwi_sdk::hook::authenticate::Outcome::Reject => Self::Reject,
176 ::kiwi_sdk::hook::authenticate::Outcome::WithContext(payload) => Self::WithContext(payload),
177 }
178 }
179 }
180
181 impl From<self::bindings::kiwi::kiwi::authenticate_types::HttpRequest> for ::kiwi_sdk::http::Request<()> {
182 fn from(value: self::bindings::kiwi::kiwi::authenticate_types::HttpRequest) -> Self {
183 let mut uri_builder = ::kiwi_sdk::http::Uri::builder();
184
185 if let Some(scheme) = value.scheme {
186 let scheme = match scheme {
187 ::kiwi_sdk::wit::wasi::http::types::Scheme::Http => ::kiwi_sdk::http::Scheme::HTTP,
188 ::kiwi_sdk::wit::wasi::http::types::Scheme::Https => ::kiwi_sdk::http::Scheme::HTTPS,
189 ::kiwi_sdk::wit::wasi::http::types::Scheme::Other(scheme) => scheme.as_str().parse().expect("failed to parse scheme"),
190 };
191
192 uri_builder = uri_builder.scheme(scheme);
193 }
194
195 if let Some(authority) = value.authority {
196 uri_builder = uri_builder.authority(authority.as_str());
197 }
198
199 if let Some(path_with_query) = value.path_with_query {
200 uri_builder = uri_builder.path_and_query(path_with_query.as_str());
201 }
202
203 let uri = uri_builder.build().expect("failed to build uri");
204
205 let method = match value.method {
206 ::kiwi_sdk::wit::wasi::http::types::Method::Get => ::kiwi_sdk::http::Method::GET,
207 ::kiwi_sdk::wit::wasi::http::types::Method::Head => ::kiwi_sdk::http::Method::HEAD,
208 ::kiwi_sdk::wit::wasi::http::types::Method::Post => ::kiwi_sdk::http::Method::POST,
209 ::kiwi_sdk::wit::wasi::http::types::Method::Put => ::kiwi_sdk::http::Method::PUT,
210 ::kiwi_sdk::wit::wasi::http::types::Method::Delete => ::kiwi_sdk::http::Method::DELETE,
211 ::kiwi_sdk::wit::wasi::http::types::Method::Connect => ::kiwi_sdk::http::Method::CONNECT,
212 ::kiwi_sdk::wit::wasi::http::types::Method::Options => ::kiwi_sdk::http::Method::OPTIONS,
213 ::kiwi_sdk::wit::wasi::http::types::Method::Trace => ::kiwi_sdk::http::Method::TRACE,
214 ::kiwi_sdk::wit::wasi::http::types::Method::Patch => ::kiwi_sdk::http::Method::PATCH,
215 ::kiwi_sdk::wit::wasi::http::types::Method::Other(_) => panic!("Unknown method"),
216 };
217
218 let mut request_builder = ::kiwi_sdk::http::Request::builder()
219 .method(method)
220 .uri(uri);
221
222 for (key, value) in value.headers {
223 request_builder = request_builder.header(key, value);
224 }
225
226 request_builder.body(()).expect("failed to build request")
227 }
228 }
229
230 bindings::export!(Kiwi with_types_in bindings);
231 }
232 )
233 .into()
234}