Test-Implementation Pair

Implementation: crates/common_utils/src/custom_serde.rs
================================================================================
//! Custom serialization/deserialization implementations.

/// Use the well-known ISO 8601 format when serializing and deserializing an
/// [`PrimitiveDateTime`][PrimitiveDateTime].
///
/// [PrimitiveDateTime]: ::time::PrimitiveDateTime
pub mod iso8601 {
    use std::num::NonZeroU8;

    use serde::{ser::Error as _, Deserializer, Serialize, Serializer};
    use time::{
        format_description::well_known::{
            iso8601::{Config, EncodedConfig, TimePrecision},
            Iso8601,
        },
        serde::iso8601,
        PrimitiveDateTime, UtcOffset,
    };

    const FORMAT_CONFIG: EncodedConfig = Config::DEFAULT
        .set_time_precision(TimePrecision::Second {
            decimal_digits: NonZeroU8::new(3),
        })
        .encode();

    /// Serialize a [`PrimitiveDateTime`] using the well-known ISO 8601 format.
    pub fn serialize<S>(date_time: &PrimitiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        date_time
            .assume_utc()
            .format(&Iso8601::<FORMAT_CONFIG>)
            .map_err(S::Error::custom)?
            .serialize(serializer)
    }

    /// Deserialize an [`PrimitiveDateTime`] from its ISO 8601 representation.
    pub fn deserialize<'a, D>(deserializer: D) -> Result<PrimitiveDateTime, D::Error>
    where
        D: Deserializer<'a>,
    {
        iso8601::deserialize(deserializer).map(|offset_date_time| {
            let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
            PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
        })
    }

    /// Use the well-known ISO 8601 format when serializing and deserializing an
    /// [`Option<PrimitiveDateTime>`][PrimitiveDateTime].
    ///
    /// [PrimitiveDateTime]: ::time::PrimitiveDateTime
    pub mod option {
        use serde::Serialize;
        use time::format_description::well_known::Iso8601;

        use super::*;

        /// Serialize an [`Option<PrimitiveDateTime>`] using the well-known ISO 8601 format.
        pub fn serialize<S>(
            date_time: &Option<PrimitiveDateTime>,
            serializer: S,
        ) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            date_time
                .map(|date_time| date_time.assume_utc().format(&Iso8601::<FORMAT_CONFIG>))
                .transpose()
                .map_err(S::Error::custom)?
                .serialize(serializer)
        }

        /// Deserialize an [`Option<PrimitiveDateTime>`] from its ISO 8601 representation.
        pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<PrimitiveDateTime>, D::Error>
        where
            D: Deserializer<'a>,
        {
            iso8601::option::deserialize(deserializer).map(|option_offset_date_time| {
                option_offset_date_time.map(|offset_date_time| {
                    let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
                    PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
                })
            })
        }
    }
    /// Use the well-known ISO 8601 format which is without timezone when serializing and deserializing an
    /// [`Option<PrimitiveDateTime>`][PrimitiveDateTime].
    ///
    /// [PrimitiveDateTime]: ::time::PrimitiveDateTime
    pub mod option_without_timezone {
        use serde::{de, Deserialize, Serialize};
        use time::macros::format_description;

        use super::*;

        /// Serialize an [`Option<PrimitiveDateTime>`] using the well-known ISO 8601 format which is without timezone.
        pub fn serialize<S>(
            date_time: &Option<PrimitiveDateTime>,
            serializer: S,
        ) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            date_time
                .map(|date_time| {
                    let format =
                        format_description!("[year]-[month]-[day]T[hour]:[minute]:[second]");
                    date_time.assume_utc().format(format)
                })
                .transpose()
                .map_err(S::Error::custom)?
                .serialize(serializer)
        }

        /// Deserialize an [`Option<PrimitiveDateTime>`] from its ISO 8601 representation.
        pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<PrimitiveDateTime>, D::Error>
        where
            D: Deserializer<'a>,
        {
            Option::deserialize(deserializer)?
                .map(|time_string| {
                    let format =
                        format_description!("[year]-[month]-[day]T[hour]:[minute]:[second]");
                    PrimitiveDateTime::parse(time_string, format).map_err(|_| {
                        de::Error::custom(format!(
                            "Failed to parse PrimitiveDateTime from {time_string}"
                        ))
                    })
                })
                .transpose()
        }
    }
}

