api-macro: generalized '{ schema: PATH }' schemas

allow 'schema: PATH' outside object property context

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2019-12-16 12:11:52 +01:00
parent 808035f524
commit 3e5927a1b4
3 changed files with 51 additions and 0 deletions

View File

@ -155,6 +155,7 @@ enum SchemaItem {
Object(SchemaObject), Object(SchemaObject),
Array(SchemaArray), Array(SchemaArray),
ExternType(ExprPath), ExternType(ExprPath),
ExternSchema(ExprPath),
Inferred(Span), Inferred(Span),
} }
@ -162,6 +163,10 @@ impl SchemaItem {
/// If there's a `type` specified, parse it as that type. Otherwise check for keys which /// If there's a `type` specified, parse it as that type. Otherwise check for keys which
/// uniqueply identify the type, such as "properties" for type `Object`. /// uniqueply identify the type, such as "properties" for type `Object`.
fn try_extract_from(obj: &mut JSONObject) -> Result<Self, syn::Error> { fn try_extract_from(obj: &mut JSONObject) -> Result<Self, syn::Error> {
if let Some(ext) = obj.remove("schema").map(ExprPath::try_from).transpose()? {
return Ok(SchemaItem::ExternSchema(ext));
}
let ty = obj.remove("type").map(ExprPath::try_from).transpose()?; let ty = obj.remove("type").map(ExprPath::try_from).transpose()?;
let ty = match ty { let ty = match ty {
Some(ty) => ty, Some(ty) => ty,
@ -257,6 +262,13 @@ impl SchemaItem {
ts.extend(quote_spanned! { path.span() => #path::API_SCHEMA }); ts.extend(quote_spanned! { path.span() => #path::API_SCHEMA });
return Ok(true); return Ok(true);
} }
SchemaItem::ExternSchema(path) => {
if !properties.is_empty() {
bail!(&properties[0].0 => "additional properties not allowed on schema ref");
}
ts.extend(quote_spanned! { path.span() => &#path });
return Ok(true);
}
SchemaItem::Inferred(span) => { SchemaItem::Inferred(span) => {
bail!(*span, "failed to guess 'type' in schema definition"); bail!(*span, "failed to guess 'type' in schema definition");
} }

View File

@ -31,3 +31,23 @@ pub fn hello(message: String) -> Result<(), Error> {
pub async fn number(num: u32) -> Result<u32, Error> { pub async fn number(num: u32) -> Result<u32, Error> {
Ok(num) Ok(num)
} }
#[api(
input: {
properties: {
foo: {
type: String,
description: "The great Foo",
},
bar: {
type: String,
description: "The great Bar",
},
},
},
)]
/// Return the number...
pub async fn more_async_params(param: Value) -> Result<(), Error> {
let _ = param;
Ok(())
}

View File

@ -40,3 +40,22 @@ pub fn get_archive_2(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Va
let _ = rpcenv; let _ = rpcenv;
Ok(json!("test")) Ok(json!("test"))
} }
#[api(
input: {
properties: {
"data": {
description: "The data",
type: Array,
items: {
schema: NAME_SCHEMA,
}
}
}
}
)]
/// Get data.
pub fn get_data(param: Value) -> Result<(), Error> {
let _ = param;
Ok(())
}