mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 04:04:55 +08:00
refactor(id_type): use macros for defining ID types and implementing common traits (#5471)
This commit is contained in:
@ -1,104 +1,14 @@
|
||||
use std::{borrow::Cow, fmt::Debug};
|
||||
|
||||
use diesel::{
|
||||
backend::Backend,
|
||||
deserialize::FromSql,
|
||||
expression::AsExpression,
|
||||
serialize::{Output, ToSql},
|
||||
sql_types, Queryable,
|
||||
};
|
||||
use error_stack::{Result, ResultExt};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
consts::{MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH, MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH},
|
||||
errors, generate_customer_id_of_default_length,
|
||||
id_type::LengthId,
|
||||
};
|
||||
|
||||
/// A type for customer_id that can be used for customer ids
|
||||
#[derive(Clone, Serialize, Deserialize, Hash, PartialEq, Eq, AsExpression)]
|
||||
#[diesel(sql_type = sql_types::Text)]
|
||||
pub struct CustomerId(
|
||||
LengthId<MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH, MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH>,
|
||||
crate::id_type!(
|
||||
CustomerId,
|
||||
"A type for customer_id that can be used for customer ids"
|
||||
);
|
||||
crate::impl_id_type_methods!(CustomerId, "customer_id");
|
||||
|
||||
impl Default for CustomerId {
|
||||
fn default() -> Self {
|
||||
generate_customer_id_of_default_length()
|
||||
}
|
||||
}
|
||||
// This is to display the `CustomerId` as CustomerId(abcd)
|
||||
crate::impl_debug_id_type!(CustomerId);
|
||||
crate::impl_default_id_type!(CustomerId, "cus");
|
||||
crate::impl_try_from_cow_str_id_type!(CustomerId, "customer_id");
|
||||
|
||||
/// This is to display the `CustomerId` as CustomerId(abcd)
|
||||
impl Debug for CustomerId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple("CustomerId").field(&self.0 .0 .0).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> Queryable<sql_types::Text, DB> for CustomerId
|
||||
where
|
||||
DB: Backend,
|
||||
Self: FromSql<sql_types::Text, DB>,
|
||||
{
|
||||
type Row = Self;
|
||||
|
||||
fn build(row: Self::Row) -> diesel::deserialize::Result<Self> {
|
||||
Ok(row)
|
||||
}
|
||||
}
|
||||
|
||||
impl CustomerId {
|
||||
pub(crate) fn new(
|
||||
merchant_ref_id: LengthId<
|
||||
MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH,
|
||||
MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH,
|
||||
>,
|
||||
) -> Self {
|
||||
Self(merchant_ref_id)
|
||||
}
|
||||
|
||||
/// Get the string representation of customer id
|
||||
pub fn get_string_repr(&self) -> &str {
|
||||
&self.0 .0 .0
|
||||
}
|
||||
|
||||
/// Create a Customer id from string
|
||||
pub fn from(input_string: Cow<'static, str>) -> Result<Self, errors::ValidationError> {
|
||||
let merchant_ref_id = LengthId::from(input_string).change_context(
|
||||
errors::ValidationError::IncorrectValueProvided {
|
||||
field_name: "customer_id",
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(Self(merchant_ref_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl masking::SerializableSecret for CustomerId {}
|
||||
|
||||
impl<DB> ToSql<sql_types::Text, DB> for CustomerId
|
||||
where
|
||||
DB: Backend,
|
||||
LengthId<MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH, MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH>:
|
||||
ToSql<sql_types::Text, DB>,
|
||||
{
|
||||
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> diesel::serialize::Result {
|
||||
self.0.to_sql(out)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> FromSql<sql_types::Text, DB> for CustomerId
|
||||
where
|
||||
DB: Backend,
|
||||
LengthId<MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH, MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH>:
|
||||
FromSql<sql_types::Text, DB>,
|
||||
{
|
||||
fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result<Self> {
|
||||
LengthId::<
|
||||
MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH,
|
||||
MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH,
|
||||
>::from_sql(value)
|
||||
.map(Self)
|
||||
}
|
||||
}
|
||||
crate::impl_serializable_secret_id_type!(CustomerId);
|
||||
crate::impl_queryable_id_type!(CustomerId);
|
||||
crate::impl_to_sql_from_sql_id_type!(CustomerId);
|
||||
|
||||
@ -3,51 +3,29 @@
|
||||
//! Ids for merchant account are derived from the merchant name
|
||||
//! If there are any special characters, they are removed
|
||||
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
fmt::{Debug, Display},
|
||||
};
|
||||
|
||||
use diesel::{
|
||||
backend::Backend,
|
||||
deserialize::FromSql,
|
||||
expression::AsExpression,
|
||||
serialize::{Output, ToSql},
|
||||
sql_types, Queryable,
|
||||
};
|
||||
use error_stack::{Result, ResultExt};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::{
|
||||
consts::{MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH, MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH},
|
||||
date_time, errors, generate_id_with_default_len, generate_ref_id_with_default_length,
|
||||
date_time, generate_id_with_default_len,
|
||||
id_type::{AlphaNumericId, LengthId},
|
||||
new_type::MerchantName,
|
||||
types::keymanager,
|
||||
};
|
||||
|
||||
/// A type for merchant_id that can be used for merchant ids
|
||||
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, AsExpression, Hash, ToSchema)]
|
||||
#[diesel(sql_type = sql_types::Text)]
|
||||
#[schema(value_type = String)]
|
||||
pub struct MerchantId(
|
||||
LengthId<MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH, MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH>,
|
||||
crate::id_type!(
|
||||
MerchantId,
|
||||
"A type for merchant_id that can be used for merchant ids"
|
||||
);
|
||||
crate::impl_id_type_methods!(MerchantId, "merchant_id");
|
||||
|
||||
/// This is to display the `MerchantId` as MerchantId(abcd)
|
||||
impl Debug for MerchantId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple("MerchantId").field(&self.0 .0 .0).finish()
|
||||
}
|
||||
}
|
||||
// This is to display the `MerchantId` as MerchantId(abcd)
|
||||
crate::impl_debug_id_type!(MerchantId);
|
||||
crate::impl_default_id_type!(MerchantId, "mer");
|
||||
crate::impl_try_from_cow_str_id_type!(MerchantId, "merchant_id");
|
||||
|
||||
/// This should be temporary, we should not have direct impl of Display for merchant id
|
||||
impl Display for MerchantId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.get_string_repr())
|
||||
}
|
||||
}
|
||||
crate::impl_serializable_secret_id_type!(MerchantId);
|
||||
crate::impl_queryable_id_type!(MerchantId);
|
||||
crate::impl_to_sql_from_sql_id_type!(MerchantId);
|
||||
|
||||
#[cfg(feature = "metrics")]
|
||||
/// This is implemented so that we can use merchant id directly as attribute in metrics
|
||||
@ -58,41 +36,7 @@ impl From<MerchantId> for router_env::opentelemetry::Value {
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> Queryable<sql_types::Text, DB> for MerchantId
|
||||
where
|
||||
DB: Backend,
|
||||
Self: FromSql<sql_types::Text, DB>,
|
||||
{
|
||||
type Row = Self;
|
||||
|
||||
fn build(row: Self::Row) -> diesel::deserialize::Result<Self> {
|
||||
Ok(row)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MerchantId {
|
||||
fn default() -> Self {
|
||||
Self(generate_ref_id_with_default_length("mer"))
|
||||
}
|
||||
}
|
||||
|
||||
impl MerchantId {
|
||||
/// Get the string representation of merchant id
|
||||
pub fn get_string_repr(&self) -> &str {
|
||||
&self.0 .0 .0
|
||||
}
|
||||
|
||||
/// Create a Merchant id from string
|
||||
pub fn from(input_string: Cow<'static, str>) -> Result<Self, errors::ValidationError> {
|
||||
let length_id = LengthId::from(input_string).change_context(
|
||||
errors::ValidationError::IncorrectValueProvided {
|
||||
field_name: "merchant_id",
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(Self(length_id))
|
||||
}
|
||||
|
||||
/// Create a Merchant id from MerchantName
|
||||
pub fn from_merchant_name(merchant_name: MerchantName) -> Self {
|
||||
let merchant_name_string = merchant_name.into_inner();
|
||||
@ -144,34 +88,6 @@ impl From<MerchantId> for keymanager::Identifier {
|
||||
}
|
||||
}
|
||||
|
||||
impl masking::SerializableSecret for MerchantId {}
|
||||
|
||||
impl<DB> ToSql<sql_types::Text, DB> for MerchantId
|
||||
where
|
||||
DB: Backend,
|
||||
LengthId<MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH, MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH>:
|
||||
ToSql<sql_types::Text, DB>,
|
||||
{
|
||||
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> diesel::serialize::Result {
|
||||
self.0.to_sql(out)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> FromSql<sql_types::Text, DB> for MerchantId
|
||||
where
|
||||
DB: Backend,
|
||||
LengthId<MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH, MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH>:
|
||||
FromSql<sql_types::Text, DB>,
|
||||
{
|
||||
fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result<Self> {
|
||||
LengthId::<
|
||||
MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH,
|
||||
MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH,
|
||||
>::from_sql(value)
|
||||
.map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
/// All the keys that can be formed from merchant id
|
||||
impl MerchantId {
|
||||
/// get step up enabled key
|
||||
|
||||
@ -1,106 +1,14 @@
|
||||
use std::{borrow::Cow, fmt::Debug};
|
||||
|
||||
use diesel::{
|
||||
backend::Backend,
|
||||
deserialize::FromSql,
|
||||
expression::AsExpression,
|
||||
serialize::{Output, ToSql},
|
||||
sql_types, Queryable,
|
||||
};
|
||||
use error_stack::{Result, ResultExt};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
consts::{MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH, MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH},
|
||||
errors, generate_organization_id_of_default_length,
|
||||
id_type::LengthId,
|
||||
};
|
||||
|
||||
/// A type for customer_id that can be used for customer ids
|
||||
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, AsExpression, Hash)]
|
||||
#[diesel(sql_type = sql_types::Text)]
|
||||
pub struct OrganizationId(
|
||||
LengthId<MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH, MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH>,
|
||||
crate::id_type!(
|
||||
OrganizationId,
|
||||
"A type for organization_id that can be used for organization ids"
|
||||
);
|
||||
crate::impl_id_type_methods!(OrganizationId, "organization_id");
|
||||
|
||||
impl Default for OrganizationId {
|
||||
fn default() -> Self {
|
||||
generate_organization_id_of_default_length()
|
||||
}
|
||||
}
|
||||
// This is to display the `OrganizationId` as OrganizationId(abcd)
|
||||
crate::impl_debug_id_type!(OrganizationId);
|
||||
crate::impl_default_id_type!(OrganizationId, "org");
|
||||
crate::impl_try_from_cow_str_id_type!(OrganizationId, "organization_id");
|
||||
|
||||
/// This is to display the `OrganizationId` as OrganizationId(abcd)
|
||||
impl Debug for OrganizationId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple("OrganizationId")
|
||||
.field(&self.0 .0 .0)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> Queryable<sql_types::Text, DB> for OrganizationId
|
||||
where
|
||||
DB: Backend,
|
||||
Self: FromSql<sql_types::Text, DB>,
|
||||
{
|
||||
type Row = Self;
|
||||
|
||||
fn build(row: Self::Row) -> diesel::deserialize::Result<Self> {
|
||||
Ok(row)
|
||||
}
|
||||
}
|
||||
|
||||
impl OrganizationId {
|
||||
pub(crate) fn new(
|
||||
organization_id: LengthId<
|
||||
MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH,
|
||||
MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH,
|
||||
>,
|
||||
) -> Self {
|
||||
Self(organization_id)
|
||||
}
|
||||
|
||||
/// Get the string representation of customer id
|
||||
pub fn get_string_repr(&self) -> &str {
|
||||
&self.0 .0 .0
|
||||
}
|
||||
|
||||
/// Create a Customer id from string
|
||||
pub fn from(input_string: Cow<'static, str>) -> Result<Self, errors::ValidationError> {
|
||||
let organization_id = LengthId::from(input_string).change_context(
|
||||
errors::ValidationError::IncorrectValueProvided {
|
||||
field_name: "customer_id",
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(Self(organization_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl masking::SerializableSecret for OrganizationId {}
|
||||
|
||||
impl<DB> ToSql<sql_types::Text, DB> for OrganizationId
|
||||
where
|
||||
DB: Backend,
|
||||
LengthId<MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH, MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH>:
|
||||
ToSql<sql_types::Text, DB>,
|
||||
{
|
||||
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> diesel::serialize::Result {
|
||||
self.0.to_sql(out)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> FromSql<sql_types::Text, DB> for OrganizationId
|
||||
where
|
||||
DB: Backend,
|
||||
LengthId<MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH, MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH>:
|
||||
FromSql<sql_types::Text, DB>,
|
||||
{
|
||||
fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result<Self> {
|
||||
LengthId::<
|
||||
MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH,
|
||||
MIN_REQUIRED_MERCHANT_REFERENCE_ID_LENGTH,
|
||||
>::from_sql(value)
|
||||
.map(Self)
|
||||
}
|
||||
}
|
||||
crate::impl_serializable_secret_id_type!(OrganizationId);
|
||||
crate::impl_queryable_id_type!(OrganizationId);
|
||||
crate::impl_to_sql_from_sql_id_type!(OrganizationId);
|
||||
|
||||
@ -217,12 +217,12 @@ fn generate_ref_id_with_default_length<const MAX_LENGTH: u8, const MIN_LENGTH: u
|
||||
|
||||
/// Generate a customer id with default length, with prefix as `cus`
|
||||
pub fn generate_customer_id_of_default_length() -> id_type::CustomerId {
|
||||
id_type::CustomerId::new(generate_ref_id_with_default_length("cus"))
|
||||
id_type::CustomerId::default()
|
||||
}
|
||||
|
||||
/// Generate a organization id with default length, with prefix as `org`
|
||||
pub fn generate_organization_id_of_default_length() -> id_type::OrganizationId {
|
||||
id_type::OrganizationId::new(generate_ref_id_with_default_length("org"))
|
||||
id_type::OrganizationId::default()
|
||||
}
|
||||
|
||||
/// Generate a nanoid with the given prefix and a default length
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
#![allow(missing_docs)]
|
||||
//! Utility macros
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[macro_export]
|
||||
macro_rules! newtype_impl {
|
||||
($is_pub:vis, $name:ident, $ty_path:path) => {
|
||||
impl std::ops::Deref for $name {
|
||||
impl core::ops::Deref for $name {
|
||||
type Target = $ty_path;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
@ -11,7 +12,7 @@ macro_rules! newtype_impl {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for $name {
|
||||
impl core::ops::DerefMut for $name {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
@ -31,6 +32,7 @@ macro_rules! newtype_impl {
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[macro_export]
|
||||
macro_rules! newtype {
|
||||
($is_pub:vis $name:ident = $ty_path:path) => {
|
||||
@ -59,6 +61,7 @@ macro_rules! openapi_route {
|
||||
}};
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[macro_export]
|
||||
macro_rules! fallback_reverse_lookup_not_found {
|
||||
($a:expr,$b:expr) => {
|
||||
@ -81,6 +84,8 @@ macro_rules! fallback_reverse_lookup_not_found {
|
||||
};
|
||||
}
|
||||
|
||||
/// 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)),+] => {
|
||||
@ -96,6 +101,8 @@ macro_rules! collect_missing_value_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) => {
|
||||
@ -135,3 +142,162 @@ macro_rules! impl_to_sql_from_sql_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 `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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user