/// Use the UNIX timestamp when serializing and deserializing an
/// [`PrimitiveDateTime`][PrimitiveDateTime].
///
/// [PrimitiveDateTime]: ::time::PrimitiveDateTime
pub mod timestamp {

    use serde::{Deserializer, Serialize, Serializer};
    use time::{serde::timestamp, PrimitiveDateTime, UtcOffset};

    /// Serialize a [`PrimitiveDateTime`] using UNIX timestamp.
    pub fn serialize<S>(date_time: &PrimitiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        date_time
            .assume_utc()
            .unix_timestamp()
            .serialize(serializer)
    }

    /// Deserialize an [`PrimitiveDateTime`] from UNIX timestamp.
    pub fn deserialize<'a, D>(deserializer: D) -> Result<PrimitiveDateTime, D::Error>
    where
        D: Deserializer<'a>,
    {
        timestamp::deserialize(deserializer).map(|offset_date_time| {
            let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
            PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
        })
    }

    /// Use the UNIX timestamp when serializing and deserializing an
    /// [`Option<PrimitiveDateTime>`][PrimitiveDateTime].
    ///
    /// [PrimitiveDateTime]: ::time::PrimitiveDateTime
    pub mod option {
        use serde::Serialize;

        use super::*;

        /// Serialize an [`Option<PrimitiveDateTime>`] from UNIX timestamp.
        pub fn serialize<S>(
            date_time: &Option<PrimitiveDateTime>,
            serializer: S,
        ) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            date_time
                .map(|date_time| date_time.assume_utc().unix_timestamp())
                .serialize(serializer)
        }

        /// Deserialize an [`Option<PrimitiveDateTime>`] from UNIX timestamp.
        pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<PrimitiveDateTime>, D::Error>
        where
            D: Deserializer<'a>,
        {
            timestamp::option::deserialize(deserializer).map(|option_offset_date_time| {
                option_offset_date_time.map(|offset_date_time| {
                    let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
                    PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
                })
            })
        }
    }
}

/// <https://github.com/serde-rs/serde/issues/994#issuecomment-316895860>
pub mod json_string {
    use serde::{
        de::{self, Deserialize, DeserializeOwned, Deserializer},
        ser::{self, Serialize, Serializer},
    };

    /// Serialize a type to json_string format
    pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
    where
        T: Serialize,
        S: Serializer,
    {
        let j = serde_json::to_string(value).map_err(ser::Error::custom)?;
        j.serialize(serializer)
    }

    /// Deserialize a string which is in json format
    pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
    where
        T: DeserializeOwned,
        D: Deserializer<'de>,
    {
        let j = String::deserialize(deserializer)?;
        serde_json::from_str(&j).map_err(de::Error::custom)
    }
}

/// Use a custom ISO 8601 format when serializing and deserializing
/// [`PrimitiveDateTime`][PrimitiveDateTime].
///
/// [PrimitiveDateTime]: ::time::PrimitiveDateTime
pub mod iso8601custom {

    use serde::{ser::Error as _, Deserializer, Serialize, Serializer};
    use time::{
        format_description::well_known::{
            iso8601::{Config, EncodedConfig, TimePrecision},
            Iso8601,
        },
        serde::iso8601,
        PrimitiveDateTime, UtcOffset,
    };

    const FORMAT_CONFIG: EncodedConfig = Config::DEFAULT
        .set_time_precision(TimePrecision::Second {
            decimal_digits: None,
        })
        .encode();

    /// Serialize a [`PrimitiveDateTime`] using the well-known ISO 8601 format.
    pub fn serialize<S>(date_time: &PrimitiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        date_time
            .assume_utc()
            .format(&Iso8601::<FORMAT_CONFIG>)
            .map_err(S::Error::custom)?
            .replace('T', " ")
            .replace('Z', "")
            .serialize(serializer)
    }

    /// Deserialize an [`PrimitiveDateTime`] from its ISO 8601 representation.
    pub fn deserialize<'a, D>(deserializer: D) -> Result<PrimitiveDateTime, D::Error>
    where
        D: Deserializer<'a>,
    {
        iso8601::deserialize(deserializer).map(|offset_date_time| {
            let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
            PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
        })
    }
}

#[cfg(test)]
mod tests {
    use serde::{Deserialize, Serialize};
    use serde_json::json;

    #[test]
    fn test_leap_second_parse() {
        #[derive(Serialize, Deserialize)]
        struct Try {
            #[serde(with = "crate::custom_serde::iso8601")]
            f: time::PrimitiveDateTime,
        }
        let leap_second_date_time = json!({"f": "2023-12-31T23:59:60.000Z"});
        let deser = serde_json::from_value::<Try>(leap_second_date_time);

        assert!(deser.is_ok())
    }
}

