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