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}