Tests: crates/common_utils/src/custom_serde.rs
================================================================================
//! Custom serialization/deserialization implementations.

/// Use the well-known ISO 8601 format when serializing and deserializing an
/// [`PrimitiveDateTime`][PrimitiveDateTime].
///
/// [PrimitiveDateTime]: ::time::PrimitiveDateTime
pub mod iso8601 {
    use std::num::NonZeroU8;

    use serde::{ser::Error as _, Deserializer, Serialize, Serializer};
    use time::{
        format_description::well_known::{
            iso8601::{Config, EncodedConfig, TimePrecision},
            Iso8601,
        },
        serde::iso8601,
        PrimitiveDateTime, UtcOffset,
    };

    const FORMAT_CONFIG: EncodedConfig = Config::DEFAULT
        .set_time_precision(TimePrecision::Second {
            decimal_digits: NonZeroU8::new(3),
        })
        .encode();

    /// Serialize a [`PrimitiveDateTime`] using the well-known ISO 8601 format.
    pub fn serialize<S>(date_time: &PrimitiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        date_time
            .assume_utc()
            .format(&Iso8601::<FORMAT_CONFIG>)
            .map_err(S::Error::custom)?
            .serialize(serializer)
    }

    /// Deserialize an [`PrimitiveDateTime`] from its ISO 8601 representation.
    pub fn deserialize<'a, D>(deserializer: D) -> Result<PrimitiveDateTime, D::Error>
    where
        D: Deserializer<'a>,
    {
        iso8601::deserialize(deserializer).map(|offset_date_time| {
            let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
            PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
        })
    }

    /// Use the well-known ISO 8601 format when serializing and deserializing an
    /// [`Option<PrimitiveDateTime>`][PrimitiveDateTime].
    ///
    /// [PrimitiveDateTime]: ::time::PrimitiveDateTime
    pub mod option {
        use serde::Serialize;
        use time::format_description::well_known::Iso8601;

        use super::*;

        /// Serialize an [`Option<PrimitiveDateTime>`] using the well-known ISO 8601 format.
        pub fn serialize<S>(
            date_time: &Option<PrimitiveDateTime>,
            serializer: S,
        ) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            date_time
                .map(|date_time| date_time.assume_utc().format(&Iso8601::<FORMAT_CONFIG>))
                .transpose()
                .map_err(S::Error::custom)?
                .serialize(serializer)
        }

        /// Deserialize an [`Option<PrimitiveDateTime>`] from its ISO 8601 representation.
        pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<PrimitiveDateTime>, D::Error>
        where
            D: Deserializer<'a>,
        {
            iso8601::option::deserialize(deserializer).map(|option_offset_date_time| {
                option_offset_date_time.map(|offset_date_time| {
                    let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
                    PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
                })
            })
        }
    }
    /// Use the well-known ISO 8601 format which is without timezone when serializing and deserializing an
    /// [`Option<PrimitiveDateTime>`][PrimitiveDateTime].
    ///
    /// [PrimitiveDateTime]: ::time::PrimitiveDateTime
    pub mod option_without_timezone {
        use serde::{de, Deserialize, Serialize};
        use time::macros::format_description;

        use super::*;

        /// Serialize an [`Option<PrimitiveDateTime>`] using the well-known ISO 8601 format which is without timezone.
        pub fn serialize<S>(
            date_time: &Option<PrimitiveDateTime>,
            serializer: S,
        ) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            date_time
                .map(|date_time| {
                    let format =
                        format_description!("[year]-[month]-[day]T[hour]:[minute]:[second]");
                    date_time.assume_utc().format(format)
                })
                .transpose()
                .map_err(S::Error::custom)?
                .serialize(serializer)
        }

        /// Deserialize an [`Option<PrimitiveDateTime>`] from its ISO 8601 representation.
        pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<PrimitiveDateTime>, D::Error>
        where
            D: Deserializer<'a>,
        {
            Option::deserialize(deserializer)?
                .map(|time_string| {
                    let format =
                        format_description!("[year]-[month]-[day]T[hour]:[minute]:[second]");
                    PrimitiveDateTime::parse(time_string, format).map_err(|_| {
                        de::Error::custom(format!(
                            "Failed to parse PrimitiveDateTime from {time_string}"
                        ))
                    })
                })
                .transpose()
        }
    }
}

