From d79f0f56b020f0e7ac4a521fb1979faa8cc982c6 Mon Sep 17 00:00:00 2001 From: Graham Esau Date: Mon, 5 Aug 2019 13:16:06 +0100 Subject: [PATCH] Schema now implements MakeSchema --- schemars/src/{generator.rs => gen.rs} | 0 schemars/src/lib.rs | 4 +-- schemars/src/main.rs | 47 ++------------------------- schemars/src/make_schema.rs | 8 ++--- schemars/src/schema.rs | 12 ++++--- schemars_derive/src/lib.rs | 18 +++++++--- 6 files changed, 30 insertions(+), 59 deletions(-) rename schemars/src/{generator.rs => gen.rs} (100%) diff --git a/schemars/src/generator.rs b/schemars/src/gen.rs similarity index 100% rename from schemars/src/generator.rs rename to schemars/src/gen.rs diff --git a/schemars/src/lib.rs b/schemars/src/lib.rs index 13f3091..a288e1b 100644 --- a/schemars/src/lib.rs +++ b/schemars/src/lib.rs @@ -1,8 +1,8 @@ -pub mod generator; +pub mod gen; pub mod make_schema; pub mod schema; -pub use generator::SchemaGenerator; pub use schema::{Schema, SchemaObject, SchemaRef}; +pub use make_schema::MakeSchema; pub use schemars_derive::*; diff --git a/schemars/src/main.rs b/schemars/src/main.rs index 533a945..fd620bb 100644 --- a/schemars/src/main.rs +++ b/schemars/src/main.rs @@ -1,52 +1,11 @@ -use schemars::MakeSchema; -use serde::{Deserialize, Serialize}; +use schemars::*; use serde_json::Result; -#[derive(Serialize, Deserialize, Debug, MakeSchema)] -#[serde(rename_all = "camelCase")] -enum TodoStatus { - Backlog, - InProgress, - Done, - Archived, -} - -#[derive(Serialize, Deserialize, Debug, MakeSchema)] -#[serde(rename_all = "camelCase")] -struct Todo { - id: u64, - title: String, - description: Option, - status: TodoStatus, - assigned_to: Vec, -} - -#[derive(Serialize, Deserialize, Debug, MakeSchema)] -#[serde(rename_all = "camelCase")] -struct User { - id: u64, - username: String, -} - fn main() -> Result<()> { - let gen = schemars::SchemaGenerator::new(); - let schema = gen.into_root_schema_for::(); + let gen = gen::SchemaGenerator::new(); + let schema = gen.into_root_schema_for::(); let json = serde_json::to_string_pretty(&schema)?; println!("{}", json); - /*let todo = Todo { - id: 42, - title: "Learn Rust".to_owned(), - description: Option::None, - status: TodoStatus::InProgress, - assigned_to: vec![User { - id: 1248, - username: "testuser".to_owned(), - }], - }; - - let t = serde_json::to_string(&todo)?; - println!("{}", t);*/ - Ok(()) } diff --git a/schemars/src/make_schema.rs b/schemars/src/make_schema.rs index 0f29343..401a5d4 100644 --- a/schemars/src/make_schema.rs +++ b/schemars/src/make_schema.rs @@ -1,4 +1,4 @@ -use crate::generator::SchemaGenerator; +use crate::gen::SchemaGenerator; use crate::schema::*; use serde_json::json; use std::collections::BTreeMap as Map; @@ -225,7 +225,7 @@ macro_rules! map_impl { impl $($desc)+ where K: Into, - T: MakeSchema, + V: MakeSchema, { no_ref_schema!(); @@ -246,8 +246,8 @@ macro_rules! map_impl { }; } -map_impl!( MakeSchema for std::collections::BTreeMap); -map_impl!( MakeSchema for std::collections::HashMap); +map_impl!( MakeSchema for std::collections::BTreeMap); +map_impl!( MakeSchema for std::collections::HashMap); ////////// OPTION ////////// diff --git a/schemars/src/schema.rs b/schemars/src/schema.rs index cc5b3b9..595bd18 100644 --- a/schemars/src/schema.rs +++ b/schemars/src/schema.rs @@ -1,10 +1,12 @@ +use crate as schemars; +use schemars::MakeSchema; use serde::{Deserialize, Serialize}; use serde_json::Value; use std::collections::BTreeMap as Map; // TODO use serde_json::Map (or some other wrapper) instead of BTreeMap to ensure preserve_order is possible -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, MakeSchema)] #[serde(untagged)] pub enum Schema { Bool(bool), @@ -30,13 +32,13 @@ impl From for Schema { } } -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, MakeSchema)] pub struct SchemaRef { #[serde(rename = "$ref")] pub reference: String, } -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, MakeSchema)] #[serde(rename_all = "camelCase")] pub struct SchemaObject { #[serde(rename = "$schema", skip_serializing_if = "Option::is_none")] @@ -71,7 +73,7 @@ pub struct SchemaObject { pub extensions: Map, } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, MakeSchema)] #[serde(rename_all = "camelCase")] pub enum InstanceType { Null, @@ -83,7 +85,7 @@ pub enum InstanceType { Integer, } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, MakeSchema)] #[serde(untagged)] pub enum SingleOrVec { Single(Box), diff --git a/schemars_derive/src/lib.rs b/schemars_derive/src/lib.rs index 9bfa5b7..09a3335 100644 --- a/schemars_derive/src/lib.rs +++ b/schemars_derive/src/lib.rs @@ -9,11 +9,13 @@ use proc_macro2::{Span, TokenStream}; use serde_derive_internals::ast::{Container, Data, Field, Style, Variant}; use serde_derive_internals::{Ctxt, Derive}; use syn::spanned::Spanned; -use syn::DeriveInput; +use syn::{DeriveInput, GenericParam, Generics}; #[proc_macro_derive(MakeSchema, attributes(schemars, serde))] pub fn derive_make_schema(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = parse_macro_input!(input as DeriveInput); + let mut input = parse_macro_input!(input as DeriveInput); + // TODO is mutating the input really the best way to do this? + add_trait_bounds(&mut input.generics); let ctxt = Ctxt::new(); let cont = Container::from_ast(&ctxt, &input, Derive::Deserialize); if let Err(e) = ctxt.check() { @@ -31,8 +33,8 @@ pub fn derive_make_schema(input: proc_macro::TokenStream) -> proc_macro::TokenSt let impl_block = quote! { #[automatically_derived] - impl #impl_generics schemars::make_schema::MakeSchema for #name #ty_generics #where_clause { - fn make_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema { + impl #impl_generics schemars::MakeSchema for #name #ty_generics #where_clause { + fn make_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::Schema { #schema } }; @@ -40,6 +42,14 @@ pub fn derive_make_schema(input: proc_macro::TokenStream) -> proc_macro::TokenSt proc_macro::TokenStream::from(impl_block) } +fn add_trait_bounds(generics: &mut Generics) { + for param in &mut generics.params { + if let GenericParam::Type(ref mut type_param) = *param { + type_param.bounds.push(parse_quote!(schemars::MakeSchema)); + } + } +} + fn wrap_schema_fields(schema_contents: TokenStream) -> TokenStream { quote! { schemars::SchemaObject {