diff --git a/proxmox-api-macro/src/api.rs b/proxmox-api-macro/src/api.rs index 75973927..6a88671e 100644 --- a/proxmox-api-macro/src/api.rs +++ b/proxmox-api-macro/src/api.rs @@ -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 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"), } } diff --git a/proxmox-api-macro/src/api/structs.rs b/proxmox-api-macro/src/api/structs.rs new file mode 100644 index 00000000..8be40b70 --- /dev/null +++ b/proxmox-api-macro/src/api/structs.rs @@ -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 { + 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; + } + }) +} diff --git a/proxmox-api-macro/tests/types.rs b/proxmox-api-macro/tests/types.rs index 916c2ffc..43f256a0 100644 --- a/proxmox-api-macro/tests/types.rs +++ b/proxmox-api-macro/tests/types.rs @@ -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 { - Ok(arg.0 == "ok") +pub fn string_check(arg: Value) -> Result { + let _ = arg; + panic!("body") }