/// Use the UNIX timestamp when serializing and deserializing an
/// [`PrimitiveDateTime`][PrimitiveDateTime].
///
/// [PrimitiveDateTime]: ::time::PrimitiveDateTime
pub mod timestamp {

    use serde::{Deserializer, Serialize, Serializer};
    use time::{serde::timestamp, PrimitiveDateTime, UtcOffset};

    /// Serialize a [`PrimitiveDateTime`] using UNIX timestamp.
    pub fn serialize<S>(date_time: &PrimitiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        date_time
            .assume_utc()
            .unix_timestamp()
            .serialize(serializer)
    }

    /// Deserialize an [`PrimitiveDateTime`] from UNIX timestamp.
    pub fn deserialize<'a, D>(deserializer: D) -> Result<PrimitiveDateTime, D::Error>
    where
        D: Deserializer<'a>,
    {
        timestamp::deserialize(deserializer).map(|offset_date_time| {
            let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
            PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
        })
    }

    /// Use the UNIX timestamp when serializing and deserializing an
    /// [`Option<PrimitiveDateTime>`][PrimitiveDateTime].
    ///
    /// [PrimitiveDateTime]: ::time::PrimitiveDateTime
    pub mod option {
        use serde::Serialize;

        use super::*;

        /// Serialize an [`Option<PrimitiveDateTime>`] from UNIX timestamp.
        pub fn serialize<S>(
            date_time: &Option<PrimitiveDateTime>,
            serializer: S,
        ) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            date_time
                .map(|date_time| date_time.assume_utc().unix_timestamp())
                .serialize(serializer)
        }

        /// Deserialize an [`Option<PrimitiveDateTime>`] from UNIX timestamp.
        pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<PrimitiveDateTime>, D::Error>
        where
            D: Deserializer<'a>,
        {
            timestamp::option::deserialize(deserializer).map(|option_offset_date_time| {
                option_offset_date_time.map(|offset_date_time| {
                    let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
                    PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
                })
            })
        }
    }
}

/// <https://github.com/serde-rs/serde/issues/994#issuecomment-316895860>
pub mod json_string {
    use serde::{
        de::{self, Deserialize, DeserializeOwned, Deserializer},
        ser::{self, Serialize, Serializer},
    };

    /// Serialize a type to json_string format
    pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
    where
        T: Serialize,
        S: Serializer,
    {
        let j = serde_json::to_string(value).map_err(ser::Error::custom)?;
        j.serialize(serializer)
    }

    /// Deserialize a string which is in json format
    pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
    where
        T: DeserializeOwned,
        D: Deserializer<'de>,
    {
        let j = String::deserialize(deserializer)?;
        serde_json::from_str(&j).map_err(de::Error::custom)
    }
}

/// Use a custom ISO 8601 format when serializing and deserializing
/// [`PrimitiveDateTime`][PrimitiveDateTime].
///
/// [PrimitiveDateTime]: ::time::PrimitiveDateTime
pub mod iso8601custom {

    use serde::{ser::Error as _, Deserializer, Serialize, Serializer};
    use time::{
        format_description::well_known::{
            iso8601::{Config, EncodedConfig, TimePrecision},
            Iso8601,
        },
        serde::iso8601,
        PrimitiveDateTime, UtcOffset,
    };

    const FORMAT_CONFIG: EncodedConfig = Config::DEFAULT
        .set_time_precision(TimePrecision::Second {
            decimal_digits: None,
        })
        .encode();

    /// Serialize a [`PrimitiveDateTime`] using the well-known ISO 8601 format.
    pub fn serialize<S>(date_time: &PrimitiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        date_time
            .assume_utc()
            .format(&Iso8601::<FORMAT_CONFIG>)
            .map_err(S::Error::custom)?
            .replace('T', " ")
            .replace('Z', "")
            .serialize(serializer)
    }

    /// Deserialize an [`PrimitiveDateTime`] from its ISO 8601 representation.
    pub fn deserialize<'a, D>(deserializer: D) -> Result<PrimitiveDateTime, D::Error>
    where
        D: Deserializer<'a>,
    {
        iso8601::deserialize(deserializer).map(|offset_date_time| {
            let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
            PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
        })
    }
}

#[cfg(test)]
mod tests {
    use serde::{Deserialize, Serialize};
    use serde_json::json;

