1use std::collections::HashMap;
4
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize, Default)]
9#[serde(rename_all = "camelCase")]
10pub struct RestDescription {
11 pub name: String,
12 pub version: String,
13 pub title: Option<String>,
14 pub description: Option<String>,
15 pub canonical_name: Option<String>,
17 pub revision: Option<String>,
19 pub root_url: String,
20 #[serde(default)]
21 pub service_path: String,
22 pub base_url: Option<String>,
23 #[serde(default)]
24 pub schemas: HashMap<String, JsonSchema>,
25 #[serde(default)]
26 pub resources: HashMap<String, RestResource>,
27 #[serde(default)]
28 pub parameters: HashMap<String, MethodParameter>,
29 pub auth: Option<AuthDescription>,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize, Default)]
33pub struct AuthDescription {
34 pub oauth2: Option<OAuth2Description>,
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize, Default)]
38pub struct OAuth2Description {
39 pub scopes: Option<HashMap<String, ScopeDescription>>,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize, Default)]
43pub struct ScopeDescription {
44 pub description: Option<String>,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize, Default)]
49pub struct RestResource {
50 #[serde(default)]
51 pub methods: HashMap<String, RestMethod>,
52 #[serde(default)]
53 pub resources: HashMap<String, RestResource>,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize, Default)]
58#[serde(rename_all = "camelCase")]
59pub struct RestMethod {
60 pub id: Option<String>,
61 pub description: Option<String>,
62 pub http_method: String,
63 pub path: String,
64 #[serde(default)]
65 pub parameters: HashMap<String, MethodParameter>,
66 #[serde(default)]
67 pub parameter_order: Vec<String>,
68 pub request: Option<SchemaRef>,
69 pub response: Option<SchemaRef>,
70 #[serde(default)]
71 pub scopes: Vec<String>,
72 pub flat_path: Option<String>,
73 #[serde(default)]
74 pub supports_media_download: bool,
75 #[serde(default)]
76 pub supports_media_upload: bool,
77 pub media_upload: Option<MediaUpload>,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize, Default)]
81pub struct MediaUpload {
82 pub protocols: Option<MediaUploadProtocols>,
83 #[serde(default)]
84 pub accept: Vec<String>,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize, Default)]
88pub struct MediaUploadProtocols {
89 pub simple: Option<MediaUploadProtocol>,
90}
91
92#[derive(Debug, Clone, Serialize, Deserialize, Default)]
93pub struct MediaUploadProtocol {
94 pub path: String,
95 pub multipart: Option<bool>,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize, Default)]
101pub struct SchemaRef {
102 #[serde(rename = "$ref")]
103 pub schema_ref: Option<String>,
104 #[serde(rename = "parameterName")]
105 pub parameter_name: Option<String>,
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize, Default)]
110#[serde(rename_all = "camelCase")]
111pub struct MethodParameter {
112 #[serde(rename = "type")]
113 pub param_type: Option<String>,
114 pub description: Option<String>,
115 pub location: Option<String>,
116 #[serde(default)]
117 pub required: bool,
118 pub format: Option<String>,
119 pub default: Option<serde_json::Value>,
120 #[serde(rename = "enum")]
121 pub enum_values: Option<Vec<String>>,
122 pub enum_descriptions: Option<Vec<String>>,
123 #[serde(default)]
124 pub repeated: bool,
125 pub minimum: Option<String>,
126 pub maximum: Option<String>,
127 #[serde(default)]
128 pub deprecated: bool,
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize, Default)]
133#[serde(rename_all = "camelCase")]
134pub struct JsonSchema {
135 pub id: Option<String>,
136 #[serde(rename = "type")]
137 pub schema_type: Option<String>,
138 pub description: Option<String>,
139 #[serde(default)]
140 pub deprecated: bool,
141 #[serde(default)]
142 pub properties: HashMap<String, JsonSchemaProperty>,
143 #[serde(rename = "$ref")]
144 pub schema_ref: Option<String>,
145 pub items: Option<Box<JsonSchemaProperty>>,
146 #[serde(default)]
147 pub required: Vec<String>,
148 pub additional_properties: Option<serde_json::Value>,
149 #[serde(rename = "enum")]
150 pub enum_values: Option<Vec<String>>,
151 pub enum_descriptions: Option<Vec<String>>,
152}
153
154#[derive(Debug, Clone, Serialize, Deserialize, Default)]
156#[serde(rename_all = "camelCase")]
157pub struct JsonSchemaProperty {
158 #[serde(rename = "type")]
159 pub prop_type: Option<String>,
160 pub description: Option<String>,
161 #[serde(rename = "$ref")]
162 pub schema_ref: Option<String>,
163 pub format: Option<String>,
164 pub items: Option<Box<JsonSchemaProperty>>,
165 #[serde(default)]
166 pub properties: HashMap<String, JsonSchemaProperty>,
167 #[serde(default)]
168 pub read_only: bool,
169 pub default: Option<serde_json::Value>,
170 #[serde(rename = "enum")]
171 pub enum_values: Option<Vec<String>>,
172 pub enum_descriptions: Option<Vec<String>>,
173 pub additional_properties: Option<serde_json::Value>,
174 pub annotations: Option<serde_json::Value>,
176}
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181
182 #[test]
183 fn deserialize_minimal_rest_description() {
184 let json = r#"{
185 "name": "drive",
186 "version": "v3",
187 "rootUrl": "https://www.googleapis.com/",
188 "servicePath": "drive/v3/",
189 "resources": {
190 "files": {
191 "methods": {
192 "list": {
193 "httpMethod": "GET",
194 "path": "files",
195 "response": { "$ref": "FileList" }
196 }
197 }
198 }
199 },
200 "schemas": {
201 "FileList": {
202 "id": "FileList",
203 "type": "object",
204 "properties": {
205 "files": {
206 "type": "array",
207 "items": { "$ref": "File" }
208 }
209 }
210 }
211 }
212 }"#;
213
214 let doc: RestDescription = serde_json::from_str(json).expect("parse");
215 assert_eq!(doc.name, "drive");
216 assert_eq!(doc.version, "v3");
217 let files = doc.resources.get("files").expect("files");
218 let list = files.methods.get("list").expect("list");
219 assert_eq!(list.http_method, "GET");
220 assert_eq!(list.path, "files");
221 }
222}