#[cfg(not(feature = "std"))]
use alloc::string::String;
#[cfg(not(feature = "std"))]
use core::{
cmp::{Ordering, PartialOrd},
fmt::{Display, Formatter, Result as FormatterResult},
ops::Deref,
str::FromStr,
};
#[cfg(feature = "std")]
use std::{
cmp::Ordering,
fmt::{Display, Formatter, Result as FormatterResult},
ops::Deref,
str::FromStr,
};
use serde::{de::Deserializer, ser::Serializer, Deserialize, Serialize};
macro_rules! def_id_serde_impls {
($struct_name:ident) => {
impl Serialize for $struct_name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.as_str().serialize(serializer)
}
}
impl<'de> Deserialize<'de> for $struct_name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s: String = Deserialize::deserialize(deserializer)?;
s.parse::<Self>().map_err(::serde::de::Error::custom)
}
}
};
}
macro_rules! def_id {
($struct_name:ident, $prefix:literal) => {
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
pub struct $struct_name(smol_str::SmolStr);
impl $struct_name {
#[inline(always)]
pub fn prefix() -> &'static str {
$prefix
}
#[inline(always)]
pub fn as_str(&self) -> &str {
self.0.as_str()
}
}
impl PartialEq<str> for $struct_name {
fn eq(&self, other: &str) -> bool {
self.as_str() == other
}
}
impl PartialEq<&str> for $struct_name {
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}
impl PartialEq<String> for $struct_name {
fn eq(&self, other: &String) -> bool {
self.as_str() == other
}
}
impl PartialOrd for $struct_name {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for $struct_name {
fn cmp(&self, other: &Self) -> Ordering {
self.as_str().cmp(other.as_str())
}
}
impl AsRef<str> for $struct_name {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl Deref for $struct_name {
type Target = str;
fn deref(&self) -> &str {
self.as_str()
}
}
impl Display for $struct_name {
fn fmt(&self, f: &mut Formatter<'_>) -> FormatterResult {
self.0.fmt(f)
}
}
impl FromStr for $struct_name {
type Err = ParseIdError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if !s.starts_with($prefix) {
Err(ParseIdError {
typename: stringify!($struct_name),
expected: stringify!(id to start with $prefix),
})
} else {
Ok($struct_name(s.into()))
}
}
}
def_id_serde_impls!($struct_name);
};
}
#[derive(Debug, Clone)]
pub struct ParseIdError {
typename: &'static str,
expected: &'static str,
}
impl Display for ParseIdError {
fn fmt(&self, f: &mut Formatter<'_>) -> FormatterResult {
write!(f, "invalid `{}`, expected {}", self.typename, self.expected)
}
}
#[cfg(feature = "std")]
impl std::error::Error for ParseIdError {}
def_id!(CardId, "card_");
def_id!(ItemId, "item_");
def_id!(PlanId, "plan_");
def_id!(AddonId, "ao_");
def_id!(OrderId, "order_");
def_id!(OfferId, "offer_");
def_id!(BatchId, "batch_");
def_id!(RefundId, "rfnd_");
def_id!(AccountId, "acc_");
def_id!(AddressId, "addr_");
def_id!(DisputeId, "disp_");
def_id!(InvoiceId, "inv_");
def_id!(PaymentId, "pay_");
def_id!(CustomerId, "cust_");
def_id!(DowntimeId, "down_");
def_id!(DocumentId, "doc_");
def_id!(TransferId, "trf_");
def_id!(LineItemId, "li_");
def_id!(AdjustmentId, "adj_");
def_id!(SettlementId, "setl_");
def_id!(SubscriptionId, "sub_");
def_id!(InstantSettlementId, "setlod_");
def_id!(InstantSettlementPayoutId, "setlodp_");