Lines
100 %
Functions
27.69 %
Branches
use attribute_derive::Attribute;
use manyhow::Result;
use proc_macro2::TokenStream;
use quote::quote;
use syn::punctuated::Punctuated;
use syn::token::Paren;
use syn::{DeriveInput, Ident, LitStr, Path, Type, TypeTuple};
use crate::core_path;
#[derive(Attribute)]
#[attribute(ident = view)]
struct ViewAttribute {
#[attribute(example = "CollectionType")]
collection: Type,
#[attribute(example = "KeyType")]
key: Type,
#[attribute(example = "\"by-name\"")]
name: Option<LitStr>,
#[attribute(example = "ValueType")]
value: Option<Type>,
#[attribute(example = "bosaidb::core")]
core: Option<Path>,
#[attribute(example = "Format or None")]
serialization: Option<Path>,
}
pub fn derive(
DeriveInput {
attrs,
ident,
generics,
..
}: DeriveInput,
) -> Result {
let ViewAttribute {
collection,
key,
name,
value,
core,
serialization,
} = ViewAttribute::from_attributes(&attrs)?;
let core = core.unwrap_or_else(core_path);
let value = value.unwrap_or_else(|| {
Type::Tuple(TypeTuple {
paren_token: Paren::default(),
elems: Punctuated::new(),
})
});
let name = name
.as_ref()
.map_or_else(|| ident.to_string(), LitStr::value);
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let serialization = match serialization {
Some(serialization) if serialization.is_ident("None") => TokenStream::new(),
Some(serialization) => quote! {
impl #impl_generics #core::schema::SerializedView for #ident #ty_generics #where_clause {
type Format = #serialization;
fn format() -> Self::Format {
#serialization::default()
},
None => quote! {
impl #impl_generics #core::schema::DefaultViewSerialization for #ident #ty_generics #where_clause {}
};
Ok(quote! {
impl #impl_generics #core::schema::View for #ident #ty_generics #where_clause {
type Collection = #collection;
type Key = #key;
type Value = #value;
fn name(&self) -> #core::schema::Name {
#core::schema::Name::new(#name)
#serialization
#[attribute(ident = view_schema)]
struct ViewSchemaAttribute {
#[attribute(example = "ViewType")]
view: Option<Type>,
#[attribute(example = "KeyType<'doc>")]
mapped_key: Option<Type>,
version: Option<u64>,
#[attribute(example = "Lazy")]
policy: Option<Ident>,
pub fn derive_schema(
let ViewSchemaAttribute {
view,
mapped_key,
version,
policy,
} = ViewSchemaAttribute::from_attributes(&attrs)?;
let view = view.map_or_else(|| quote!(Self), |ty| quote!(#ty));
let mapped_key = mapped_key.map_or_else(
|| quote!(<Self as #core::schema::View>::Key),
|ty| quote!(#ty),
);
let version = version.map(|version| {
quote!(fn version(&self) -> u64 {
#version
let policy = policy.map(|policy| {
quote!(fn update_policy(&self) -> #core::schema::view::ViewUpdatePolicy {
#core::schema::view::ViewUpdatePolicy::#policy
impl #impl_generics #core::schema::ViewSchema for #ident #ty_generics #where_clause {
type View = #view;
type MappedKey<'doc> = #mapped_key;
#policy