Skip to main content

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