    #[test]
    fn test_leap_second_parse() {
        #[derive(Serialize, Deserialize)]
        struct Try {
            #[serde(with = "crate::custom_serde::iso8601")]
            f: time::PrimitiveDateTime,
        }
        let leap_second_date_time = json!({"f": "2023-12-31T23:59:60.000Z"});
        let deser = serde_json::from_value::<Try>(leap_second_date_time);

        assert!(deser.is_ok())
    }
}


Test-Implementation Pair

Implementation: crates/common_utils/src/id_type/global_id.rs
================================================================================
pub(super) mod customer;
pub(super) mod payment;
pub(super) mod payment_methods;
pub(super) mod refunds;
pub(super) mod token;

use diesel::{backend::Backend, deserialize::FromSql, serialize::ToSql, sql_types};
use error_stack::ResultExt;
use thiserror::Error;

use crate::{
    consts::{CELL_IDENTIFIER_LENGTH, MAX_GLOBAL_ID_LENGTH, MIN_GLOBAL_ID_LENGTH},
    errors, generate_time_ordered_id,
    id_type::{AlphaNumericId, AlphaNumericIdError, LengthId, LengthIdError},
};

#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize)]
/// A global id that can be used to identify any entity
/// This id will have information about the entity and cell in a distributed system architecture
pub(crate) struct GlobalId(LengthId<MAX_GLOBAL_ID_LENGTH, MIN_GLOBAL_ID_LENGTH>);

#[derive(Clone, Copy)]
/// Entities that can be identified by a global id
pub(crate) enum GlobalEntity {
    Customer,
    Payment,
    Attempt,
    AttemptGroup,
    PaymentMethod,
    Refund,
    PaymentMethodSession,
    Token,
}

impl GlobalEntity {
    fn prefix(self) -> &'static str {
        match self {
            Self::Customer => "cus",
            Self::Payment => "pay",
            Self::PaymentMethod => "pm",
            Self::Attempt => "att",
            Self::AttemptGroup => "atg",
            Self::Refund => "ref",
            Self::PaymentMethodSession => "pms",
            Self::Token => "tok",
        }
    }
}

/// Cell identifier for an instance / deployment of application
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct CellId(LengthId<CELL_IDENTIFIER_LENGTH, CELL_IDENTIFIER_LENGTH>);

#[derive(Debug, Error, PartialEq, Eq)]
pub enum CellIdError {
    #[error("cell id error: {0}")]
    InvalidCellLength(LengthIdError),

    #[error("{0}")]
    InvalidCellIdFormat(AlphaNumericIdError),
}

impl From<LengthIdError> for CellIdError {
    fn from(error: LengthIdError) -> Self {
        Self::InvalidCellLength(error)
    }
}

impl From<AlphaNumericIdError> for CellIdError {
    fn from(error: AlphaNumericIdError) -> Self {
        Self::InvalidCellIdFormat(error)
    }
}

impl CellId {
    /// Create a new cell id from a string
    fn from_str(cell_id_string: impl AsRef<str>) -> Result<Self, CellIdError> {
        let trimmed_input_string = cell_id_string.as_ref().trim().to_string();
        let alphanumeric_id = AlphaNumericId::from(trimmed_input_string.into())?;
        let length_id = LengthId::from_alphanumeric_id(alphanumeric_id)?;
        Ok(Self(length_id))
    }

    /// Create a new cell id from a string
    pub fn from_string(
        input_string: impl AsRef<str>,
    ) -> error_stack::Result<Self, errors::ValidationError> {
        Self::from_str(input_string).change_context(
            errors::ValidationError::IncorrectValueProvided {
                field_name: "cell_id",
            },
        )
    }

    /// Get the string representation of the cell id
    fn get_string_repr(&self) -> &str {
        &self.0 .0 .0
    }
}

impl<'de> serde::Deserialize<'de> for CellId {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let deserialized_string = String::deserialize(deserializer)?;
        Self::from_str(deserialized_string.as_str()).map_err(serde::de::Error::custom)
    }
}

/// Error generated from violation of constraints for MerchantReferenceId
#[derive(Debug, Error, PartialEq, Eq)]
pub(crate) enum GlobalIdError {
    /// The format for the global id is invalid
    #[error("The id format is invalid, expected format is {{cell_id:5}}_{{entity_prefix:3}}_{{uuid:32}}_{{random:24}}")]
    InvalidIdFormat,

