diff --git a/proxmox-api-macro/src/api.rs b/proxmox-api-macro/src/api.rs index 6f32933b..1e33c08d 100644 --- a/proxmox-api-macro/src/api.rs +++ b/proxmox-api-macro/src/api.rs @@ -129,14 +129,6 @@ struct JSONObject { pub elements: HashMap, } -//impl TryFrom for JSONObject { -// type Error = syn::Error; -// -// fn try_from(value: JSONValue) -> Result { -// value.into_object() -// } -//} - impl Parse for JSONObject { fn parse(input: ParseStream) -> syn::Result { let content; @@ -157,15 +149,25 @@ impl Parse for JSONObject { } } +impl std::ops::Deref for JSONObject { + type Target = HashMap; + + fn deref(&self) -> &Self::Target { + &self.elements + } +} + +impl std::ops::DerefMut for JSONObject { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.elements + } +} + impl JSONObject { fn span(&self) -> Span { self.brace_token.span } - fn remove(&mut self, name: &str) -> Option { - self.elements.remove(name) - } - fn remove_required_element(&mut self, name: &str) -> Result { self.remove(name) .ok_or_else(|| format_err!(self.span(), "missing required element: {}", name)) @@ -309,8 +311,23 @@ enum SchemaItem { } impl SchemaItem { + /// If there's a `type` specified, parse it as that type. Otherwise check for keys which + /// uniqueply identify the type, such as "properties" for type `Object`. fn try_extract_from(obj: &mut JSONObject) -> Result { - match SimpleIdent::try_from(obj.remove_required_element("type")?)?.as_str() { + let ty = obj.remove("type").map(SimpleIdent::try_from).transpose()?; + let ty = match &ty { + Some(ty) => ty.as_str(), + None => { + if obj.contains_key("properties") { + "Object" + } else if obj.contains_key("items") { + "Array" + } else { + bail!(obj.span(), "failed to guess 'type' in schema definition"); + } + } + }; + match ty { "Null" => Ok(SchemaItem::Null), "Boolean" => Ok(SchemaItem::Boolean), "Integer" => Ok(SchemaItem::Integer), diff --git a/proxmox-api-macro/tests/api1.rs b/proxmox-api-macro/tests/api1.rs index 34b1a11a..2b4a726b 100644 --- a/proxmox-api-macro/tests/api1.rs +++ b/proxmox-api-macro/tests/api1.rs @@ -8,7 +8,6 @@ use serde_json::Value; #[api] #[input({ - type: Object, properties: { username: { type: String, @@ -22,7 +21,6 @@ use serde_json::Value; } })] #[returns({ - type: Object, description: "Returns a ticket", properties: { "username": {