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>,
|
||||
|
||||
/// 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<JSONObject> 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<Schema>,
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user