    /// LengthIdError and AlphanumericIdError
    #[error("{0}")]
    LengthIdError(#[from] LengthIdError),

    /// CellIdError because of invalid cell id format
    #[error("{0}")]
    CellIdError(#[from] CellIdError),
}

impl GlobalId {
    /// Create a new global id from entity and cell information
    /// The entity prefix is used to identify the entity, `cus` for customers, `pay`` for payments etc.
    pub fn generate(cell_id: &CellId, entity: GlobalEntity) -> Self {
        let prefix = format!("{}_{}", cell_id.get_string_repr(), entity.prefix());
        let id = generate_time_ordered_id(&prefix);
        let alphanumeric_id = AlphaNumericId::new_unchecked(id);
        Self(LengthId::new_unchecked(alphanumeric_id))
    }

    pub(crate) fn from_string(
        input_string: std::borrow::Cow<'static, str>,
    ) -> Result<Self, GlobalIdError> {
        let length_id = LengthId::from(input_string)?;
        let input_string = &length_id.0 .0;
        let (cell_id, _remaining) = input_string
            .split_once("_")
            .ok_or(GlobalIdError::InvalidIdFormat)?;

        CellId::from_str(cell_id)?;

        Ok(Self(length_id))
    }

    pub(crate) fn get_string_repr(&self) -> &str {
        &self.0 .0 .0
    }
}

impl<DB> ToSql<sql_types::Text, DB> for GlobalId
where
    DB: Backend,
    String: ToSql<sql_types::Text, DB>,
{
    fn to_sql<'b>(
        &'b self,
        out: &mut diesel::serialize::Output<'b, '_, DB>,
    ) -> diesel::serialize::Result {
        self.0 .0 .0.to_sql(out)
    }
}

impl<DB> FromSql<sql_types::Text, DB> for GlobalId
where
    DB: Backend,
    String: FromSql<sql_types::Text, DB>,
{
    fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result<Self> {
        let string_val = String::from_sql(value)?;
        let alphanumeric_id = AlphaNumericId::from(string_val.into())?;
        let length_id = LengthId::from_alphanumeric_id(alphanumeric_id)?;
        Ok(Self(length_id))
    }
}

/// Deserialize the global id from string
/// The format should match {cell_id:5}_{entity_prefix:3}_{time_ordered_id:32}_{.*:24}
impl<'de> serde::Deserialize<'de> for GlobalId {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let deserialized_string = String::deserialize(deserializer)?;
        Self::from_string(deserialized_string.into()).map_err(serde::de::Error::custom)
    }
}

#[cfg(test)]
mod global_id_tests {
    use super::*;

    #[test]
    fn test_cell_id_from_str() {
        let cell_id_string = "12345";
        let cell_id = CellId::from_str(cell_id_string).unwrap();
        assert_eq!(cell_id.get_string_repr(), cell_id_string);
    }

    #[test]
    fn test_global_id_generate() {
        let cell_id_string = "12345";
        let entity = GlobalEntity::Customer;
        let cell_id = CellId::from_str(cell_id_string).unwrap();
        let global_id = GlobalId::generate(&cell_id, entity);

        // Generate a regex for globalid
        // Eg - 12abc_cus_abcdefghijklmnopqrstuvwxyz1234567890
        let regex = regex::Regex::new(r"[a-z0-9]{5}_cus_[a-z0-9]{32}").unwrap();

        assert!(regex.is_match(&global_id.0 .0 .0));
    }

    #[test]
    fn test_global_id_from_string() {
        let input_string = "12345_cus_abcdefghijklmnopqrstuvwxyz1234567890";
        let global_id = GlobalId::from_string(input_string.into()).unwrap();
        assert_eq!(global_id.0 .0 .0, input_string);
    }

    #[test]
    fn test_global_id_deser() {
        let input_string_for_serde_json_conversion =
            r#""12345_cus_abcdefghijklmnopqrstuvwxyz1234567890""#;

        let input_string = "12345_cus_abcdefghijklmnopqrstuvwxyz1234567890";
        let global_id =
            serde_json::from_str::<GlobalId>(input_string_for_serde_json_conversion).unwrap();
        assert_eq!(global_id.0 .0 .0, input_string);
    }

    #[test]
    fn test_global_id_deser_error() {
        let input_string_for_serde_json_conversion =
            r#""123_45_cus_abcdefghijklmnopqrstuvwxyz1234567890""#;

        let global_id = serde_json::from_str::<GlobalId>(input_string_for_serde_json_conversion);
        assert!(global_id.is_err());

        let expected_error_message = format!(
            "cell id error: the minimum required length for this field is {CELL_IDENTIFIER_LENGTH}"
        );

        let error_message = global_id.unwrap_err().to_string();
        assert_eq!(error_message, expected_error_message);
    }
}

