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