refactor: add payment_issuer and payment_experience in pa (#491)

This commit is contained in:
Narayan Bhat
2023-02-19 19:29:22 +05:30
committed by GitHub
parent c47619b5ea
commit 66563595df
54 changed files with 790 additions and 801 deletions

View File

@ -53,13 +53,13 @@ pub fn debug_as_display_derive(input: proc_macro::TokenStream) -> proc_macro::To
/// # Example
///
/// ```
/// use router_derive::{DieselEnum, diesel_enum};
/// use router_derive::diesel_enum;
///
/// // Deriving `FromStr` and `ToString` using the `strum` crate, you can also implement it
/// // yourself if required.
/// #[derive(strum::Display, strum::EnumString)]
/// #[derive(Debug, DieselEnum)]
/// #[diesel_enum]
/// #[derive(Debug)]
/// #[diesel_enum(storage_type = "pg_enum")]
/// enum Color {
/// Red,
/// Green,
@ -69,32 +69,64 @@ pub fn debug_as_display_derive(input: proc_macro::TokenStream) -> proc_macro::To
#[proc_macro_derive(DieselEnum)]
pub fn diesel_enum_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse_macro_input!(input as syn::DeriveInput);
let tokens =
macros::diesel_enum_derive_inner(&ast).unwrap_or_else(|error| error.to_compile_error());
tokens.into()
}
/// Similar to [`DieselEnum`] but uses text when storing in the database, this is to avoid
/// making changes to the database when the enum variants are added or modified
///
/// # Example
/// [DieselEnum]: macro@crate::diesel_enum
///
/// ```
/// use router_derive::{diesel_enum};
///
/// // Deriving `FromStr` and `ToString` using the `strum` crate, you can also implement it
/// // yourself if required.
/// #[derive(strum::Display, strum::EnumString)]
/// #[derive(Debug)]
/// #[diesel_enum(storage_type = "text")]
/// enum Color {
/// Red,
/// Green,
/// Blue,
/// }
/// ```
#[proc_macro_derive(DieselEnumText)]
pub fn diesel_enum_derive_string(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse_macro_input!(input as syn::DeriveInput);
let tokens = macros::diesel_enum_text_derive_inner(&ast)
.unwrap_or_else(|error| error.to_compile_error());
tokens.into()
}
/// Derives the boilerplate code required for using an enum with `diesel` and a PostgreSQL database.
///
/// Works in tandem with the [`DieselEnum`][DieselEnum] derive macro to achieve the desired results.
/// Storage Type can either be "text" or "pg_enum"
/// Choosing text will store the enum as text in the database, whereas pg_enum will map it to the
/// database enum
///
/// Works in tandem with the [`DieselEnum`][DieselEnum] and [`DieselEnumText`][DieselEnumText] derive macro to achieve the desired results.
/// The enum is required to implement (or derive) the [`ToString`][ToString] and the
/// [`FromStr`][FromStr] traits for the [`DieselEnum`][DieselEnum] derive macro to be used.
///
/// [DieselEnum]: crate::DieselEnum
/// [DieselEnumText]: crate::DieselEnumText
/// [FromStr]: ::core::str::FromStr
/// [ToString]: ::std::string::ToString
///
/// # Example
///
/// ```
/// use router_derive::{DieselEnum, diesel_enum};
/// use router_derive::{diesel_enum};
///
/// // Deriving `FromStr` and `ToString` using the `strum` crate, you can also implement it
/// // yourself if required. (Required by the DieselEnum derive macro.)
/// #[derive(strum::Display, strum::EnumString)]
/// #[derive(Debug, DieselEnum)]
/// #[diesel_enum]
/// #[derive(Debug)]
/// #[diesel_enum(storage_type = "text")]
/// enum Color {
/// Red,
/// Green,

View File

@ -9,7 +9,9 @@ use syn::DeriveInput;
pub(crate) use self::{
api_error::api_error_derive_inner,
diesel::{diesel_enum_attribute_inner, diesel_enum_derive_inner},
diesel::{
diesel_enum_attribute_inner, diesel_enum_derive_inner, diesel_enum_text_derive_inner,
},
operation::operation_derive_inner,
};

View File

@ -1,9 +1,46 @@
use darling::FromMeta;
use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote};
use syn::{AttributeArgs, Data, DeriveInput, ItemEnum};
use crate::macros::helpers::non_enum_error;
pub(crate) fn diesel_enum_text_derive_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
let name = &ast.ident;
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
match &ast.data {
Data::Enum(_) => (),
_ => return Err(non_enum_error()),
}
Ok(quote! {
#[automatically_derived]
impl #impl_generics ::diesel::serialize::ToSql<::diesel::sql_types::Text, ::diesel::pg::Pg> for #name #ty_generics
#where_clause
{
fn to_sql<'b>(&'b self, out: &mut ::diesel::serialize::Output<'b, '_, ::diesel::pg::Pg>) -> ::diesel::serialize::Result {
use ::std::io::Write;
out.write_all(self.to_string().as_bytes())?;
Ok(::diesel::serialize::IsNull::No)
}
}
#[automatically_derived]
impl #impl_generics ::diesel::deserialize::FromSql<::diesel::sql_types::Text, ::diesel::pg::Pg> for #name #ty_generics
#where_clause
{
fn from_sql(value: ::diesel::pg::PgValue) -> diesel::deserialize::Result<Self> {
use ::core::str::FromStr;
Self::from_str(::core::str::from_utf8(value.as_bytes())?)
.map_err(|_| "Unrecognized enum variant".into())
}
}
})
}
pub(crate) fn diesel_enum_derive_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
let name = &ast.ident;
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
@ -50,18 +87,41 @@ pub(crate) fn diesel_enum_attribute_inner(
args: &AttributeArgs,
item: &ItemEnum,
) -> syn::Result<TokenStream> {
if !args.is_empty() {
return Err(syn::Error::new(
Span::call_site(),
"This attribute macro does not accept any arguments.",
));
#[derive(FromMeta, Debug)]
enum StorageType {
PgEnum,
Text,
}
let name = &item.ident;
let struct_name = format_ident!("Db{name}");
Ok(quote! {
#[derive(diesel::AsExpression, diesel::FromSqlRow)]
#[diesel(sql_type = #struct_name)]
#item
})
#[derive(FromMeta, Debug)]
struct StorageTypeArgs {
storage_type: StorageType,
}
let storage_type_args = match StorageTypeArgs::from_list(args) {
Ok(v) => v,
Err(_) => {
return Err(syn::Error::new(
Span::call_site(),
"Expected storage_type of text or pg_enum",
));
}
};
match storage_type_args.storage_type {
StorageType::PgEnum => {
let name = &item.ident;
let type_name = format_ident!("Db{name}");
Ok(quote! {
#[derive(diesel::AsExpression, diesel::FromSqlRow, router_derive::DieselEnum) ]
#[diesel(sql_type = #type_name)]
#item
})
}
StorageType::Text => Ok(quote! {
#[derive(diesel::AsExpression, diesel::FromSqlRow, router_derive::DieselEnumText) ]
#[diesel(sql_type = ::diesel::sql_types::Text)]
#item
}),
}
}