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    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 codec: Option<HttpBodyCodec>,
149    pub shape: HttpRequestBodyShape,
150}
151
152#[derive(Debug, Clone, Serialize, Deserialize)]
153pub enum HttpRequestBodyShape {
154    Empty,
155    SingleValue {
156        source_param: String,
157        flatten: bool,
158        ty: hir::TypeSpec,
159    },
160    Object {
161        fields: Vec<HttpRequestBodyField>,
162    },
163    Stream {
164        source_param: String,
165        item_ty: hir::TypeSpec,
166        codec: HttpStreamPayloadCodec,
167    },
168}
169
170#[derive(Debug, Clone, Serialize, Deserialize)]
171pub struct HttpRequestBodyField {
172    pub source_param: String,
173    pub field_name: String,
174    pub ty: hir::TypeSpec,
175    pub optional: bool,
176    pub flatten: bool,
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize)]
180pub struct HttpResponseMapping {
181    pub header: Vec<HttpOutputBinding>,
182    pub cookie: Vec<HttpOutputBinding>,
183    pub body: HttpResponseBodyMapping,
184    pub status: String,
185}
186
187#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct HttpOutputBinding {
189    pub source: HttpOutputSource,
190    pub wire_name: String,
191    pub ty: hir::TypeSpec,
192}
193
194#[derive(Debug, Clone, Serialize, Deserialize)]
195pub enum HttpOutputSource {
196    ReturnValue,
197    Param { name: String },
198}
199
200#[derive(Debug, Clone, Serialize, Deserialize)]
201pub struct HttpResponseBodyMapping {
202    pub content_type: Option<String>,
203    pub codec: Option<HttpBodyCodec>,
204    pub shape: HttpResponseBodyShape,
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize)]
208pub enum HttpResponseBodyShape {
209    Empty,
210    ReturnOnly {
211        ty: hir::TypeSpec,
212    },
213    SingleValue {
214        source: HttpOutputSource,
215        ty: hir::TypeSpec,
216    },
217    Object {
218        fields: Vec<HttpResponseBodyField>,
219    },
220    Stream {
221        item_source: HttpOutputSource,
222        item_ty: hir::TypeSpec,
223        codec: HttpStreamPayloadCodec,
224    },
225}
226
227#[derive(Debug, Clone, Serialize, Deserialize)]
228pub struct HttpResponseBodyField {
229    pub source: HttpOutputSource,
230    pub field_name: String,
231    pub ty: hir::TypeSpec,
232}
233
234#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
235pub enum HttpBodyCodec {
236    Json,
237    Text,
238    FormUrlEncoded,
239    Msgpack,
240}
241
242#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
243pub enum HttpStreamPayloadCodec {
244    Ndjson,
245    Sse,
246}
247
248#[derive(Debug, Clone, Serialize, Deserialize)]
249pub struct HttpInterface {
250    pub name: String,
251    pub module_path: Vec<String>,
252    pub operations: Vec<HttpOperation>,
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize)]
256pub struct RestHirDocument {
257    pub spec: hir::Specification,
258    pub document: HttpDocumentMetadata,
259    pub interfaces: Vec<HttpInterface>,
260}
261
262impl RestHirDocument {
263    pub fn from_props(props: &hir::ParserProperties) -> ParserResult<Self> {
264        let value = props
265            .get("rest_hir")
266            .cloned()
267            .ok_or_else(|| ParseError::Message("missing rest_hir properties".to_string()))?;
268        serde_json::from_value(value).map_err(|err| ParseError::Message(err.to_string()))
269    }
270
271    pub fn find_interface(&self, module_path: &[String], name: &str) -> Option<&HttpInterface> {
272        self.interfaces
273            .iter()
274            .find(|interface| interface.name == name && interface.module_path == module_path)
275    }
276}