forked from proxmox-mirrors/proxmox
api-macro: factor out type inference for reuse with structs
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
b9769de6b6
commit
e960a68b60
@ -47,7 +47,7 @@ pub struct Schema {
|
|||||||
pub description: Option<syn::LitStr>,
|
pub description: Option<syn::LitStr>,
|
||||||
|
|
||||||
/// The specific schema type (Object, String, ...)
|
/// 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
|
/// The remaining key-value pairs the `SchemaItem` parser did not extract will be appended as
|
||||||
/// builder-pattern method calls to this schema.
|
/// builder-pattern method calls to this schema.
|
||||||
@ -100,6 +100,15 @@ impl TryFrom<JSONObject> for Schema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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> {
|
fn to_typed_schema(&self, ts: &mut TokenStream) -> Result<(), Error> {
|
||||||
self.item.to_schema(
|
self.item.to_schema(
|
||||||
ts,
|
ts,
|
||||||
@ -148,7 +157,7 @@ impl Schema {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SchemaItem {
|
pub enum SchemaItem {
|
||||||
Null,
|
Null,
|
||||||
Boolean,
|
Boolean,
|
||||||
Integer,
|
Integer,
|
||||||
@ -317,7 +326,7 @@ impl SchemaItem {
|
|||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
/// Contains a sorted list of properties:
|
/// Contains a sorted list of properties:
|
||||||
struct SchemaObject {
|
pub struct SchemaObject {
|
||||||
properties: Vec<(FieldName, bool, Schema)>,
|
properties: Vec<(FieldName, bool, Schema)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,7 +397,7 @@ impl SchemaObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SchemaArray {
|
pub struct SchemaArray {
|
||||||
item: Box<Schema>,
|
item: Box<Schema>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,42 +140,14 @@ fn handle_function_signature(
|
|||||||
let (pat_type, pat) = check_input_type(input)?;
|
let (pat_type, pat) = check_input_type(input)?;
|
||||||
|
|
||||||
// For any named type which exists on the function signature...
|
// 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())
|
input_schema.find_obj_property_by_ident_mut(&pat.ident.to_string())
|
||||||
{
|
{
|
||||||
match &mut schema.item {
|
// try to infer the type in the schema if it is not specified explicitly:
|
||||||
// ... if it has no `type` property (item = SchemaItem::Inferred), get a mutable
|
util::infer_type(schema, &*pat_type.ty)?;
|
||||||
// reference to the schema, so that we can...
|
|
||||||
SchemaItem::Inferred(_span) => schema,
|
|
||||||
// other types are fine:
|
|
||||||
_ => continue,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
continue;
|
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() {
|
for input in sig.inputs.iter() {
|
||||||
|
@ -10,7 +10,7 @@ use syn::Token;
|
|||||||
|
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
use crate::api::Schema;
|
use crate::api::{self, Schema, SchemaItem};
|
||||||
|
|
||||||
/// A more relaxed version of Ident which allows hyphens.
|
/// A more relaxed version of Ident which allows hyphens.
|
||||||
///
|
///
|
||||||
@ -441,3 +441,31 @@ pub fn derive_descriptions(
|
|||||||
|
|
||||||
Ok(())
|
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(())
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user