Skip to main content

xidl_parser/rest_hir/model/
mod.rs

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, PartialEq, Eq, Serialize, Deserialize, Default)]
60pub struct HttpDocumentMetadata {
61    pub package: Option<String>,
62    pub version: Option<String>,
63    pub servers: Vec<HttpDocumentServer>,
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct HttpOperation {
68    pub meta: HttpOperationMeta,
69    pub signature: HttpOperationSignature,
70    pub http: HttpOperationHttpMapping,
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct HttpOperationMeta {
75    pub name: String,
76    pub operation_id: String,
77    pub source: HttpOperationSource,
78    pub method: HttpMethod,
79    pub routes: Vec<HttpRoute>,
80    pub stream: super::semantics::HttpStreamConfig,
81    pub cors: Option<super::semantics::HttpCorsProfile>,
82    pub security: Option<super::semantics::HttpSecurityProfile>,
83    pub basic_auth_realm: Option<String>,
84    pub deprecated: Option<super::semantics::DeprecatedInfo>,
85    pub upgrade_protocol: Option<String>,
86    pub upgrade_mode: Option<super::semantics::UpgradeMode>,
87    pub websocket: Option<super::semantics::WebSocketConfig>,
88}
89
90#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct HttpOperationSignature {
92    pub params: Vec<HttpSignatureParam>,
93    pub return_type: Option<hir::TypeSpec>,
94}
95
96#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct HttpSignatureParam {
98    pub name: String,
99    pub ty: hir::TypeSpec,
100    pub direction: HttpSignatureParamDirection,
101    pub is_optional: bool,
102    pub is_flatten: bool,
103    pub annotations: Vec<HttpSignatureParamAnnotation>,
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
107pub enum HttpSignatureParamDirection {
108    In,
109    Out,
110    InOut,
111}
112
113#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
114pub enum HttpSignatureParamAnnotation {
115    Optional,
116    Flatten,
117    Path { name: String },
118    Query { name: String },
119    Header { name: String },
120    Cookie { name: String },
121    Body,
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize)]
125pub struct HttpOperationHttpMapping {
126    pub request: HttpRequestMapping,
127    pub response: HttpResponseMapping,
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct HttpRequestMapping {
132    pub path: Vec<HttpInputBinding>,
133    pub query: Vec<HttpInputBinding>,
134    pub header: Vec<HttpInputBinding>,
135    pub cookie: Vec<HttpInputBinding>,
136    pub body: HttpRequestBodyMapping,
137}
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
140pub struct HttpInputBinding {
141    pub source_param: String,
142    pub wire_name: String,
143    pub ty: hir::TypeSpec,
144    pub optional: bool,
145}
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
148pub struct HttpRequestBodyMapping {
149    pub content_type: Option<String>,
150    pub content_type_explicit: bool,
151    pub codec: Option<HttpBodyCodec>,
152    pub shape: HttpRequestBodyShape,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
156pub enum HttpRequestBodyShape {
157    Empty,
158    SingleValue {
159        source_param: String,
160        flatten: bool,
161        ty: hir::TypeSpec,
162    },
163    Object {
164        fields: Vec<HttpRequestBodyField>,
165    },
166    Stream {
167        source_param: String,
168        item_ty: hir::TypeSpec,
169        codec: HttpStreamPayloadCodec,
170    },
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct HttpRequestBodyField {
175    pub source_param: String,
176    pub field_name: String,
177    pub ty: hir::TypeSpec,
178    pub optional: bool,
179    pub flatten: bool,
180}
181
182#[derive(Debug, Clone, Serialize, Deserialize)]
183pub struct HttpResponseMapping {
184    pub header: Vec<HttpOutputBinding>,
185    pub cookie: Vec<HttpOutputBinding>,
186    pub body: HttpResponseBodyMapping,
187    pub status: String,
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize)]
191pub struct HttpOutputBinding {
192    pub source: HttpOutputSource,
193    pub wire_name: String,
194    pub ty: hir::TypeSpec,
195}
196
197#[derive(Debug, Clone, Serialize, Deserialize)]
198pub enum HttpOutputSource {
199    ReturnValue,
200    Param { name: String },
201}
202
203#[derive(Debug, Clone, Serialize, Deserialize)]
204pub struct HttpResponseBodyMapping {
205    pub content_type: Option<String>,
206    pub content_type_explicit: bool,
207    pub codec: Option<HttpBodyCodec>,
208    pub shape: HttpResponseBodyShape,
209}
210
211#[derive(Debug, Clone, Serialize, Deserialize)]
212pub enum HttpResponseBodyShape {
213    Empty,
214    ReturnOnly {
215        ty: hir::TypeSpec,
216    },
217    SingleValue {
218        source: HttpOutputSource,
219        ty: hir::TypeSpec,
220    },
221    Object {
222        fields: Vec<HttpResponseBodyField>,
223    },
224    Stream {
225        item_source: HttpOutputSource,
226        item_ty: hir::TypeSpec,
227        codec: HttpStreamPayloadCodec,
228    },
229}
230
231#[derive(Debug, Clone, Serialize, Deserialize)]
232pub struct HttpResponseBodyField {
233    pub source: HttpOutputSource,
234    pub field_name: String,
235    pub ty: hir::TypeSpec,
236}
237
238#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
239pub enum HttpBodyCodec {
240    Json,
241    Text,
242    FormUrlEncoded,
243    Msgpack,
244}
245
246#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
247pub enum HttpStreamPayloadCodec {
248    Ndjson,
249    Sse,
250    Bytes,
251}
252
253#[derive(Debug, Clone, Serialize, Deserialize)]
254pub struct HttpInterface {
255    pub name: String,
256    pub module_path: Vec<String>,
257    pub operations: Vec<HttpOperation>,
258}
259
260#[derive(Debug, Clone, Serialize, Deserialize)]
261pub struct RestHirDocument {
262    pub spec: hir::Specification,
263    pub document: HttpDocumentMetadata,
264    pub interfaces: Vec<HttpInterface>,
265}
266
267impl RestHirDocument {
268    pub fn from_props(props: &hir::ParserProperties) -> ParserResult<Self> {
269        let value = props
270            .get("rest_hir")
271            .cloned()
272            .ok_or_else(|| ParseError::Message("missing rest_hir properties".to_string()))?;
273        serde_json::from_value(value).map_err(|err| ParseError::Message(err.to_string()))
274    }
275
276    pub fn find_interface(&self, module_path: &[String], name: &str) -> Option<&HttpInterface> {
277        self.interfaces
278            .iter()
279            .find(|interface| interface.name == name && interface.module_path == module_path)
280    }
281}