refactor(macros): use syn2.0 (#2890)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Sanchith Hegde <22217505+SanchithHegde@users.noreply.github.com>
This commit is contained in:
Narayan Bhat
2023-11-22 15:46:33 +05:30
committed by GitHub
parent 7d223ee0d1
commit 46e13d5475
26 changed files with 501 additions and 365 deletions

48
Cargo.lock generated
View File

@ -114,7 +114,7 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a0a77f836d869f700e5b47ac7c3c8b9c8bc82e4aec861954c6198abee3ebd4d"
dependencies = [
"darling 0.20.3",
"darling",
"parse-size",
"proc-macro2",
"quote",
@ -1858,38 +1858,14 @@ dependencies = [
"typenum",
]
[[package]]
name = "darling"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
dependencies = [
"darling_core 0.14.4",
"darling_macro 0.14.4",
]
[[package]]
name = "darling"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
dependencies = [
"darling_core 0.20.3",
"darling_macro 0.20.3",
]
[[package]]
name = "darling_core"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 1.0.109",
"darling_core",
"darling_macro",
]
[[package]]
@ -1906,24 +1882,13 @@ dependencies = [
"syn 2.0.38",
]
[[package]]
name = "darling_macro"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
dependencies = [
"darling_core 0.14.4",
"quote",
"syn 1.0.109",
]
[[package]]
name = "darling_macro"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
dependencies = [
"darling_core 0.20.3",
"darling_core",
"quote",
"syn 2.0.38",
]
@ -4861,7 +4826,6 @@ dependencies = [
name = "router_derive"
version = "0.1.0"
dependencies = [
"darling 0.14.4",
"diesel",
"indexmap 2.0.2",
"proc-macro2",
@ -4869,7 +4833,7 @@ dependencies = [
"serde",
"serde_json",
"strum 0.24.1",
"syn 1.0.109",
"syn 2.0.38",
]
[[package]]
@ -5358,7 +5322,7 @@ version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e6be15c453eb305019bfa438b1593c731f36a289a7853f7707ee29e870b3b3c"
dependencies = [
"darling 0.20.3",
"darling",
"proc-macro2",
"quote",
"syn 2.0.38",

View File

@ -1,6 +1,5 @@
use std::num::{ParseFloatError, TryFromIntError};
use router_derive;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
#[doc(hidden)]
@ -29,7 +28,7 @@ pub mod diesel_exports {
strum::EnumString,
ToSchema,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum AttemptStatus {
@ -107,7 +106,7 @@ impl AttemptStatus {
strum::EnumString,
ToSchema,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum AuthenticationType {
@ -132,7 +131,7 @@ pub enum AuthenticationType {
ToSchema,
Hash,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum CaptureStatus {
@ -163,7 +162,7 @@ pub enum CaptureStatus {
strum::EnumString,
ToSchema,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum CaptureMethod {
@ -190,7 +189,7 @@ pub enum CaptureMethod {
serde::Serialize,
ToSchema,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[strum(serialize_all = "snake_case")]
#[serde(rename_all = "snake_case")]
pub enum ConnectorType {
@ -231,7 +230,7 @@ pub enum ConnectorType {
strum::EnumVariantNames,
ToSchema,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
pub enum Currency {
AED,
ALL,
@ -789,7 +788,7 @@ impl Currency {
strum::EnumString,
ToSchema,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum EventType {
@ -825,7 +824,7 @@ pub enum EventType {
strum::Display,
strum::EnumString,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum MerchantStorageScheme {
@ -848,7 +847,7 @@ pub enum MerchantStorageScheme {
strum::Display,
strum::EnumString,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum IntentStatus {
@ -882,7 +881,7 @@ pub enum IntentStatus {
strum::EnumString,
ToSchema,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum FutureUsage {
@ -904,7 +903,7 @@ pub enum FutureUsage {
strum::EnumString,
ToSchema,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[strum(serialize_all = "snake_case")]
#[serde(rename_all = "snake_case")]
pub enum PaymentMethodIssuerCode {
@ -1108,7 +1107,7 @@ pub enum PaymentMethod {
strum::EnumString,
ToSchema,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum PaymentType {
@ -1132,7 +1131,7 @@ pub enum PaymentType {
serde::Serialize,
serde::Deserialize,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[strum(serialize_all = "snake_case")]
pub enum RefundStatus {
Failure,
@ -1157,7 +1156,7 @@ pub enum RefundStatus {
strum::EnumString,
ToSchema,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum MandateStatus {
@ -1211,7 +1210,7 @@ pub enum CardNetwork {
strum::EnumString,
ToSchema,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum DisputeStage {
@ -1235,7 +1234,7 @@ pub enum DisputeStage {
strum::EnumString,
ToSchema,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum DisputeStatus {
@ -1265,7 +1264,7 @@ pub enum DisputeStatus {
utoipa::ToSchema,
Copy
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[rustfmt::skip]
pub enum CountryAlpha2 {
AF, AX, AL, DZ, AS, AD, AO, AI, AQ, AG, AR, AM, AW, AU, AT,
@ -1692,7 +1691,7 @@ pub enum CanadaStatesAbbreviation {
strum::Display,
strum::EnumString,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum PayoutStatus {
@ -1720,7 +1719,7 @@ pub enum PayoutStatus {
strum::Display,
strum::EnumString,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum PayoutType {
@ -1775,7 +1774,7 @@ pub enum PayoutEntityType {
ToSchema,
Hash,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum PaymentSource {
@ -1842,7 +1841,7 @@ pub enum FrmSuggestion {
utoipa::ToSchema,
Copy,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum ReconStatus {
@ -1871,7 +1870,7 @@ pub enum ApplePayFlow {
ToSchema,
Default,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[router_derive::diesel_enum(storage_type = "db_enum")]
#[strum(serialize_all = "snake_case")]
#[serde(rename_all = "snake_case")]
pub enum ConnectorStatus {

View File

@ -21,6 +21,7 @@ pub mod diesel_exports {
pub use common_enums::*;
use common_utils::pii;
use diesel::serialize::{Output, ToSql};
use router_derive::diesel_enum;
use time::PrimitiveDateTime;
#[derive(
@ -34,7 +35,7 @@ use time::PrimitiveDateTime;
strum::Display,
strum::EnumString,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum RoutingAlgorithmKind {
@ -55,7 +56,7 @@ pub enum RoutingAlgorithmKind {
strum::Display,
strum::EnumString,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum EventClass {
@ -76,7 +77,7 @@ pub enum EventClass {
strum::Display,
strum::EnumString,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum EventObjectType {
@ -97,7 +98,7 @@ pub enum EventObjectType {
strum::Display,
strum::EnumString,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum ProcessTrackerStatus {
@ -126,7 +127,7 @@ pub enum ProcessTrackerStatus {
strum::Display,
strum::EnumString,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[diesel_enum(storage_type = "db_enum")]
#[strum(serialize_all = "snake_case")]
#[serde(rename_all = "snake_case")]
pub enum RefundType {
@ -149,7 +150,7 @@ pub enum RefundType {
strum::Display,
strum::EnumString,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum MandateType {
@ -217,7 +218,7 @@ pub struct MandateAmountData {
strum::Display,
strum::EnumString,
)]
#[router_derive::diesel_enum(storage_type = "text")]
#[diesel_enum(storage_type = "text")]
#[strum(serialize_all = "snake_case")]
#[serde(rename_all = "snake_case")]
pub enum BankNames {
@ -348,7 +349,7 @@ pub enum BankNames {
strum::Display,
strum::EnumString,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[diesel_enum(storage_type = "db_enum")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum FraudCheckType {
@ -369,7 +370,7 @@ pub enum FraudCheckType {
strum::EnumString,
frunk::LabelledGeneric,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[diesel_enum(storage_type = "db_enum")]
#[strum(serialize_all = "snake_case")]
pub enum FraudCheckStatus {
Fraud,
@ -393,7 +394,7 @@ pub enum FraudCheckStatus {
strum::EnumString,
frunk::LabelledGeneric,
)]
#[router_derive::diesel_enum(storage_type = "text")]
#[diesel_enum(storage_type = "text")]
#[strum(serialize_all = "snake_case")]
pub enum FraudCheckLastStep {
#[default]
@ -416,7 +417,7 @@ pub enum FraudCheckLastStep {
strum::EnumString,
frunk::LabelledGeneric,
)]
#[router_derive::diesel_enum(storage_type = "text")]
#[diesel_enum(storage_type = "text")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum UserStatus {

View File

@ -28,7 +28,7 @@ use crate::{
};
#[derive(Debug, Clone, Copy, PaymentOperation)]
#[operation(ops = "all", flow = "authorize")]
#[operation(operations = "all", flow = "authorize")]
pub struct PaymentApprove;
#[async_trait]

View File

@ -25,7 +25,7 @@ use crate::{
};
#[derive(Debug, Clone, Copy, router_derive::PaymentOperation)]
#[operation(ops = "all", flow = "cancel")]
#[operation(operations = "all", flow = "cancel")]
pub struct PaymentCancel;
#[async_trait]

View File

@ -24,7 +24,7 @@ use crate::{
};
#[derive(Debug, Clone, Copy, router_derive::PaymentOperation)]
#[operation(ops = "all", flow = "capture")]
#[operation(operations = "all", flow = "capture")]
pub struct PaymentCapture;
#[async_trait]

View File

@ -27,7 +27,7 @@ use crate::{
};
#[derive(Debug, Clone, Copy, PaymentOperation)]
#[operation(ops = "all", flow = "authorize")]
#[operation(operations = "all", flow = "authorize")]
pub struct CompleteAuthorize;
#[async_trait]

View File

@ -34,7 +34,7 @@ use crate::{
};
#[derive(Debug, Clone, Copy, PaymentOperation)]
#[operation(ops = "all", flow = "authorize")]
#[operation(operations = "all", flow = "authorize")]
pub struct PaymentConfirm;
#[async_trait]
impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>

View File

@ -34,7 +34,7 @@ use crate::{
};
#[derive(Debug, Clone, Copy, PaymentOperation)]
#[operation(ops = "all", flow = "authorize")]
#[operation(operations = "all", flow = "authorize")]
pub struct PaymentCreate;
/// The `get_trackers` function for `PaymentsCreate` is an entrypoint for new payments

View File

@ -29,7 +29,7 @@ use crate::{
};
#[derive(Debug, Clone, Copy, PaymentOperation)]
#[operation(ops = "all", flow = "verify")]
#[operation(operations = "all", flow = "verify")]
pub struct PaymentMethodValidate;
impl<F: Send + Clone, Ctx: PaymentMethodRetrieve> ValidateRequest<F, api::VerifyRequest, Ctx>

View File

@ -24,7 +24,7 @@ use crate::{
};
#[derive(Debug, Clone, Copy, router_derive::PaymentOperation)]
#[operation(ops = "all", flow = "reject")]
#[operation(operations = "all", flow = "reject")]
pub struct PaymentReject;
#[async_trait]

View File

@ -35,8 +35,8 @@ use crate::{
#[derive(Debug, Clone, Copy, router_derive::PaymentOperation)]
#[operation(
ops = "post_tracker",
flow = "syncdata,authorizedata,canceldata,capturedata,completeauthorizedata,approvedata,rejectdata,setupmandatedata,sessiondata"
operations = "post_update_tracker",
flow = "sync_data, authorize_data, cancel_data, capture_data, complete_authorize_data, approve_data, reject_data, setup_mandate_data, session_data"
)]
pub struct PaymentResponse;

View File

@ -26,7 +26,7 @@ use crate::{
};
#[derive(Debug, Clone, Copy, PaymentOperation)]
#[operation(ops = "all", flow = "session")]
#[operation(operations = "all", flow = "session")]
pub struct PaymentSession;
#[async_trait]

View File

@ -25,7 +25,7 @@ use crate::{
};
#[derive(Debug, Clone, Copy, PaymentOperation)]
#[operation(ops = "all", flow = "start")]
#[operation(operations = "all", flow = "start")]
pub struct PaymentStart;
#[async_trait]

View File

@ -28,7 +28,7 @@ use crate::{
};
#[derive(Debug, Clone, Copy, PaymentOperation)]
#[operation(ops = "all", flow = "sync")]
#[operation(operations = "all", flow = "sync")]
pub struct PaymentStatus;
impl<F: Send + Clone, Ctx: PaymentMethodRetrieve> Operation<F, api::PaymentsRequest, Ctx>

View File

@ -27,7 +27,7 @@ use crate::{
};
#[derive(Debug, Clone, Copy, PaymentOperation)]
#[operation(ops = "all", flow = "authorize")]
#[operation(operations = "all", flow = "authorize")]
pub struct PaymentUpdate;
#[async_trait]

View File

@ -12,14 +12,14 @@ proc-macro = true
doctest = false
[dependencies]
darling = "0.14.4"
indexmap = "2.0.0"
proc-macro2 = "1.0.56"
quote = "1.0.26"
syn = { version = "1.0.109", features = ["full", "extra-traits"] } # the full feature does not seem to encompass all the features
syn = { version = "2.0.5", features = ["full", "extra-traits"] } # the full feature does not seem to encompass all the features
strum = { version = "0.24.1", features = ["derive"] }
[dev-dependencies]
diesel = { version = "2.1.0", features = ["postgres"] }
serde = { version = "1.0.163", features = ["derive"] }
serde_json = "1.0.96"
strum = { version = "0.24.1", features = ["derive"] }

View File

@ -2,6 +2,10 @@
#![forbid(unsafe_code)]
#![warn(missing_docs)]
use syn::parse_macro_input;
use crate::macros::diesel::DieselEnumMeta;
mod macros;
/// Uses the [`Debug`][Debug] implementation of a type to derive its [`Display`][Display]
@ -66,7 +70,7 @@ pub fn debug_as_display_derive(input: proc_macro::TokenStream) -> proc_macro::To
/// Blue,
/// }
/// ```
#[proc_macro_derive(DieselEnum)]
#[proc_macro_derive(DieselEnum, attributes(storage_type))]
pub fn diesel_enum_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse_macro_input!(input as syn::DeriveInput);
let tokens =
@ -104,16 +108,15 @@ pub fn diesel_enum_derive_string(input: proc_macro::TokenStream) -> proc_macro::
/// Derives the boilerplate code required for using an enum with `diesel` and a PostgreSQL database.
///
/// 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
/// Storage Type can either be "text" or "db_enum"
/// Choosing text will store the enum as text in the database, whereas db_enum will map it to the
/// corresponding database enum
///
/// Works in tandem with the [`DieselEnum`][DieselEnum] and [`DieselEnumText`][DieselEnumText] derive macro to achieve the desired results.
/// Works in tandem with the [`DieselEnum`][DieselEnum] 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
///
@ -138,12 +141,12 @@ pub fn diesel_enum(
args: proc_macro::TokenStream,
item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let args = syn::parse_macro_input!(args as syn::AttributeArgs);
let args_parsed = parse_macro_input!(args as DieselEnumMeta);
let item = syn::parse_macro_input!(item as syn::ItemEnum);
let tokens = macros::diesel_enum_attribute_inner(&args, &item)
.unwrap_or_else(|error| error.to_compile_error());
tokens.into()
macros::diesel::diesel_enum_attribute_macro(args_parsed, &item)
.unwrap_or_else(|error| error.to_compile_error())
.into()
}
/// A derive macro which generates the setter functions for any struct with fields
@ -226,7 +229,7 @@ pub fn setter(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
#[inline]
fn check_if_auth_based_attr_is_present(f: &syn::Field, ident: &str) -> bool {
for i in f.attrs.iter() {
if i.path.is_ident(ident) {
if i.path().is_ident(ident) {
return true;
}
}
@ -460,7 +463,8 @@ pub fn api_error_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStre
#[proc_macro_derive(PaymentOperation, attributes(operation))]
pub fn operation_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = syn::parse_macro_input!(input as syn::DeriveInput);
macros::operation_derive_inner(input).unwrap_or_else(|err| err.to_compile_error().into())
macros::operation::operation_derive_inner(input)
.unwrap_or_else(|err| err.to_compile_error().into())
}
/// Generates different schemas with the ability to mark few fields as mandatory for certain schema

View File

@ -13,11 +13,8 @@ use syn::DeriveInput;
pub(crate) use self::{
api_error::api_error_derive_inner,
diesel::{
diesel_enum_attribute_inner, diesel_enum_derive_inner, diesel_enum_text_derive_inner,
},
diesel::{diesel_enum_derive_inner, diesel_enum_text_derive_inner},
generate_schema::polymorphic_macro_derive_inner,
operation::operation_derive_inner,
};
pub(crate) fn debug_as_display_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {

View File

@ -1,3 +1,5 @@
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::{
parse::Parse, spanned::Spanned, DeriveInput, Field, Fields, LitStr, Token, TypePath, Variant,
};
@ -38,10 +40,10 @@ impl Parse for EnumMeta {
}
}
impl Spanned for EnumMeta {
fn span(&self) -> proc_macro2::Span {
impl ToTokens for EnumMeta {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
Self::ErrorTypeEnum { keyword, .. } => keyword.span(),
Self::ErrorTypeEnum { keyword, .. } => keyword.to_tokens(tokens),
}
}
}
@ -143,13 +145,13 @@ impl Parse for VariantMeta {
}
}
impl Spanned for VariantMeta {
fn span(&self) -> proc_macro2::Span {
impl ToTokens for VariantMeta {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
Self::ErrorType { keyword, .. } => keyword.span,
Self::Code { keyword, .. } => keyword.span,
Self::Message { keyword, .. } => keyword.span,
Self::Ignore { keyword, .. } => keyword.span,
Self::ErrorType { keyword, .. } => keyword.to_tokens(tokens),
Self::Code { keyword, .. } => keyword.to_tokens(tokens),
Self::Message { keyword, .. } => keyword.to_tokens(tokens),
Self::Ignore { keyword, .. } => keyword.to_tokens(tokens),
}
}
}

View File

@ -1,10 +1,8 @@
#![allow(clippy::use_self)]
use darling::FromMeta;
use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote};
use syn::{AttributeArgs, Data, DeriveInput, ItemEnum};
use quote::{format_ident, quote, ToTokens};
use syn::{parse::Parse, Data, DeriveInput, ItemEnum};
use crate::macros::helpers::non_enum_error;
use crate::macros::helpers;
pub(crate) fn diesel_enum_text_derive_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
let name = &ast.ident;
@ -12,10 +10,11 @@ pub(crate) fn diesel_enum_text_derive_inner(ast: &DeriveInput) -> syn::Result<To
match &ast.data {
Data::Enum(_) => (),
_ => return Err(non_enum_error()),
}
_ => return Err(helpers::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
@ -42,18 +41,20 @@ pub(crate) fn diesel_enum_text_derive_inner(ast: &DeriveInput) -> syn::Result<To
})
}
pub(crate) fn diesel_enum_derive_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
pub(crate) fn diesel_enum_db_enum_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()),
}
_ => return Err(helpers::non_enum_error()),
};
let struct_name = format_ident!("Db{name}");
let type_name = format!("{name}");
Ok(quote! {
#[derive(::core::clone::Clone, ::core::marker::Copy, ::core::fmt::Debug, ::diesel::QueryId, ::diesel::SqlType)]
#[diesel(postgres_type(name = #type_name))]
pub struct #struct_name;
@ -84,45 +85,138 @@ pub(crate) fn diesel_enum_derive_inner(ast: &DeriveInput) -> syn::Result<TokenSt
})
}
pub(crate) fn diesel_enum_attribute_inner(
args: &AttributeArgs,
mod diesel_keyword {
use syn::custom_keyword;
custom_keyword!(storage_type);
custom_keyword!(db_enum);
custom_keyword!(text);
}
#[derive(Debug, strum::EnumString, strum::EnumIter, strum::Display)]
#[strum(serialize_all = "snake_case")]
pub enum StorageType {
/// Store the Enum as Text value in the database
Text,
/// Store the Enum as Enum in the database. This requires a corresponding enum to be created
/// in the database with the same name
DbEnum,
}
#[derive(Debug)]
pub enum DieselEnumMeta {
StorageTypeEnum {
keyword: diesel_keyword::storage_type,
value: StorageType,
},
}
impl Parse for StorageType {
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
let text = input.parse::<syn::LitStr>()?;
let value = text.value();
value.as_str().parse().map_err(|_| {
syn::Error::new_spanned(
&text,
format!(
"Unexpected value for storage_type: `{value}`. Possible values are `{}`",
helpers::get_possible_values_for_enum::<Self>()
),
)
})
}
}
impl DieselEnumMeta {
pub fn get_storage_type(&self) -> &StorageType {
match self {
Self::StorageTypeEnum { value, .. } => value,
}
}
}
impl Parse for DieselEnumMeta {
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(diesel_keyword::storage_type) {
let keyword = input.parse()?;
input.parse::<syn::Token![=]>()?;
let value = input.parse()?;
Ok(Self::StorageTypeEnum { keyword, value })
} else {
Err(lookahead.error())
}
}
}
impl ToTokens for DieselEnumMeta {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
Self::StorageTypeEnum { keyword, .. } => keyword.to_tokens(tokens),
}
}
}
trait DieselDeriveInputExt {
/// Get all the error metadata associated with an enum.
fn get_metadata(&self) -> syn::Result<Vec<DieselEnumMeta>>;
}
impl DieselDeriveInputExt for DeriveInput {
fn get_metadata(&self) -> syn::Result<Vec<DieselEnumMeta>> {
helpers::get_metadata_inner("storage_type", &self.attrs)
}
}
pub(crate) fn diesel_enum_derive_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
let storage_type = ast.get_metadata()?;
match storage_type
.first()
.ok_or(syn::Error::new(
Span::call_site(),
"Storage type must be specified",
))?
.get_storage_type()
{
StorageType::Text => diesel_enum_text_derive_inner(ast),
StorageType::DbEnum => diesel_enum_db_enum_derive_inner(ast),
}
}
/// Based on the storage type, derive appropriate diesel traits
/// This will add the appropriate #[diesel(sql_type)]
/// Since the `FromSql` and `ToSql` have to be derived for all the enums, this will add the
/// `DieselEnum` derive trait.
pub(crate) fn diesel_enum_attribute_macro(
diesel_enum_meta: DieselEnumMeta,
item: &ItemEnum,
) -> syn::Result<TokenStream> {
#[derive(FromMeta, Debug)]
enum StorageType {
PgEnum,
Text,
}
let diesel_derives =
quote!(#[derive(diesel::AsExpression, diesel::FromSqlRow, router_derive::DieselEnum) ]);
#[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 => {
match diesel_enum_meta {
DieselEnumMeta::StorageTypeEnum {
value: storage_type,
..
} => match storage_type {
StorageType::Text => Ok(quote! {
#diesel_derives
#[diesel(sql_type = ::diesel::sql_types::Text)]
#[storage_type(storage_type = "text")]
#item
}),
StorageType::DbEnum => {
let name = &item.ident;
let type_name = format_ident!("Db{name}");
Ok(quote! {
#[derive(diesel::AsExpression, diesel::FromSqlRow, router_derive::DieselEnum) ]
#diesel_derives
#[diesel(sql_type = #type_name)]
#[storage_type(storage_type= "db_enum")]
#item
})
}
StorageType::Text => Ok(quote! {
#[derive(diesel::AsExpression, diesel::FromSqlRow, router_derive::DieselEnumText) ]
#[diesel(sql_type = ::diesel::sql_types::Text)]
#item
}),
},
}
}

View File

@ -42,12 +42,14 @@ pub fn polymorphic_macro_derive_inner(
let (mandatory_attribute, other_attributes) = field
.attrs
.iter()
.partition::<Vec<_>, _>(|attribute| attribute.path.is_ident("mandatory_in"));
.partition::<Vec<_>, _>(|attribute| attribute.path().is_ident("mandatory_in"));
// Other attributes ( schema ) are to be printed as is
other_attributes
.iter()
.filter(|attribute| attribute.path.is_ident("schema") || attribute.path.is_ident("doc"))
.filter(|attribute| {
attribute.path().is_ident("schema") || attribute.path().is_ident("doc")
})
.for_each(|attribute| {
// Since attributes will be modified, the field should not contain any attributes
// So create a field, with previous attributes removed

View File

@ -23,13 +23,24 @@ pub(super) fn syn_error(span: Span, message: &str) -> syn::Error {
syn::Error::new(span, message)
}
/// Get all the variants of a enum in the form of a string
pub fn get_possible_values_for_enum<T>() -> String
where
T: strum::IntoEnumIterator + ToString,
{
T::iter()
.map(|variants| variants.to_string())
.collect::<Vec<_>>()
.join(", ")
}
pub(super) fn get_metadata_inner<'a, T: Parse + Spanned>(
ident: &str,
attrs: impl IntoIterator<Item = &'a Attribute>,
) -> syn::Result<Vec<T>> {
attrs
.into_iter()
.filter(|attr| attr.path.is_ident(ident))
.filter(|attr| attr.path().is_ident(ident))
.try_fold(Vec::new(), |mut vec, attr| {
vec.extend(attr.parse_args_with(Punctuated::<T, Token![,]>::parse_terminated)?);
Ok(vec)

View File

@ -1,25 +1,27 @@
use std::collections::HashMap;
use std::str::FromStr;
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{self, spanned::Spanned, DeriveInput, Lit, Meta, MetaNameValue, NestedMeta};
use quote::{quote, ToTokens};
use strum::IntoEnumIterator;
use syn::{self, parse::Parse, DeriveInput};
use crate::macros::helpers;
use crate::macros::helpers::{self};
#[derive(Debug, Clone, Copy)]
enum Derives {
#[derive(Debug, Clone, Copy, strum::EnumString, strum::EnumIter, strum::Display)]
#[strum(serialize_all = "snake_case")]
pub enum Derives {
Sync,
Cancel,
Reject,
Capture,
Approvedata,
ApproveData,
Authorize,
Authorizedata,
Syncdata,
Canceldata,
Capturedata,
AuthorizeData,
SyncData,
CancelData,
CaptureData,
CompleteAuthorizeData,
Rejectdata,
RejectData,
SetupMandateData,
Start,
Verify,
@ -27,31 +29,6 @@ enum Derives {
SessionData,
}
impl From<String> for Derives {
fn from(s: String) -> Self {
match s.as_str() {
"sync" => Self::Sync,
"cancel" => Self::Cancel,
"reject" => Self::Reject,
"syncdata" => Self::Syncdata,
"authorize" => Self::Authorize,
"approvedata" => Self::Approvedata,
"authorizedata" => Self::Authorizedata,
"canceldata" => Self::Canceldata,
"capture" => Self::Capture,
"capturedata" => Self::Capturedata,
"completeauthorizedata" => Self::CompleteAuthorizeData,
"rejectdata" => Self::Rejectdata,
"start" => Self::Start,
"verify" => Self::Verify,
"setupmandatedata" => Self::SetupMandateData,
"session" => Self::Session,
"sessiondata" => Self::SessionData,
_ => Self::Authorize,
}
}
}
impl Derives {
fn to_operation(
self,
@ -82,8 +59,9 @@ impl Derives {
}
}
#[derive(PartialEq, Eq, Hash)]
enum Conversion {
#[derive(Debug, Clone, strum::EnumString, strum::EnumIter, strum::Display)]
#[strum(serialize_all = "snake_case")]
pub enum Conversion {
ValidateRequest,
GetTracker,
Domain,
@ -93,34 +71,20 @@ enum Conversion {
Invalid(String),
}
impl From<String> for Conversion {
fn from(s: String) -> Self {
match s.as_str() {
"validate_request" => Self::ValidateRequest,
"get_tracker" => Self::GetTracker,
"domain" => Self::Domain,
"update_tracker" => Self::UpdateTracker,
"post_tracker" => Self::PostUpdateTracker,
"all" => Self::All,
s => Self::Invalid(s.to_string()),
}
}
}
impl Conversion {
fn get_req_type(ident: Derives) -> syn::Ident {
match ident {
Derives::Authorize => syn::Ident::new("PaymentsRequest", Span::call_site()),
Derives::Authorizedata => syn::Ident::new("PaymentsAuthorizeData", Span::call_site()),
Derives::AuthorizeData => syn::Ident::new("PaymentsAuthorizeData", Span::call_site()),
Derives::Sync => syn::Ident::new("PaymentsRetrieveRequest", Span::call_site()),
Derives::Syncdata => syn::Ident::new("PaymentsSyncData", Span::call_site()),
Derives::SyncData => syn::Ident::new("PaymentsSyncData", Span::call_site()),
Derives::Cancel => syn::Ident::new("PaymentsCancelRequest", Span::call_site()),
Derives::Canceldata => syn::Ident::new("PaymentsCancelData", Span::call_site()),
Derives::Approvedata => syn::Ident::new("PaymentsApproveData", Span::call_site()),
Derives::CancelData => syn::Ident::new("PaymentsCancelData", Span::call_site()),
Derives::ApproveData => syn::Ident::new("PaymentsApproveData", Span::call_site()),
Derives::Reject => syn::Ident::new("PaymentsRejectRequest", Span::call_site()),
Derives::Rejectdata => syn::Ident::new("PaymentsRejectData", Span::call_site()),
Derives::RejectData => syn::Ident::new("PaymentsRejectData", Span::call_site()),
Derives::Capture => syn::Ident::new("PaymentsCaptureRequest", Span::call_site()),
Derives::Capturedata => syn::Ident::new("PaymentsCaptureData", Span::call_site()),
Derives::CaptureData => syn::Ident::new("PaymentsCaptureData", Span::call_site()),
Derives::CompleteAuthorizeData => {
syn::Ident::new("CompleteAuthorizeData", Span::call_site())
}
@ -231,103 +195,206 @@ impl Conversion {
}
}
fn find_operation_attr(a: &[syn::Attribute]) -> syn::Result<syn::Attribute> {
a.iter()
.find(|a| {
a.path
.get_ident()
.map(|ident| *ident == "operation")
.unwrap_or(false)
})
.cloned()
.ok_or_else(|| {
helpers::syn_error(
mod operations_keyword {
use syn::custom_keyword;
custom_keyword!(operations);
custom_keyword!(flow);
}
#[derive(Debug)]
pub enum OperationsEnumMeta {
Operations {
keyword: operations_keyword::operations,
value: Vec<Conversion>,
},
Flow {
keyword: operations_keyword::flow,
value: Vec<Derives>,
},
}
#[derive(Clone)]
pub struct OperationProperties {
operations: Vec<Conversion>,
flows: Vec<Derives>,
}
fn get_operation_properties(
operation_enums: Vec<OperationsEnumMeta>,
) -> syn::Result<OperationProperties> {
let mut operations = vec![];
let mut flows = vec![];
for operation in operation_enums {
match operation {
OperationsEnumMeta::Operations { value, .. } => {
operations = value;
}
OperationsEnumMeta::Flow { value, .. } => {
flows = value;
}
}
}
if operations.is_empty() {
Err(syn::Error::new(
Span::call_site(),
"Cannot find attribute 'operation' in the macro",
"atleast one operation must be specitied",
))?;
}
if flows.is_empty() {
Err(syn::Error::new(
Span::call_site(),
"atleast one flow must be specitied",
))?;
}
Ok(OperationProperties { operations, flows })
}
impl Parse for Derives {
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
let text = input.parse::<syn::LitStr>()?;
let value = text.value();
value.as_str().parse().map_err(|_| {
syn::Error::new_spanned(
&text,
format!(
"Unexpected value for flow: `{value}`. Possible values are `{}`",
helpers::get_possible_values_for_enum::<Self>()
),
)
})
}
fn find_value(v: &NestedMeta) -> Option<(String, Vec<String>)> {
match v {
NestedMeta::Meta(Meta::NameValue(MetaNameValue {
ref path,
eq_token: _,
lit: Lit::Str(ref litstr),
})) => {
let key = path.get_ident()?.to_string();
Some((
key,
litstr.value().split(',').map(ToString::to_string).collect(),
))
}
_ => None,
impl Parse for Conversion {
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
let text = input.parse::<syn::LitStr>()?;
let value = text.value();
value.as_str().parse().map_err(|_| {
syn::Error::new_spanned(
&text,
format!(
"Unexpected value for operation: `{value}`. Possible values are `{}`",
helpers::get_possible_values_for_enum::<Self>()
),
)
})
}
}
fn find_properties(attr: &syn::Attribute) -> syn::Result<HashMap<String, Vec<String>>> {
let meta = attr.parse_meta();
match meta {
Ok(syn::Meta::List(syn::MetaList {
ref path,
paren_token: _,
nested,
})) => {
path.get_ident().map(|i| i == "operation").ok_or_else(|| {
helpers::syn_error(path.span(), "Attribute 'operation' was not found")
})?;
Ok(HashMap::from_iter(nested.iter().filter_map(find_value)))
fn parse_list_string<T>(list_string: String, keyword: &str) -> syn::Result<Vec<T>>
where
T: FromStr + IntoEnumIterator + ToString,
{
list_string
.split(',')
.map(str::trim)
.map(T::from_str)
.map(|result| {
result.map_err(|_| {
syn::Error::new(
Span::call_site(),
format!(
"Unexpected {keyword}, possible values are {}",
helpers::get_possible_values_for_enum::<T>()
),
)
})
})
.collect()
}
fn get_conversions(input: syn::parse::ParseStream<'_>) -> syn::Result<Vec<Conversion>> {
let lit_str_list = input.parse::<syn::LitStr>()?;
parse_list_string(lit_str_list.value(), "operation")
}
fn get_derives(input: syn::parse::ParseStream<'_>) -> syn::Result<Vec<Derives>> {
let lit_str_list = input.parse::<syn::LitStr>()?;
parse_list_string(lit_str_list.value(), "flow")
}
impl Parse for OperationsEnumMeta {
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(operations_keyword::operations) {
let keyword = input.parse()?;
input.parse::<syn::Token![=]>()?;
let value = get_conversions(input)?;
Ok(Self::Operations { keyword, value })
} else if lookahead.peek(operations_keyword::flow) {
let keyword = input.parse()?;
input.parse::<syn::Token![=]>()?;
let value = get_derives(input)?;
Ok(Self::Flow { keyword, value })
} else {
Err(lookahead.error())
}
}
}
trait OperationsDeriveInputExt {
/// Get all the error metadata associated with an enum.
fn get_metadata(&self) -> syn::Result<Vec<OperationsEnumMeta>>;
}
impl OperationsDeriveInputExt for DeriveInput {
fn get_metadata(&self) -> syn::Result<Vec<OperationsEnumMeta>> {
helpers::get_metadata_inner("operation", &self.attrs)
}
}
impl ToTokens for OperationsEnumMeta {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
Self::Operations { keyword, .. } => keyword.to_tokens(tokens),
Self::Flow { keyword, .. } => keyword.to_tokens(tokens),
}
_ => Err(helpers::syn_error(
attr.span(),
"No attributes were found. Expected format is ops=..,flow=..",
)),
}
}
pub fn operation_derive_inner(input: DeriveInput) -> syn::Result<proc_macro::TokenStream> {
let struct_name = &input.ident;
let op = find_operation_attr(&input.attrs)?;
let prop = find_properties(&op)?;
let ops = prop.get("ops").ok_or_else(|| {
helpers::syn_error(
op.span(),
"Invalid properties. Property 'ops' was not found",
)
})?;
let flow = prop.get("flow").ok_or_else(|| {
helpers::syn_error(
op.span(),
"Invalid properties. Property 'flow' was not found",
)
})?;
let current_crate = syn::Ident::new(
&prop
.get("crate")
.map(|v| v.join(""))
.unwrap_or_else(|| String::from("crate")),
Span::call_site(),
);
let operations_meta = input.get_metadata()?;
let operation_properties = get_operation_properties(operations_meta)?;
let trait_derive = flow.iter().map(|derive| {
let derive: Derives = derive.to_owned().into();
let fns = ops.iter().map(|t| {
let con: Conversion = t.to_owned().into();
con.to_function(derive)
});
let current_crate = syn::Ident::new("crate", Span::call_site());
let trait_derive = operation_properties
.clone()
.flows
.into_iter()
.map(|derive| {
let fns = operation_properties
.operations
.iter()
.map(|conversion| conversion.to_function(derive));
derive.to_operation(fns, struct_name)
});
let ref_trait_derive = flow.iter().map(|derive| {
let derive: Derives = derive.to_owned().into();
let fns = ops.iter().map(|t| {
let con: Conversion = t.to_owned().into();
con.to_ref_function(derive)
});
})
.collect::<Vec<_>>();
let ref_trait_derive = operation_properties
.flows
.into_iter()
.map(|derive| {
let fns = operation_properties
.operations
.iter()
.map(|conversion| conversion.to_ref_function(derive));
derive.to_ref_operation(fns, struct_name)
});
})
.collect::<Vec<_>>();
let trait_derive = quote! {
#(#ref_trait_derive)* #(#trait_derive)*
};
let output = quote! {
const _: () = {
use #current_crate::core::errors::RouterResult;

View File

@ -1,21 +1,62 @@
use proc_macro2::Span;
use syn::punctuated::Punctuated;
use quote::ToTokens;
use syn::{parse::Parse, punctuated::Punctuated};
mod try_get_keyword {
use syn::custom_keyword;
custom_keyword!(error_type);
}
#[derive(Debug)]
pub struct TryGetEnumMeta {
error_type: syn::Ident,
variant: syn::Ident,
}
impl Parse for TryGetEnumMeta {
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
let error_type = input.parse()?;
_ = input.parse::<syn::Token![::]>()?;
let variant = input.parse()?;
Ok(Self {
error_type,
variant,
})
}
}
trait TryGetDeriveInputExt {
/// Get all the error metadata associated with an enum.
fn get_metadata(&self) -> syn::Result<Vec<TryGetEnumMeta>>;
}
impl TryGetDeriveInputExt for syn::DeriveInput {
fn get_metadata(&self) -> syn::Result<Vec<TryGetEnumMeta>> {
super::helpers::get_metadata_inner("error", &self.attrs)
}
}
impl ToTokens for TryGetEnumMeta {
fn to_tokens(&self, _: &mut proc_macro2::TokenStream) {}
}
/// Try and get the variants for an enum
pub fn try_get_enum_variant(
input: syn::DeriveInput,
) -> Result<proc_macro2::TokenStream, syn::Error> {
let name = &input.ident;
let parsed_error_type = input.get_metadata()?;
let (error_type, error_variant) = parsed_error_type
.first()
.ok_or(syn::Error::new(
Span::call_site(),
"One error should be specified",
))
.map(|error_struct| (&error_struct.error_type, &error_struct.variant))?;
let error_attr = input
.attrs
.iter()
.find(|attr| attr.path.is_ident("error"))
.ok_or(super::helpers::syn_error(
proc_macro2::Span::call_site(),
"Unable to find attribute error. Expected #[error(..)]",
))?;
let (error_type, error_variant) = get_error_type_and_variant(error_attr)?;
let (impl_generics, generics, where_clause) = input.generics.split_for_impl();
let variants = get_enum_variants(&input.data)?;
@ -49,52 +90,6 @@ pub fn try_get_enum_variant(
Ok(expanded)
}
/// Parses the attribute #[error(ErrorType(ErrorVariant))]
fn get_error_type_and_variant(attr: &syn::Attribute) -> syn::Result<(syn::Ident, syn::Path)> {
let meta = attr.parse_meta()?;
let metalist = match meta {
syn::Meta::List(list) => list,
_ => {
return Err(super::helpers::syn_error(
proc_macro2::Span::call_site(),
"Invalid attribute format #[error(ErrorType(ErrorVariant)]",
))
}
};
for meta in metalist.nested.iter() {
if let syn::NestedMeta::Meta(syn::Meta::List(meta)) = meta {
let error_type = meta
.path
.get_ident()
.ok_or(super::helpers::syn_error(
proc_macro2::Span::call_site(),
"Invalid attribute format #[error(ErrorType(ErrorVariant))]",
))
.cloned()?;
let error_variant = get_error_variant(meta)?;
return Ok((error_type, error_variant));
};
}
Err(super::helpers::syn_error(
proc_macro2::Span::call_site(),
"Invalid attribute format #[error(ErrorType(ErrorVariant))]",
))
}
fn get_error_variant(meta: &syn::MetaList) -> syn::Result<syn::Path> {
for meta in meta.nested.iter() {
if let syn::NestedMeta::Meta(syn::Meta::Path(meta)) = meta {
return Ok(meta.clone());
}
}
Err(super::helpers::syn_error(
proc_macro2::Span::call_site(),
"Invalid attribute format expected #[error(ErrorType(ErrorVariant))]",
))
}
/// Get variants from Enum
fn get_enum_variants(data: &syn::Data) -> syn::Result<Punctuated<syn::Variant, syn::token::Comma>> {
if let syn::Data::Enum(syn::DataEnum { variants, .. }) = data {

View File

@ -60,7 +60,7 @@ pub enum KvOperation<'a, S: serde::Serialize + Debug> {
}
#[derive(TryGetEnumVariant)]
#[error(RedisError(UnknownResult))]
#[error(RedisError::UnknownResult)]
pub enum KvResult<T: de::DeserializeOwned> {
HGet(T),
Get(T),