api-macro: include default minimum/maximum for integer types

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2020-03-06 11:57:15 +01:00
parent f4e88aab6c
commit 723500dbfc
3 changed files with 50 additions and 7 deletions

View File

@ -14,8 +14,25 @@ mod enums;
mod method;
mod structs;
pub const INTNAMES: &[&str] = &[
"Integer", "i8", "i16", "i32", "i64", "isize", "u8", "u16", "u32", "u64", "usize",
pub struct IntType {
pub name: &'static str,
pub minimum: Option<&'static str>,
pub maximum: Option<&'static str>,
}
#[rustfmt::skip]
pub const INTTYPES: &[IntType] = &[
IntType { name: "Integer", minimum: None, maximum: None, },
IntType { name: "i8", minimum: Some("-0x80"), maximum: Some("0x7f"), },
IntType { name: "i16", minimum: Some("-0x8000"), maximum: Some("0x7fff"), },
IntType { name: "i32", minimum: Some("-0x80000000"), maximum: Some("0x7fffffff"), },
IntType { name: "i64", minimum: None, maximum: None, },
IntType { name: "isize", minimum: None, maximum: None, },
IntType { name: "u8", minimum: Some("0"), maximum: Some("0xff"), },
IntType { name: "u16", minimum: Some("0"), maximum: Some("0xffff"), },
IntType { name: "u32", minimum: Some("0"), maximum: Some("0xffffffff"), },
IntType { name: "u64", minimum: Some("0"), maximum: None, },
IntType { name: "usize", minimum: Some("0"), maximum: None, },
];
pub const NUMBERNAMES: &[&str] = &["Number", "f32", "f64"];
@ -164,6 +181,23 @@ impl Schema {
self.as_object_mut()
.and_then(|obj| obj.find_property_by_ident_mut(key))
}
// FIXME: Should we turn the property list into a map? We used to have no need to find keys in
// it, but we do now...
fn find_schema_property(&self, key: &str) -> Option<&syn::Expr> {
for prop in &self.properties {
if prop.0 == key {
return Some(&prop.1)
}
}
None
}
pub fn add_default_property(&mut self, key: &str, value: syn::Expr) {
if !self.find_schema_property(key).is_some() {
self.properties.push((Ident::new(key, Span::call_site()), value));
}
}
}
pub enum SchemaItem {
@ -220,7 +254,7 @@ impl SchemaItem {
Ok(SchemaItem::Null)
} else if name == "Boolean" || name == "bool" {
Ok(SchemaItem::Boolean)
} else if INTNAMES.iter().any(|n| name == n) {
} else if INTTYPES.iter().any(|n| name == n.name) {
Ok(SchemaItem::Integer)
} else if NUMBERNAMES.iter().any(|n| name == n) {
Ok(SchemaItem::Number)

View File

@ -2,7 +2,7 @@ use std::borrow::Borrow;
use std::collections::HashMap;
use std::convert::TryFrom;
use proc_macro2::{Ident, Span};
use proc_macro2::{Ident, Span, TokenStream};
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
@ -460,7 +460,7 @@ pub fn derive_descriptions(
Ok(())
}
pub fn infer_type(schema: &mut Schema, ty: &syn::Type) -> Result<bool, Error> {
pub fn infer_type(schema: &mut Schema, ty: &syn::Type) -> Result<bool, syn::Error> {
if let SchemaItem::Inferred(_) = schema.item {
//
} else {
@ -479,8 +479,14 @@ pub fn infer_type(schema: &mut Schema, ty: &syn::Type) -> Result<bool, Error> {
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)) {
} else if let Some(ty) = api::INTTYPES.iter().find(|i| path.path.is_ident(i.name)) {
schema.item = SchemaItem::Integer;
if let Some(min) = ty.minimum {
schema.add_default_property("minimum", syn::Expr::Verbatim(min.parse()?));
}
if let Some(max) = ty.maximum {
schema.add_default_property("maximum", syn::Expr::Verbatim(max.parse()?));
}
} else if api::NUMBERNAMES.iter().any(|n| path.path.is_ident(n)) {
schema.item = SchemaItem::Number;
} else {

View File

@ -41,7 +41,10 @@ fn number_schema_check() {
&[(
"num",
false,
&::proxmox::api::schema::IntegerSchema::new("The version to upgrade to").schema(),
&::proxmox::api::schema::IntegerSchema::new("The version to upgrade to")
.minimum(0)
.maximum(0xffffffff)
.schema(),
)],
),
)