1use crate::hir;
2use serde::{Deserialize, Serialize};
3
4mod document;
5
6#[cfg(test)]
7mod tests;
8
9use std::collections::BTreeMap;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
12pub enum HttpMethod {
13 Get,
14 Post,
15 Put,
16 Patch,
17 Delete,
18 Head,
19 Options,
20}
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
23pub enum HttpParamKind {
24 Path,
25 Query,
26 Header,
27 Cookie,
28 Body,
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
32pub enum HttpOperationSource {
33 Method,
34 AttributeGet,
35 AttributeSet,
36 AttributeWatch,
37}
38
39#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
40pub struct HttpRoute {
41 pub path: String,
42 pub path_params: Vec<String>,
43 pub query_params: Vec<String>,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct HttpParam {
48 pub name: String,
49 pub wire_name: String,
50 pub ty: hir::TypeSpec,
51 pub kind: HttpParamKind,
52 pub optional: bool,
53 pub flatten: bool,
54}
55
56#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
57pub struct HttpDocumentServer {
58 pub base_url: String,
59 pub description: Option<String>,
60}
61
62#[derive(Debug, Default)]
64pub struct ProjectOptions {
65 pub version_parameter: Option<hir::VersionParameter>,
67 pub version_values: Vec<(String, String)>,
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize, Default)]
72pub struct HttpDocumentMetadata {
73 pub package: Option<String>,
74 pub version: Option<String>,
75 pub servers: Vec<HttpDocumentServer>,
76 #[serde(default, skip_serializing_if = "Option::is_none")]
78 pub version_parameter: Option<hir::VersionParameter>,
79 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
82 pub version_values: BTreeMap<String, String>,
83 #[serde(default)]
85 pub exceptions: Vec<HttpException>,
86 #[serde(default)]
88 pub http_unions: Vec<HttpUnion>,
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize)]
96pub struct HttpException {
97 pub module_path: Vec<String>,
98 pub ident: String,
99 pub status: u16,
101 pub headers: Vec<HttpExceptionMember>,
102 pub cookies: Vec<HttpExceptionMember>,
103 pub body: Vec<HttpExceptionField>,
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct HttpExceptionMember {
109 pub field: String,
110 pub wire_name: String,
111 pub ty: hir::TypeSpec,
112 pub is_multi: bool,
114 #[serde(default)]
117 pub optional: bool,
118}
119
120#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct HttpExceptionField {
123 pub field: String,
124 pub wire_name: String,
126 pub optional: bool,
128 pub ty: hir::TypeSpec,
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct HttpExceptionRef {
134 pub module_path: Vec<String>,
135 pub ident: String,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct HttpOperation {
140 pub meta: HttpOperationMeta,
141 pub signature: HttpOperationSignature,
142 pub http: HttpOperationHttpMapping,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
146pub struct HttpOperationMeta {
147 pub name: String,
148 pub operation_id: String,
149 pub source: HttpOperationSource,
150 pub method: HttpMethod,
151 pub routes: Vec<HttpRoute>,
152 pub stream: super::semantics::HttpStreamConfig,
153 pub cors: Option<super::semantics::HttpCorsProfile>,
154 pub security: Option<super::semantics::HttpSecurityProfile>,
155 pub basic_auth_realm: Option<String>,
156 pub deprecated: Option<super::semantics::DeprecatedInfo>,
157 pub upgrade_protocol: Option<String>,
158 pub upgrade_mode: Option<super::semantics::UpgradeMode>,
159 pub websocket: Option<super::semantics::WebSocketConfig>,
160 #[serde(default)]
162 pub raises: Vec<HttpExceptionRef>,
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct HttpOperationSignature {
167 pub params: Vec<HttpSignatureParam>,
168 pub return_type: Option<hir::TypeSpec>,
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
172pub struct HttpSignatureParam {
173 pub name: String,
174 pub ty: hir::TypeSpec,
175 pub direction: HttpSignatureParamDirection,
176 pub is_optional: bool,
177 pub is_flatten: bool,
178 pub annotations: Vec<HttpSignatureParamAnnotation>,
179}
180
181#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
182pub enum HttpSignatureParamDirection {
183 In,
184 Out,
185 InOut,
186}
187
188#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
189pub enum HttpSignatureParamAnnotation {
190 Optional,
191 Flatten,
192 Path { name: String },
193 Query { name: String },
194 Header { name: String },
195 Cookie { name: String },
196 Body,
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct HttpOperationHttpMapping {
201 pub request: HttpRequestMapping,
202 pub response: HttpResponseMapping,
203}
204
205#[derive(Debug, Clone, Serialize, Deserialize)]
206pub struct HttpRequestMapping {
207 pub path: Vec<HttpInputBinding>,
208 pub query: Vec<HttpInputBinding>,
209 pub header: Vec<HttpInputBinding>,
210 pub cookie: Vec<HttpInputBinding>,
211 pub body: HttpRequestBodyMapping,
212}
213
214#[derive(Debug, Clone, Serialize, Deserialize)]
215pub struct HttpInputBinding {
216 pub source_param: String,
217 pub wire_name: String,
218 pub ty: hir::TypeSpec,
219 pub optional: bool,
220}
221
222#[derive(Debug, Clone, Serialize, Deserialize)]
223pub struct HttpRequestBodyMapping {
224 pub content_type: Option<String>,
225 pub content_type_explicit: bool,
226 pub codec: Option<HttpBodyCodec>,
227 pub shape: HttpRequestBodyShape,
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize)]
231pub enum HttpRequestBodyShape {
232 Empty,
233 SingleValue {
234 source_param: String,
235 #[serde(skip)]
236 wire_name: String,
237 flatten: bool,
238 ty: hir::TypeSpec,
239 },
240 Object {
241 fields: Vec<HttpRequestBodyField>,
242 },
243 Stream {
244 source_param: String,
245 #[serde(skip)]
246 wire_name: String,
247 item_ty: hir::TypeSpec,
248 codec: HttpStreamPayloadCodec,
249 },
250}
251
252impl HttpRequestBodyShape {
253 pub fn byte_parameter(&self) -> Option<&str> {
255 match self {
256 Self::SingleValue {
257 source_param, ty, ..
258 } if super::is_byte_sequence(ty) => Some(source_param),
259 _ => None,
260 }
261 }
262}
263
264#[derive(Debug, Clone, Serialize, Deserialize)]
265pub struct HttpRequestBodyField {
266 pub source_param: String,
267 pub field_name: String,
268 pub ty: hir::TypeSpec,
269 pub optional: bool,
270 pub flatten: bool,
271}
272
273#[derive(Debug, Clone, Serialize, Deserialize)]
274pub struct HttpResponseMapping {
275 pub header: Vec<HttpOutputBinding>,
276 pub cookie: Vec<HttpOutputBinding>,
277 pub body: HttpResponseBodyMapping,
278 pub status: String,
279 #[serde(default)]
282 pub representations: Vec<HttpRepresentation>,
283}
284
285#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct HttpRepresentation {
288 pub content_type: xidl_http::ContentType,
290 pub ty: hir::TypeSpec,
292 pub is_byte: bool,
294}
295
296#[derive(Debug, Clone, Serialize, Deserialize)]
298pub struct HttpUnion {
299 pub module_path: Vec<String>,
300 pub ident: String,
301 pub cases: Vec<HttpRepresentation>,
302}
303
304#[derive(Debug, Clone, Serialize, Deserialize)]
305pub struct HttpOutputBinding {
306 pub source: HttpOutputSource,
307 pub wire_name: String,
308 pub ty: hir::TypeSpec,
309}
310
311#[derive(Debug, Clone, Serialize, Deserialize)]
312pub enum HttpOutputSource {
313 ReturnValue,
314 Param { name: String },
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize)]
318pub struct HttpResponseBodyMapping {
319 pub content_type: Option<String>,
320 pub content_type_explicit: bool,
321 pub codec: Option<HttpBodyCodec>,
322 pub shape: HttpResponseBodyShape,
323}
324
325#[derive(Debug, Clone, Serialize, Deserialize)]
326pub enum HttpResponseBodyShape {
327 Empty,
328 ReturnOnly {
329 ty: hir::TypeSpec,
330 },
331 SingleValue {
332 source: HttpOutputSource,
333 ty: hir::TypeSpec,
334 },
335 Object {
336 fields: Vec<HttpResponseBodyField>,
337 },
338 Stream {
339 item_source: HttpOutputSource,
340 item_ty: hir::TypeSpec,
341 codec: HttpStreamPayloadCodec,
342 },
343}
344
345#[derive(Debug, Clone, Serialize, Deserialize)]
346pub struct HttpResponseBodyField {
347 pub source: HttpOutputSource,
348 pub field_name: String,
349 pub ty: hir::TypeSpec,
350}
351
352#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
353pub enum HttpBodyCodec {
354 Json,
355 Text,
356 FormUrlEncoded,
357 Msgpack,
358}
359
360#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
361pub enum HttpStreamPayloadCodec {
362 Ndjson,
363 Sse,
364 Bytes,
365}
366
367#[derive(Debug, Clone, Serialize, Deserialize)]
368pub struct HttpInterface {
369 pub name: String,
370 pub module_path: Vec<String>,
371 pub operations: Vec<HttpOperation>,
372}
373
374#[derive(Debug, Clone, Serialize, Deserialize)]
375pub struct RestHirDocument {
376 pub spec: hir::Specification,
377 pub document: HttpDocumentMetadata,
378 pub interfaces: Vec<HttpInterface>,
379}