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