mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 10:06:32 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			327 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			327 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| //! Utility macros
 | |
| 
 | |
| #[allow(missing_docs)]
 | |
| #[macro_export]
 | |
| macro_rules! newtype_impl {
 | |
|     ($is_pub:vis, $name:ident, $ty_path:path) => {
 | |
|         impl core::ops::Deref for $name {
 | |
|             type Target = $ty_path;
 | |
| 
 | |
|             fn deref(&self) -> &Self::Target {
 | |
|                 &self.0
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         impl core::ops::DerefMut for $name {
 | |
|             fn deref_mut(&mut self) -> &mut Self::Target {
 | |
|                 &mut self.0
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         impl From<$ty_path> for $name {
 | |
|             fn from(ty: $ty_path) -> Self {
 | |
|                 Self(ty)
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         impl $name {
 | |
|             pub fn into_inner(self) -> $ty_path {
 | |
|                 self.0
 | |
|             }
 | |
|         }
 | |
|     };
 | |
| }
 | |
| 
 | |
| #[allow(missing_docs)]
 | |
| #[macro_export]
 | |
| macro_rules! newtype {
 | |
|     ($is_pub:vis $name:ident = $ty_path:path) => {
 | |
|         $is_pub struct $name(pub $ty_path);
 | |
| 
 | |
|         $crate::newtype_impl!($is_pub, $name, $ty_path);
 | |
|     };
 | |
| 
 | |
|     ($is_pub:vis $name:ident = $ty_path:path, derives = ($($trt:path),*)) => {
 | |
|         #[derive($($trt),*)]
 | |
|         $is_pub struct $name(pub $ty_path);
 | |
| 
 | |
|         $crate::newtype_impl!($is_pub, $name, $ty_path);
 | |
|     };
 | |
| }
 | |
| 
 | |
| /// Use this to ensure that the corresponding
 | |
| /// openapi route has been implemented in the openapi crate
 | |
| #[macro_export]
 | |
| macro_rules! openapi_route {
 | |
|     ($route_name: ident) => {{
 | |
|         #[cfg(feature = "openapi")]
 | |
|         use openapi::routes::$route_name as _;
 | |
| 
 | |
|         $route_name
 | |
|     }};
 | |
| }
 | |
| 
 | |
| #[allow(missing_docs)]
 | |
| #[macro_export]
 | |
| macro_rules! fallback_reverse_lookup_not_found {
 | |
|     ($a:expr,$b:expr) => {
 | |
|         match $a {
 | |
|             Ok(res) => res,
 | |
|             Err(err) => {
 | |
|                 router_env::logger::error!(reverse_lookup_fallback = ?err);
 | |
|                 match err.current_context() {
 | |
|                     errors::StorageError::ValueNotFound(_) => return $b,
 | |
|                     errors::StorageError::DatabaseError(data_err) => {
 | |
|                         match data_err.current_context() {
 | |
|                             diesel_models::errors::DatabaseError::NotFound => return $b,
 | |
|                             _ => return Err(err)
 | |
|                         }
 | |
|                     }
 | |
|                     _=> return Err(err)
 | |
|                 }
 | |
|             }
 | |
|         };
 | |
|     };
 | |
| }
 | |
| 
 | |
| /// Collects names of all optional fields that are `None`.
 | |
| /// This is typically useful for constructing error messages including a list of all missing fields.
 | |
| #[macro_export]
 | |
| macro_rules! collect_missing_value_keys {
 | |
|     [$(($key:literal, $option:expr)),+] => {
 | |
|         {
 | |
|             let mut keys: Vec<&'static str> = Vec::new();
 | |
|             $(
 | |
|                 if $option.is_none() {
 | |
|                     keys.push($key);
 | |
|                 }
 | |
|             )*
 | |
|             keys
 | |
|         }
 | |
|     };
 | |
| }
 | |
| 
 | |
| /// Implements the `ToSql` and `FromSql` traits on a type to allow it to be serialized/deserialized
 | |
| /// to/from JSON data in the database.
 | |
| #[macro_export]
 | |
| macro_rules! impl_to_sql_from_sql_json {
 | |
|     ($type:ty, $diesel_type:ty) => {
 | |
|         #[allow(unused_qualifications)]
 | |
|         impl diesel::serialize::ToSql<$diesel_type, diesel::pg::Pg> for $type {
 | |
|             fn to_sql<'b>(
 | |
|                 &'b self,
 | |
|                 out: &mut diesel::serialize::Output<'b, '_, diesel::pg::Pg>,
 | |
|             ) -> diesel::serialize::Result {
 | |
|                 let value = serde_json::to_value(self)?;
 | |
| 
 | |
|                 // the function `reborrow` only works in case of `Pg` backend. But, in case of other backends
 | |
|                 // please refer to the diesel migration blog:
 | |
|                 // https://github.com/Diesel-rs/Diesel/blob/master/guide_drafts/migration_guide.md#changed-tosql-implementations
 | |
|                 <serde_json::Value as diesel::serialize::ToSql<
 | |
|                                                                 $diesel_type,
 | |
|                                                                 diesel::pg::Pg,
 | |
|                                                             >>::to_sql(&value, &mut out.reborrow())
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         #[allow(unused_qualifications)]
 | |
|         impl diesel::deserialize::FromSql<$diesel_type, diesel::pg::Pg> for $type {
 | |
|             fn from_sql(
 | |
|                 bytes: <diesel::pg::Pg as diesel::backend::Backend>::RawValue<'_>,
 | |
|             ) -> diesel::deserialize::Result<Self> {
 | |
|                 let value = <serde_json::Value as diesel::deserialize::FromSql<
 | |
|                     $diesel_type,
 | |
|                     diesel::pg::Pg,
 | |
|                 >>::from_sql(bytes)?;
 | |
|                 Ok(serde_json::from_value(value)?)
 | |
|             }
 | |
|         }
 | |
|     };
 | |
|     ($type: ty) => {
 | |
|         $crate::impl_to_sql_from_sql_json!($type, diesel::sql_types::Json);
 | |
|         $crate::impl_to_sql_from_sql_json!($type, diesel::sql_types::Jsonb);
 | |
|     };
 | |
| }
 | |
| 
 | |
| mod id_type {
 | |
|     /// Defines an ID type.
 | |
|     #[macro_export]
 | |
|     macro_rules! id_type {
 | |
|         ($type:ident, $doc:literal, $diesel_type:ty, $max_length:expr, $min_length:expr) => {
 | |
|             #[doc = $doc]
 | |
|             #[derive(
 | |
|                 Clone,
 | |
|                 Hash,
 | |
|                 PartialEq,
 | |
|                 Eq,
 | |
|                 serde::Serialize,
 | |
|                 serde::Deserialize,
 | |
|                 diesel::expression::AsExpression,
 | |
|             )]
 | |
|             #[diesel(sql_type = $diesel_type)]
 | |
|             pub struct $type($crate::id_type::LengthId<$max_length, $min_length>);
 | |
|         };
 | |
|         ($type:ident, $doc:literal) => {
 | |
|             $crate::id_type!(
 | |
|                 $type,
 | |
|                 $doc,
 | |
|                 diesel::sql_types::Text,
 | |
|                 { $crate::consts::MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH },
 | |
|                 { $crate::consts::MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH }
 | |
|             );
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     /// Implements common methods on the specified ID type.
 | |
|     #[macro_export]
 | |
|     macro_rules! impl_id_type_methods {
 | |
|         ($type:ty, $field_name:literal) => {
 | |
|             impl $type {
 | |
|                 /// Get the string representation of the ID type.
 | |
|                 pub fn get_string_repr(&self) -> &str {
 | |
|                     &self.0 .0 .0
 | |
|                 }
 | |
|             }
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     /// Implements the `Debug` trait on the specified ID type.
 | |
|     #[macro_export]
 | |
|     macro_rules! impl_debug_id_type {
 | |
|         ($type:ty) => {
 | |
|             impl core::fmt::Debug for $type {
 | |
|                 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
 | |
|                     f.debug_tuple(stringify!($type))
 | |
|                         .field(&self.0 .0 .0)
 | |
|                         .finish()
 | |
|                 }
 | |
|             }
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     /// Implements the `TryFrom<Cow<'static, str>>` trait on the specified ID type.
 | |
|     #[macro_export]
 | |
|     macro_rules! impl_try_from_cow_str_id_type {
 | |
|         ($type:ty, $field_name:literal) => {
 | |
|             impl TryFrom<std::borrow::Cow<'static, str>> for $type {
 | |
|                 type Error = error_stack::Report<$crate::errors::ValidationError>;
 | |
| 
 | |
|                 fn try_from(value: std::borrow::Cow<'static, str>) -> Result<Self, Self::Error> {
 | |
|                     use error_stack::ResultExt;
 | |
| 
 | |
|                     let merchant_ref_id = $crate::id_type::LengthId::from(value).change_context(
 | |
|                         $crate::errors::ValidationError::IncorrectValueProvided {
 | |
|                             field_name: $field_name,
 | |
|                         },
 | |
|                     )?;
 | |
| 
 | |
|                     Ok(Self(merchant_ref_id))
 | |
|                 }
 | |
|             }
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     /// Implements the `Default` trait on the specified ID type.
 | |
|     #[macro_export]
 | |
|     macro_rules! impl_default_id_type {
 | |
|         ($type:ty, $prefix:literal) => {
 | |
|             impl Default for $type {
 | |
|                 fn default() -> Self {
 | |
|                     Self($crate::generate_ref_id_with_default_length($prefix))
 | |
|                 }
 | |
|             }
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     /// Implements the `GenerateId` trait on the specified ID type.
 | |
|     #[macro_export]
 | |
|     macro_rules! impl_generate_id_id_type {
 | |
|         ($type:ty, $prefix:literal) => {
 | |
|             impl $crate::id_type::GenerateId for $type {
 | |
|                 fn generate() -> Self {
 | |
|                     Self($crate::generate_ref_id_with_default_length($prefix))
 | |
|                 }
 | |
|             }
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     /// Implements the `SerializableSecret` trait on the specified ID type.
 | |
|     #[macro_export]
 | |
|     macro_rules! impl_serializable_secret_id_type {
 | |
|         ($type:ty) => {
 | |
|             impl masking::SerializableSecret for $type {}
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     /// Implements the `ToSql` and `FromSql` traits on the specified ID type.
 | |
|     #[macro_export]
 | |
|     macro_rules! impl_to_sql_from_sql_id_type {
 | |
|         ($type:ty, $diesel_type:ty, $max_length:expr, $min_length:expr) => {
 | |
|             impl<DB> diesel::serialize::ToSql<$diesel_type, DB> for $type
 | |
|             where
 | |
|                 DB: diesel::backend::Backend,
 | |
|                 $crate::id_type::LengthId<$max_length, $min_length>:
 | |
|                     diesel::serialize::ToSql<$diesel_type, DB>,
 | |
|             {
 | |
|                 fn to_sql<'b>(
 | |
|                     &'b self,
 | |
|                     out: &mut diesel::serialize::Output<'b, '_, DB>,
 | |
|                 ) -> diesel::serialize::Result {
 | |
|                     self.0.to_sql(out)
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             impl<DB> diesel::deserialize::FromSql<$diesel_type, DB> for $type
 | |
|             where
 | |
|                 DB: diesel::backend::Backend,
 | |
|                 $crate::id_type::LengthId<$max_length, $min_length>:
 | |
|                     diesel::deserialize::FromSql<$diesel_type, DB>,
 | |
|             {
 | |
|                 fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result<Self> {
 | |
|                     $crate::id_type::LengthId::<$max_length, $min_length>::from_sql(value).map(Self)
 | |
|                 }
 | |
|             }
 | |
|         };
 | |
|         ($type:ty) => {
 | |
|             $crate::impl_to_sql_from_sql_id_type!(
 | |
|                 $type,
 | |
|                 diesel::sql_types::Text,
 | |
|                 { $crate::consts::MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH },
 | |
|                 { $crate::consts::MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH }
 | |
|             );
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     /// Implements the `Queryable` trait on the specified ID type.
 | |
|     #[macro_export]
 | |
|     macro_rules! impl_queryable_id_type {
 | |
|         ($type:ty, $diesel_type:ty) => {
 | |
|             impl<DB> diesel::Queryable<$diesel_type, DB> for $type
 | |
|             where
 | |
|                 DB: diesel::backend::Backend,
 | |
|                 Self: diesel::deserialize::FromSql<$diesel_type, DB>,
 | |
|             {
 | |
|                 type Row = Self;
 | |
| 
 | |
|                 fn build(row: Self::Row) -> diesel::deserialize::Result<Self> {
 | |
|                     Ok(row)
 | |
|                 }
 | |
|             }
 | |
|         };
 | |
|         ($type:ty) => {
 | |
|             $crate::impl_queryable_id_type!($type, diesel::sql_types::Text);
 | |
|         };
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Get the type name for a type
 | |
| #[macro_export]
 | |
| macro_rules! type_name {
 | |
|     ($type:ty) => {
 | |
|         std::any::type_name::<$type>()
 | |
|             .rsplit("::")
 | |
|             .nth(1)
 | |
|             .unwrap_or_default();
 | |
|     };
 | |
| }
 | 
