From dce9102163d6bc5159b8620d86acd45424293559 Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Tue, 7 Jan 2025 17:40:24 +0100 Subject: [PATCH] api-macro: add json_schema!() macro This allows using the json schema notation to generate `Schema` expressions. Signed-off-by: Wolfgang Bumiller --- proxmox-api-macro/src/api/mod.rs | 10 ++++++++++ proxmox-api-macro/src/lib.rs | 18 ++++++++++++++++++ proxmox-api-macro/tests/types.rs | 20 +++++++++++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/proxmox-api-macro/src/api/mod.rs b/proxmox-api-macro/src/api/mod.rs index e346101b..416ea56e 100644 --- a/proxmox-api-macro/src/api/mod.rs +++ b/proxmox-api-macro/src/api/mod.rs @@ -761,3 +761,13 @@ pub(crate) fn api(attr: TokenStream, item: TokenStream) -> Result bail!(item => "api macro only works on functions"), } } + +/// Directly convert a json schema into a `Schema` expression. +pub(crate) fn json_schema(item: TokenStream) -> Result { + let attribs = JSONObject::parse_inner.parse2(item)?; + let schema: Schema = attribs.try_into()?; + + let mut ts = TokenStream::new(); + schema.to_schema(&mut ts)?; + Ok(ts) +} diff --git a/proxmox-api-macro/src/lib.rs b/proxmox-api-macro/src/lib.rs index 0d401f31..bc05c74f 100644 --- a/proxmox-api-macro/src/lib.rs +++ b/proxmox-api-macro/src/lib.rs @@ -295,6 +295,24 @@ pub fn api(attr: TokenStream_1, item: TokenStream_1) -> TokenStream_1 { handle_error(item.clone(), api::api(attr.into(), item)).into() } +/// *Experimental:* Transform a json-like schema definition into an expression yielding a `Schema`. +/// +/// This is currently considered experimental as it should not be required for normal code. +#[proc_macro] +pub fn json_schema(item: TokenStream_1) -> TokenStream_1 { + let _error_guard = init_local_error(); + let item: TokenStream = item.into(); + let mut output = take_non_fatal_errors(); + match api::json_schema(item) { + Ok(ts) => output.extend(ts), + Err(err) => match err.downcast::() { + Ok(err) => output.extend(err.to_compile_error()), + Err(err) => panic!("error in json_schema!() macro: {err}"), + }, + } + quote::quote!({ #output }).into() +} + /// This is a dummy derive macro actually handled by `#[api]`! #[doc(hidden)] #[proc_macro_derive(Updater, attributes(updater, serde))] diff --git a/proxmox-api-macro/tests/types.rs b/proxmox-api-macro/tests/types.rs index e645fa84..5c6f97c8 100644 --- a/proxmox-api-macro/tests/types.rs +++ b/proxmox-api-macro/tests/types.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; -use proxmox_api_macro::api; +use proxmox_api_macro::{api, json_schema}; use proxmox_schema as schema; use proxmox_schema::{ApiType, EnumEntry}; @@ -68,6 +68,24 @@ fn test_struct() { .schema(); assert_eq!(TEST_SCHEMA, TestStruct::API_SCHEMA); + + const TEST_JSON_SCHEMA: ::proxmox_schema::Schema = json_schema! { + description: "An example of a simple struct type.", + properties: { + another: { + type: String, + description: "An optional auto-derived value for testing:", + optional: true, + }, + test_string: { + type: String, + description: "A test string.", + optional: false, + }, + }, + }; + + assert_eq!(TEST_SCHEMA, TEST_JSON_SCHEMA); } #[api]