Tests: crates/common_utils/src/id_type/global_id.rs
================================================================================
pub(super) mod customer;
pub(super) mod payment;
pub(super) mod payment_methods;
pub(super) mod refunds;
pub(super) mod token;

use diesel::{backend::Backend, deserialize::FromSql, serialize::ToSql, sql_types};
use error_stack::ResultExt;
use thiserror::Error;

use crate::{
    consts::{CELL_IDENTIFIER_LENGTH, MAX_GLOBAL_ID_LENGTH, MIN_GLOBAL_ID_LENGTH},
    errors, generate_time_ordered_id,
    id_type::{AlphaNumericId, AlphaNumericIdError, LengthId, LengthIdError},
};

#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize)]
/// A global id that can be used to identify any entity
/// This id will have information about the entity and cell in a distributed system architecture
pub(crate) struct GlobalId(LengthId<MAX_GLOBAL_ID_LENGTH, MIN_GLOBAL_ID_LENGTH>);

#[derive(Clone, Copy)]
/// Entities that can be identified by a global id
pub(crate) enum GlobalEntity {
    Customer,
    Payment,
    Attempt,
    AttemptGroup,
    PaymentMethod,
    Refund,
    PaymentMethodSession,
    Token,
}

impl GlobalEntity {
    fn prefix(self) -> &'static str {
        match self {
            Self::Customer => "cus",
            Self::Payment => "pay",
            Self::PaymentMethod => "pm",
            Self::Attempt => "att",
            Self::AttemptGroup => "atg",
            Self::Refund => "ref",
            Self::PaymentMethodSession => "pms",
            Self::Token => "tok",
        }
    }
}

/// Cell identifier for an instance / deployment of application
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct CellId(LengthId<CELL_IDENTIFIER_LENGTH, CELL_IDENTIFIER_LENGTH>);

#[derive(Debug, Error, PartialEq, Eq)]
pub enum CellIdError {
    #[error("cell id error: {0}")]
    InvalidCellLength(LengthIdError),

    #[error("{0}")]
    InvalidCellIdFormat(AlphaNumericIdError),
}

impl From<LengthIdError> for CellIdError {
    fn from(error: LengthIdError) -> Self {
        Self::InvalidCellLength(error)
    }
}

impl From<AlphaNumericIdError> for CellIdError {
    fn from(error: AlphaNumericIdError) -> Self {
        Self::InvalidCellIdFormat(error)
    }
}

impl CellId {
    /// Create a new cell id from a string
    fn from_str(cell_id_string: impl AsRef<str>) -> Result<Self, CellIdError> {
        let trimmed_input_string = cell_id_string.as_ref().trim().to_string();
        let alphanumeric_id = AlphaNumericId::from(trimmed_input_string.into())?;
        let length_id = LengthId::from_alphanumeric_id(alphanumeric_id)?;
        Ok(Self(length_id))
    }

    /// Create a new cell id from a string
    pub fn from_string(
        input_string: impl AsRef<str>,
    ) -> error_stack::Result<Self, errors::ValidationError> {
        Self::from_str(input_string).change_context(
            errors::ValidationError::IncorrectValueProvided {
                field_name: "cell_id",
            },
        )
    }

    /// Get the string representation of the cell id
    fn get_string_repr(&self) -> &str {
        &self.0 .0 .0
    }
}

impl<'de> serde::Deserialize<'de> for CellId {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let deserialized_string = String::deserialize(deserializer)?;
        Self::from_str(deserialized_string.as_str()).map_err(serde::de::Error::custom)
    }
}

/// Error generated from violation of constraints for MerchantReferenceId
#[derive(Debug, Error, PartialEq, Eq)]
pub(crate) enum GlobalIdError {
    /// The format for the global id is invalid
    #[error("The id format is invalid, expected format is {{cell_id:5}}_{{entity_prefix:3}}_{{uuid:32}}_{{random:24}}")]
    InvalidIdFormat,

