mirror of
https://gitlab.com/msrd0/gotham-restful.git
synced 2025-05-09 08:00:41 +00:00
basic structure for openapi_type crate
This commit is contained in:
parent
2251c29d7b
commit
90870e3b6a
9 changed files with 261 additions and 1 deletions
22
openapi_type_derive/Cargo.toml
Normal file
22
openapi_type_derive/Cargo.toml
Normal file
|
@ -0,0 +1,22 @@
|
|||
# -*- eval: (cargo-minor-mode 1) -*-
|
||||
|
||||
[package]
|
||||
workspace = ".."
|
||||
name = "openapi_type_derive"
|
||||
version = "0.1.0-dev"
|
||||
authors = ["Dominic Meiser <git@msrd0.de>"]
|
||||
edition = "2018"
|
||||
description = "Implementation detail of the openapi_type crate"
|
||||
license = "Apache-2.0"
|
||||
repository = "https://gitlab.com/msrd0/gotham-restful/-/tree/master/openapi_type_derive"
|
||||
|
||||
# tests are done using trybuild exclusively
|
||||
autotests = false
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0"
|
||||
syn = "1.0"
|
93
openapi_type_derive/src/lib.rs
Normal file
93
openapi_type_derive/src/lib.rs
Normal file
|
@ -0,0 +1,93 @@
|
|||
#![warn(missing_debug_implementations, rust_2018_idioms)]
|
||||
#![deny(broken_intra_doc_links)]
|
||||
#![forbid(unsafe_code)]
|
||||
//! This crate defines the macros for `#[derive(OpenapiType)]`.
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
use syn::{
|
||||
parse_macro_input, spanned::Spanned as _, Data, DataEnum, DataStruct, DataUnion, DeriveInput, TraitBound,
|
||||
TraitBoundModifier, TypeParamBound
|
||||
};
|
||||
|
||||
#[proc_macro_derive(OpenapiType)]
|
||||
pub fn derive_openapi_type(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input);
|
||||
expand_openapi_type(input).unwrap_or_else(|err| err.to_compile_error()).into()
|
||||
}
|
||||
|
||||
macro_rules! path {
|
||||
(:: $($segment:ident)::*) => {
|
||||
path!(@private Some(Default::default()), $($segment),*)
|
||||
};
|
||||
($($segment:ident)::*) => {
|
||||
path!(@private None, $($segment),*)
|
||||
};
|
||||
(@private $leading_colon:expr, $($segment:ident),*) => {
|
||||
{
|
||||
#[allow(unused_mut)]
|
||||
let mut segments: ::syn::punctuated::Punctuated<::syn::PathSegment, _> = Default::default();
|
||||
$(
|
||||
segments.push(::syn::PathSegment {
|
||||
ident: ::proc_macro2::Ident::new(stringify!($segment), ::proc_macro2::Span::call_site()),
|
||||
arguments: Default::default()
|
||||
});
|
||||
)*
|
||||
::syn::Path {
|
||||
leading_colon: $leading_colon,
|
||||
segments
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn expand_openapi_type(mut input: DeriveInput) -> syn::Result<TokenStream2> {
|
||||
let ident = &input.ident;
|
||||
|
||||
// prepare the generics - all impl generics will get `OpenapiType` requirement
|
||||
let (impl_generics, ty_generics, where_clause) = {
|
||||
let generics = &mut input.generics;
|
||||
generics.type_params_mut().for_each(|param| {
|
||||
param.colon_token.get_or_insert_with(Default::default);
|
||||
param.bounds.push(TypeParamBound::Trait(TraitBound {
|
||||
paren_token: None,
|
||||
modifier: TraitBoundModifier::None,
|
||||
lifetimes: None,
|
||||
path: path!(::openapi_type::OpenapiType)
|
||||
}))
|
||||
});
|
||||
generics.split_for_impl()
|
||||
};
|
||||
|
||||
// parse the input data
|
||||
match &input.data {
|
||||
Data::Struct(strukt) => parse_struct(strukt)?,
|
||||
Data::Enum(inum) => parse_enum(inum)?,
|
||||
Data::Union(union) => parse_union(union)?
|
||||
};
|
||||
|
||||
// generate the impl code
|
||||
Ok(quote! {
|
||||
impl #impl_generics ::openapi_type::OpenapiType for #ident #ty_generics #where_clause {
|
||||
fn schema() -> ::openapi_type::OpenapiSchema {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_struct(_strukt: &DataStruct) -> syn::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_enum(_inum: &DataEnum) -> syn::Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn parse_union(union: &DataUnion) -> syn::Result<()> {
|
||||
Err(syn::Error::new(
|
||||
union.union_token.span(),
|
||||
"#[derive(OpenapiType)] cannot be used on unions"
|
||||
))
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue