use std::collections::HashMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct RestDescription {
pub name: String,
pub version: String,
pub title: Option<String>,
pub description: Option<String>,
pub canonical_name: Option<String>,
pub revision: Option<String>,
pub root_url: String,
#[serde(default)]
pub service_path: String,
pub base_url: Option<String>,
#[serde(default)]
pub schemas: HashMap<String, JsonSchema>,
#[serde(default)]
pub resources: HashMap<String, RestResource>,
#[serde(default)]
pub parameters: HashMap<String, MethodParameter>,
pub auth: Option<AuthDescription>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct AuthDescription {
pub oauth2: Option<OAuth2Description>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct OAuth2Description {
pub scopes: Option<HashMap<String, ScopeDescription>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ScopeDescription {
pub description: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct RestResource {
#[serde(default)]
pub methods: HashMap<String, RestMethod>,
#[serde(default)]
pub resources: HashMap<String, RestResource>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct RestMethod {
pub id: Option<String>,
pub description: Option<String>,
pub http_method: String,
pub path: String,
#[serde(default)]
pub parameters: HashMap<String, MethodParameter>,
#[serde(default)]
pub parameter_order: Vec<String>,
pub request: Option<SchemaRef>,
pub response: Option<SchemaRef>,
#[serde(default)]
pub scopes: Vec<String>,
pub flat_path: Option<String>,
#[serde(default)]
pub supports_media_download: bool,
#[serde(default)]
pub supports_media_upload: bool,
pub media_upload: Option<MediaUpload>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct MediaUpload {
pub protocols: Option<MediaUploadProtocols>,
#[serde(default)]
pub accept: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct MediaUploadProtocols {
pub simple: Option<MediaUploadProtocol>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct MediaUploadProtocol {
pub path: String,
pub multipart: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SchemaRef {
#[serde(rename = "$ref")]
pub schema_ref: Option<String>,
#[serde(rename = "parameterName")]
pub parameter_name: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct MethodParameter {
#[serde(rename = "type")]
pub param_type: Option<String>,
pub description: Option<String>,
pub location: Option<String>,
#[serde(default)]
pub required: bool,
pub format: Option<String>,
pub default: Option<serde_json::Value>,
#[serde(rename = "enum")]
pub enum_values: Option<Vec<String>>,
pub enum_descriptions: Option<Vec<String>>,
#[serde(default)]
pub repeated: bool,
pub minimum: Option<String>,
pub maximum: Option<String>,
#[serde(default)]
pub deprecated: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct JsonSchema {
pub id: Option<String>,
#[serde(rename = "type")]
pub schema_type: Option<String>,
pub description: Option<String>,
#[serde(default)]
pub deprecated: bool,
#[serde(default)]
pub properties: HashMap<String, JsonSchemaProperty>,
#[serde(rename = "$ref")]
pub schema_ref: Option<String>,
pub items: Option<Box<JsonSchemaProperty>>,
#[serde(default)]
pub required: Vec<String>,
pub additional_properties: Option<serde_json::Value>,
#[serde(rename = "enum")]
pub enum_values: Option<Vec<String>>,
pub enum_descriptions: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct JsonSchemaProperty {
#[serde(rename = "type")]
pub prop_type: Option<String>,
pub description: Option<String>,
#[serde(rename = "$ref")]
pub schema_ref: Option<String>,
pub format: Option<String>,
pub items: Option<Box<JsonSchemaProperty>>,
#[serde(default)]
pub properties: HashMap<String, JsonSchemaProperty>,
#[serde(default)]
pub read_only: bool,
pub default: Option<serde_json::Value>,
#[serde(rename = "enum")]
pub enum_values: Option<Vec<String>>,
pub enum_descriptions: Option<Vec<String>>,
pub additional_properties: Option<serde_json::Value>,
pub annotations: Option<serde_json::Value>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deserialize_minimal_rest_description() {
let json = r#"{
"name": "drive",
"version": "v3",
"rootUrl": "https://www.googleapis.com/",
"servicePath": "drive/v3/",
"resources": {
"files": {
"methods": {
"list": {
"httpMethod": "GET",
"path": "files",
"response": { "$ref": "FileList" }
}
}
}
},
"schemas": {
"FileList": {
"id": "FileList",
"type": "object",
"properties": {
"files": {
"type": "array",
"items": { "$ref": "File" }
}
}
}
}
}"#;
let doc: RestDescription = serde_json::from_str(json).expect("parse");
assert_eq!(doc.name, "drive");
assert_eq!(doc.version, "v3");
let files = doc.resources.get("files").expect("files");
let list = files.methods.get("list").expect("list");
assert_eq!(list.http_method, "GET");
assert_eq!(list.path, "files");
}
}