api-macro: support defining schemas for structs

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2019-11-28 11:15:37 +01:00
parent 4f042f8133
commit 6818cf76c9
3 changed files with 48 additions and 6 deletions

View File

@ -11,6 +11,7 @@ use syn::{ExprPath, Ident};
use crate::util::{JSONObject, JSONValue};
mod method;
mod structs;
/// The main `Schema` type.
///
@ -353,7 +354,8 @@ pub(crate) fn api(attr: TokenStream, item: TokenStream) -> Result<TokenStream, E
let item: syn::Item = syn::parse2(item)?;
match item {
syn::Item::Fn(func) => method::handle_method(attribs, func),
syn::Item::Fn(item) => method::handle_method(attribs, item),
syn::Item::Struct(item) => structs::handle_struct(attribs, item),
_ => bail!(item => "api macro only works on functions"),
}
}

View File

@ -0,0 +1,31 @@
use std::convert::TryInto;
use failure::Error;
use proc_macro2::TokenStream;
use quote::quote_spanned;
use super::Schema;
use crate::util::JSONObject;
/// Parse `input`, `returns` and `protected` attributes out of an function annotated
/// with an `#[api]` attribute and produce a `const ApiMethod` named after the function.
///
/// See the top level macro documentation for a complete example.
pub fn handle_struct(attribs: JSONObject, stru: syn::ItemStruct) -> Result<TokenStream, Error> {
let schema = {
let schema: Schema = attribs.try_into()?;
let mut ts = TokenStream::new();
schema.to_schema(&mut ts)?;
ts
};
let name = &stru.ident;
Ok(quote_spanned! { name.span() =>
#stru
impl #name {
pub const API_SCHEMA: &'static ::proxmox::api::schema::Schema = #schema;
}
})
}

View File

@ -5,12 +5,20 @@ use proxmox::api::schema;
use proxmox_api_macro::api;
use failure::Error;
use serde::{Deserialize, Serialize};
//use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Clone, Debug, Deserialize, Serialize)]
#[api(
type: String,
description: "A string",
format: &schema::ApiStringFormat::Enum(&["ok", "not-ok"]),
)]
//#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OkString(String);
// generates the following without the '_' prefix in the constant:
impl OkString {
pub const API_SCHEMA: &'static schema::Schema = &schema::StringSchema::new("A string")
pub const _API_SCHEMA: &'static schema::Schema = &schema::StringSchema::new("A string")
.format(&schema::ApiStringFormat::Enum(&["ok", "not-ok"]))
.schema();
}
@ -27,6 +35,7 @@ impl OkString {
/// Check a string.
///
/// Returns: Whether the string was "ok".
pub fn string_check(arg: OkString) -> Result<bool, Error> {
Ok(arg.0 == "ok")
pub fn string_check(arg: Value) -> Result<bool, Error> {
let _ = arg;
panic!("body")
}