Lines
77.14 %
Functions
36.67 %
Branches
20 %
use partialdebug::placeholder::PartialDebug;
use proc_macro2::{Ident, TokenStream};
use quote::quote;
use std::convert::TryFrom;
use syn::{
parse::{Parse, ParseBuffer},
Attribute, Generics, ItemStruct, Visibility,
};
use super::entity_fields::EntityField;
/// Provides a convenient way of handling the data on any
/// `CanyonEntity` struct annotated with the macro `#[canyon_entity]`
#[derive(PartialDebug, Clone)]
pub struct CanyonEntity {
pub struct_name: Ident,
pub user_table_name: Option<String>,
pub user_schema_name: Option<String>,
pub vis: Visibility,
pub generics: Generics,
pub fields: Vec<EntityField>,
pub attrs: Vec<Attribute>,
}
unsafe impl Send for CanyonEntity {}
unsafe impl Sync for CanyonEntity {}
impl CanyonEntity {
/// Generates as many variants for the enum as fields has the type
/// which this enum is related to, and that type it's the entity
/// stored in [`CanyonEntity`]
/// of the corresponding field
pub fn get_fields_as_enum_variants(&self) -> Vec<TokenStream> {
self.fields
.iter()
.map(|f| {
let field_name = &f.name;
quote! { #field_name }
})
.collect::<Vec<_>>()
/// which this enum is related to.
///
/// Makes a variant `#field_name(#ty)` where `#ty` it's a trait object
/// of type [`canyon_crud::bounds::QueryParameter`]
pub fn get_fields_as_enum_variants_with_value(&self) -> Vec<TokenStream> {
quote! { #field_name(&'a dyn canyon_sql::crud::bounds::QueryParameter<'a>) }
pub fn create_match_arm_for_get_variant_as_str(&self, enum_name: &Ident) -> Vec<TokenStream> {
let field_name_as_str = f.name.to_string();
quote! {
#enum_name::#field_name => #field_name_as_str
/// Generates an implementation of the match pattern to find whatever variant
/// is being requested when the method `.field_name_as_str(self)` it's invoked over some
/// instance that implements the `canyon_sql_root::crud::bounds::FieldIdentifier` trait
pub fn create_match_arm_for_get_variant_as_string(
&self,
enum_name: &Ident,
) -> Vec<TokenStream> {
let field_name_as_string = f.name.to_string();
#enum_name::#field_name => #field_name_as_string.to_string()
/// is being requested when the method `.value()` it's invoked over some
/// instance that implements the `canyon_sql_root::crud::bounds::FieldValueIdentifier` trait
pub fn create_match_arm_for_relate_fields_with_values(
#enum_name::#field_name(v) => (#field_name_as_string, v)
pub fn get_attrs_as_token_stream(&self) -> Vec<TokenStream> {
let name = &f.name;
let ty = &f.field_type;
quote! { pub #name: #ty }
impl Parse for CanyonEntity {
fn parse(input: &ParseBuffer) -> syn::Result<Self> {
let _struct = input.parse::<ItemStruct>()?;
// Retrieve the struct fields
let mut parsed_fields: Vec<EntityField> = Vec::new();
for field in _struct.fields {
let struct_attribute = EntityField::try_from(&field)?;
parsed_fields.push(struct_attribute)
Ok(Self {
struct_name: _struct.ident,
user_table_name: None,
user_schema_name: None,
vis: _struct.vis,
generics: _struct.generics,
fields: parsed_fields,
attrs: _struct.attrs,