mirror of
https://git.proxmox.com/git/proxmox
synced 2025-08-07 11:06:02 +00:00
api/macro: add NumberSchema
Adapted from the integer schema, uses f64 type. Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com> Cc: Wolfgang Bumiller <w.bumiller@proxmox.com> Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
81cac5fc29
commit
13007df318
@ -17,6 +17,9 @@ mod structs;
|
|||||||
pub const INTNAMES: &[&str] = &[
|
pub const INTNAMES: &[&str] = &[
|
||||||
"Integer", "i8", "i16", "i32", "i64", "isize", "u8", "u16", "u32", "u64", "usize",
|
"Integer", "i8", "i16", "i32", "i64", "isize", "u8", "u16", "u32", "u64", "usize",
|
||||||
];
|
];
|
||||||
|
pub const NUMBERNAMES: &[&str] = &[
|
||||||
|
"Number", "f32", "f64",
|
||||||
|
];
|
||||||
|
|
||||||
/// The main `Schema` type.
|
/// The main `Schema` type.
|
||||||
///
|
///
|
||||||
@ -151,6 +154,7 @@ enum SchemaItem {
|
|||||||
Null,
|
Null,
|
||||||
Boolean,
|
Boolean,
|
||||||
Integer,
|
Integer,
|
||||||
|
Number,
|
||||||
String,
|
String,
|
||||||
Object(SchemaObject),
|
Object(SchemaObject),
|
||||||
Array(SchemaArray),
|
Array(SchemaArray),
|
||||||
@ -202,6 +206,8 @@ impl SchemaItem {
|
|||||||
Ok(SchemaItem::Boolean)
|
Ok(SchemaItem::Boolean)
|
||||||
} else if INTNAMES.iter().any(|n| name == n) {
|
} else if INTNAMES.iter().any(|n| name == n) {
|
||||||
Ok(SchemaItem::Integer)
|
Ok(SchemaItem::Integer)
|
||||||
|
} else if NUMBERNAMES.iter().any(|n| name == n) {
|
||||||
|
Ok(SchemaItem::Number)
|
||||||
} else if name == "String" {
|
} else if name == "String" {
|
||||||
Ok(SchemaItem::String)
|
Ok(SchemaItem::String)
|
||||||
} else if name == "Object" {
|
} else if name == "Object" {
|
||||||
@ -235,6 +241,10 @@ impl SchemaItem {
|
|||||||
let description = description?;
|
let description = description?;
|
||||||
ts.extend(quote! { ::proxmox::api::schema::IntegerSchema::new(#description) });
|
ts.extend(quote! { ::proxmox::api::schema::IntegerSchema::new(#description) });
|
||||||
}
|
}
|
||||||
|
SchemaItem::Number => {
|
||||||
|
let description = description?;
|
||||||
|
ts.extend(quote! { ::proxmox::api::schema::NumberSchema::new(#description) });
|
||||||
|
}
|
||||||
SchemaItem::String => {
|
SchemaItem::String => {
|
||||||
let description = description?;
|
let description = description?;
|
||||||
ts.extend(quote! { ::proxmox::api::schema::StringSchema::new(#description) });
|
ts.extend(quote! { ::proxmox::api::schema::StringSchema::new(#description) });
|
||||||
|
@ -204,6 +204,9 @@ fn handle_function_signature(
|
|||||||
} else if super::INTNAMES.iter().any(|n| path.path.is_ident(n)) {
|
} else if super::INTNAMES.iter().any(|n| path.path.is_ident(n)) {
|
||||||
schema.item = SchemaItem::Integer;
|
schema.item = SchemaItem::Integer;
|
||||||
continue;
|
continue;
|
||||||
|
} else if super::NUMBERNAMES.iter().any(|n| path.path.is_ident(n)) {
|
||||||
|
schema.item = SchemaItem::Number;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -87,6 +87,12 @@ pub fn get_schema_type_text(schema: &Schema, _style: ParameterDisplayStyle) -> S
|
|||||||
(None, Some(max)) => format!("<integer> (-N - {})", max),
|
(None, Some(max)) => format!("<integer> (-N - {})", max),
|
||||||
_ => String::from("<integer>"),
|
_ => String::from("<integer>"),
|
||||||
},
|
},
|
||||||
|
Schema::Number(number_schema) => match (number_schema.minimum, number_schema.maximum) {
|
||||||
|
(Some(min), Some(max)) => format!("<number> ({} - {})", min, max),
|
||||||
|
(Some(min), None) => format!("<number> ({} - N)", min),
|
||||||
|
(None, Some(max)) => format!("<number> (-N - {})", max),
|
||||||
|
_ => String::from("<integer>"),
|
||||||
|
},
|
||||||
Schema::Object(_) => String::from("<object>"),
|
Schema::Object(_) => String::from("<object>"),
|
||||||
Schema::Array(_) => String::from("<array>"),
|
Schema::Array(_) => String::from("<array>"),
|
||||||
}
|
}
|
||||||
@ -106,6 +112,7 @@ pub fn get_property_description(
|
|||||||
Schema::String(ref schema) => (schema.description, schema.default.map(|v| v.to_owned())),
|
Schema::String(ref schema) => (schema.description, schema.default.map(|v| v.to_owned())),
|
||||||
Schema::Boolean(ref schema) => (schema.description, schema.default.map(|v| v.to_string())),
|
Schema::Boolean(ref schema) => (schema.description, schema.default.map(|v| v.to_string())),
|
||||||
Schema::Integer(ref schema) => (schema.description, schema.default.map(|v| v.to_string())),
|
Schema::Integer(ref schema) => (schema.description, schema.default.map(|v| v.to_string())),
|
||||||
|
Schema::Number(ref schema) => (schema.description, schema.default.map(|v| v.to_string())),
|
||||||
Schema::Object(ref schema) => (schema.description, None),
|
Schema::Object(ref schema) => (schema.description, None),
|
||||||
Schema::Array(ref schema) => (schema.description, None),
|
Schema::Array(ref schema) => (schema.description, None),
|
||||||
};
|
};
|
||||||
@ -211,6 +218,10 @@ fn dump_api_return_schema(schema: &Schema) -> String {
|
|||||||
let description = wrap_text("", "", schema.description, 80);
|
let description = wrap_text("", "", schema.description, 80);
|
||||||
res.push_str(&description);
|
res.push_str(&description);
|
||||||
}
|
}
|
||||||
|
Schema::Number(schema) => {
|
||||||
|
let description = wrap_text("", "", schema.description, 80);
|
||||||
|
res.push_str(&description);
|
||||||
|
}
|
||||||
Schema::String(schema) => {
|
Schema::String(schema) => {
|
||||||
let description = wrap_text("", "", schema.description, 80);
|
let description = wrap_text("", "", schema.description, 80);
|
||||||
res.push_str(&description);
|
res.push_str(&description);
|
||||||
|
@ -155,6 +155,73 @@ impl IntegerSchema {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Data type to describe (JSON like) number value
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NumberSchema {
|
||||||
|
pub description: &'static str,
|
||||||
|
/// Optional minimum.
|
||||||
|
pub minimum: Option<f64>,
|
||||||
|
/// Optional maximum.
|
||||||
|
pub maximum: Option<f64>,
|
||||||
|
/// Optional default.
|
||||||
|
pub default: Option<f64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NumberSchema {
|
||||||
|
pub const fn new(description: &'static str) -> Self {
|
||||||
|
NumberSchema {
|
||||||
|
description,
|
||||||
|
default: None,
|
||||||
|
minimum: None,
|
||||||
|
maximum: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn default(mut self, default: f64) -> Self {
|
||||||
|
self.default = Some(default);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn minimum(mut self, minimum: f64) -> Self {
|
||||||
|
self.minimum = Some(minimum);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn maximum(mut self, maximium: f64) -> Self {
|
||||||
|
self.maximum = Some(maximium);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn schema(self) -> Schema {
|
||||||
|
Schema::Number(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_constraints(&self, value: f64) -> Result<(), Error> {
|
||||||
|
if let Some(minimum) = self.minimum {
|
||||||
|
if value < minimum {
|
||||||
|
bail!(
|
||||||
|
"value must have a minimum value of {} (got {})",
|
||||||
|
minimum,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(maximum) = self.maximum {
|
||||||
|
if value > maximum {
|
||||||
|
bail!(
|
||||||
|
"value must have a maximum value of {} (got {})",
|
||||||
|
maximum,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Data type to describe string values.
|
/// Data type to describe string values.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StringSchema {
|
pub struct StringSchema {
|
||||||
@ -402,6 +469,7 @@ pub enum Schema {
|
|||||||
Null,
|
Null,
|
||||||
Boolean(BooleanSchema),
|
Boolean(BooleanSchema),
|
||||||
Integer(IntegerSchema),
|
Integer(IntegerSchema),
|
||||||
|
Number(NumberSchema),
|
||||||
String(StringSchema),
|
String(StringSchema),
|
||||||
Object(ObjectSchema),
|
Object(ObjectSchema),
|
||||||
Array(ArraySchema),
|
Array(ArraySchema),
|
||||||
@ -550,6 +618,11 @@ pub fn parse_simple_value(value_str: &str, schema: &Schema) -> Result<Value, Err
|
|||||||
integer_schema.check_constraints(res)?;
|
integer_schema.check_constraints(res)?;
|
||||||
Value::Number(res.into())
|
Value::Number(res.into())
|
||||||
}
|
}
|
||||||
|
Schema::Number(number_schema) => {
|
||||||
|
let res: f64 = value_str.parse()?;
|
||||||
|
number_schema.check_constraints(res)?;
|
||||||
|
Value::Number(serde_json::Number::from_f64(res).unwrap())
|
||||||
|
}
|
||||||
Schema::String(string_schema) => {
|
Schema::String(string_schema) => {
|
||||||
string_schema.check_constraints(value_str)?;
|
string_schema.check_constraints(value_str)?;
|
||||||
Value::String(value_str.into())
|
Value::String(value_str.into())
|
||||||
@ -683,6 +756,7 @@ pub fn verify_json(data: &Value, schema: &Schema) -> Result<(), Error> {
|
|||||||
}
|
}
|
||||||
Schema::Boolean(boolean_schema) => verify_json_boolean(data, &boolean_schema)?,
|
Schema::Boolean(boolean_schema) => verify_json_boolean(data, &boolean_schema)?,
|
||||||
Schema::Integer(integer_schema) => verify_json_integer(data, &integer_schema)?,
|
Schema::Integer(integer_schema) => verify_json_integer(data, &integer_schema)?,
|
||||||
|
Schema::Number(number_schema) => verify_json_number(data, &number_schema)?,
|
||||||
Schema::String(string_schema) => verify_json_string(data, &string_schema)?,
|
Schema::String(string_schema) => verify_json_string(data, &string_schema)?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -714,6 +788,15 @@ pub fn verify_json_integer(data: &Value, schema: &IntegerSchema) -> Result<(), E
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Verify JSON value using an `NumberSchema`.
|
||||||
|
pub fn verify_json_number(data: &Value, schema: &NumberSchema) -> Result<(), Error> {
|
||||||
|
if let Some(value) = data.as_f64() {
|
||||||
|
schema.check_constraints(value)
|
||||||
|
} else {
|
||||||
|
bail!("Expected number value.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Verify JSON value using an `ArraySchema`.
|
/// Verify JSON value using an `ArraySchema`.
|
||||||
pub fn verify_json_array(data: &Value, schema: &ArraySchema) -> Result<(), Error> {
|
pub fn verify_json_array(data: &Value, schema: &ArraySchema) -> Result<(), Error> {
|
||||||
let list = match data {
|
let list = match data {
|
||||||
|
Loading…
Reference in New Issue
Block a user