    /// LengthIdError and AlphanumericIdError
    #[error("{0}")]
    LengthIdError(#[from] LengthIdError),

    /// CellIdError because of invalid cell id format
    #[error("{0}")]
    CellIdError(#[from] CellIdError),
}

impl GlobalId {
    /// Create a new global id from entity and cell information
    /// The entity prefix is used to identify the entity, `cus` for customers, `pay`` for payments etc.
    pub fn generate(cell_id: &CellId, entity: GlobalEntity) -> Self {
        let prefix = format!("{}_{}", cell_id.get_string_repr(), entity.prefix());
        let id = generate_time_ordered_id(&prefix);
        let alphanumeric_id = AlphaNumericId::new_unchecked(id);
        Self(LengthId::new_unchecked(alphanumeric_id))
    }

    pub(crate) fn from_string(
        input_string: std::borrow::Cow<'static, str>,
    ) -> Result<Self, GlobalIdError> {
        let length_id = LengthId::from(input_string)?;
        let input_string = &length_id.0 .0;
        let (cell_id, _remaining) = input_string
            .split_once("_")
            .ok_or(GlobalIdError::InvalidIdFormat)?;

        CellId::from_str(cell_id)?;

        Ok(Self(length_id))
    }

    pub(crate) fn get_string_repr(&self) -> &str {
        &self.0 .0 .0
    }
}

impl<DB> ToSql<sql_types::Text, DB> for GlobalId
where
    DB: Backend,
    String: ToSql<sql_types::Text, DB>,
{
    fn to_sql<'b>(
        &'b self,
        out: &mut diesel::serialize::Output<'b, '_, DB>,
    ) -> diesel::serialize::Result {
        self.0 .0 .0.to_sql(out)
    }
}

impl<DB> FromSql<sql_types::Text, DB> for GlobalId
where
    DB: Backend,
    String: FromSql<sql_types::Text, DB>,
{
    fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result<Self> {
        let string_val = String::from_sql(value)?;
        let alphanumeric_id = AlphaNumericId::from(string_val.into())?;
        let length_id = LengthId::from_alphanumeric_id(alphanumeric_id)?;
        Ok(Self(length_id))
    }
}

/// Deserialize the global id from string
/// The format should match {cell_id:5}_{entity_prefix:3}_{time_ordered_id:32}_{.*:24}
impl<'de> serde::Deserialize<'de> for GlobalId {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let deserialized_string = String::deserialize(deserializer)?;
        Self::from_string(deserialized_string.into()).map_err(serde::de::Error::custom)
    }
}

#[cfg(test)]
mod global_id_tests {
    use super::*;

    #[test]
    fn test_cell_id_from_str() {
        let cell_id_string = "12345";
        let cell_id = CellId::from_str(cell_id_string).unwrap();
        assert_eq!(cell_id.get_string_repr(), cell_id_string);
    }

    #[test]
    fn test_global_id_generate() {
        let cell_id_string = "12345";
        let entity = GlobalEntity::Customer;
        let cell_id = CellId::from_str(cell_id_string).unwrap();
        let global_id = GlobalId::generate(&cell_id, entity);

        // Generate a regex for globalid
        // Eg - 12abc_cus_abcdefghijklmnopqrstuvwxyz1234567890
        let regex = regex::Regex::new(r"[a-z0-9]{5}_cus_[a-z0-9]{32}").unwrap();

        assert!(regex.is_match(&global_id.0 .0 .0));
    }

    #[test]
    fn test_global_id_from_string() {
        let input_string = "12345_cus_abcdefghijklmnopqrstuvwxyz1234567890";
        let global_id = GlobalId::from_string(input_string.into()).unwrap();
        assert_eq!(global_id.0 .0 .0, input_string);
    }

    #[test]
    fn test_global_id_deser() {
        let input_string_for_serde_json_conversion =
            r#""12345_cus_abcdefghijklmnopqrstuvwxyz1234567890""#;

        let input_string = "12345_cus_abcdefghijklmnopqrstuvwxyz1234567890";
        let global_id =
            serde_json::from_str::<GlobalId>(input_string_for_serde_json_conversion).unwrap();
        assert_eq!(global_id.0 .0 .0, input_string);
    }

    #[test]
    fn test_global_id_deser_error() {
        let input_string_for_serde_json_conversion =
            r#""123_45_cus_abcdefghijklmnopqrstuvwxyz1234567890""#;

        let global_id = serde_json::from_str::<GlobalId>(input_string_for_serde_json_conversion);
        assert!(global_id.is_err());

        let expected_error_message = format!(
            "cell id error: the minimum required length for this field is {CELL_IDENTIFIER_LENGTH}"
        );

        let error_message = global_id.unwrap_err().to_string();
        assert_eq!(error_message, expected_error_message);
    }
}