diff --git a/proxmox-api-macro/src/api.rs b/proxmox-api-macro/src/api.rs index 4f511807..ef3e6102 100644 --- a/proxmox-api-macro/src/api.rs +++ b/proxmox-api-macro/src/api.rs @@ -47,7 +47,7 @@ pub struct Schema { pub description: Option, /// The specific schema type (Object, String, ...) - item: SchemaItem, + pub item: SchemaItem, /// The remaining key-value pairs the `SchemaItem` parser did not extract will be appended as /// builder-pattern method calls to this schema. @@ -100,6 +100,15 @@ impl TryFrom for Schema { } impl Schema { + fn blank(span: Span) -> Self { + Self { + span, + description: None, + item: SchemaItem::Inferred(span), + properties: Vec::new(), + } + } + fn to_typed_schema(&self, ts: &mut TokenStream) -> Result<(), Error> { self.item.to_schema( ts, @@ -148,7 +157,7 @@ impl Schema { } } -enum SchemaItem { +pub enum SchemaItem { Null, Boolean, Integer, @@ -317,7 +326,7 @@ impl SchemaItem { #[derive(Default)] /// Contains a sorted list of properties: -struct SchemaObject { +pub struct SchemaObject { properties: Vec<(FieldName, bool, Schema)>, } @@ -388,7 +397,7 @@ impl SchemaObject { } } -struct SchemaArray { +pub struct SchemaArray { item: Box, } diff --git a/proxmox-api-macro/src/api/method.rs b/proxmox-api-macro/src/api/method.rs index 9c7240a7..6d809023 100644 --- a/proxmox-api-macro/src/api/method.rs +++ b/proxmox-api-macro/src/api/method.rs @@ -140,42 +140,14 @@ fn handle_function_signature( let (pat_type, pat) = check_input_type(input)?; // For any named type which exists on the function signature... - let schema: &mut Schema = if let Some((_ident, _optional, schema)) = + if let Some((_ident, _optional, ref mut schema)) = input_schema.find_obj_property_by_ident_mut(&pat.ident.to_string()) { - match &mut schema.item { - // ... if it has no `type` property (item = SchemaItem::Inferred), get a mutable - // reference to the schema, so that we can... - SchemaItem::Inferred(_span) => schema, - // other types are fine: - _ => continue, - } + // try to infer the type in the schema if it is not specified explicitly: + util::infer_type(schema, &*pat_type.ty)?; } else { continue; }; - - // ... infer the type from the function parameters: - match &*pat_type.ty { - syn::Type::Path(path) if path.qself.is_none() => { - if path.path.is_ident("String") { - schema.item = SchemaItem::String; - continue; - } else if path.path.is_ident("bool") { - schema.item = SchemaItem::Boolean; - continue; - } else if super::INTNAMES.iter().any(|n| path.path.is_ident(n)) { - schema.item = SchemaItem::Integer; - continue; - } else if super::NUMBERNAMES.iter().any(|n| path.path.is_ident(n)) { - schema.item = SchemaItem::Number; - continue; - } - } - _ => (), - } - - // if we can't, bail out: - bail!(&pat_type.ty => "cannot infer parameter type from this rust type"); } for input in sig.inputs.iter() { diff --git a/proxmox-api-macro/src/util.rs b/proxmox-api-macro/src/util.rs index 588739fa..bcd20c79 100644 --- a/proxmox-api-macro/src/util.rs +++ b/proxmox-api-macro/src/util.rs @@ -10,7 +10,7 @@ use syn::Token; use failure::Error; -use crate::api::Schema; +use crate::api::{self, Schema, SchemaItem}; /// A more relaxed version of Ident which allows hyphens. /// @@ -441,3 +441,31 @@ pub fn derive_descriptions( Ok(()) } + +pub fn infer_type(schema: &mut Schema, ty: &syn::Type) -> Result<(), Error> { + if let SchemaItem::Inferred(_) = schema.item { + // + } else { + return Ok(()); + } + + // infer the type from a rust type: + match ty { + syn::Type::Path(path) if path.qself.is_none() => { + if path.path.is_ident("String") { + schema.item = SchemaItem::String; + } else if path.path.is_ident("bool") { + schema.item = SchemaItem::Boolean; + } else if api::INTNAMES.iter().any(|n| path.path.is_ident(n)) { + schema.item = SchemaItem::Integer; + } else if api::NUMBERNAMES.iter().any(|n| path.path.is_ident(n)) { + schema.item = SchemaItem::Number; + } else { + bail!(ty => "cannot infer parameter type from this rust type"); + } + } + _ => (), + } + + Ok(()) +}