payrail_core/
reference.rs1use crate::PaymentError;
2
3macro_rules! string_newtype {
4 ($name:ident, $error:ident, $doc:literal) => {
5 #[doc = $doc]
6 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
7 pub struct $name(String);
8
9 impl $name {
10 pub fn new(value: impl AsRef<str>) -> Result<Self, PaymentError> {
16 let value = value.as_ref().trim();
17 if value.is_empty() || value.len() > 255 {
18 return Err(PaymentError::$error(value.to_owned()));
19 }
20
21 Ok(Self(value.to_owned()))
22 }
23
24 #[inline]
26 #[must_use]
27 pub fn as_str(&self) -> &str {
28 &self.0
29 }
30
31 #[inline]
33 #[must_use]
34 pub fn into_string(self) -> String {
35 self.0
36 }
37 }
38
39 impl AsRef<str> for $name {
40 #[inline]
41 fn as_ref(&self) -> &str {
42 self.as_str()
43 }
44 }
45 };
46}
47
48string_newtype!(MerchantReference, InvalidReference, "Merchant reference.");
49string_newtype!(ProviderReference, InvalidReference, "Provider reference.");
50string_newtype!(PaymentId, InvalidReference, "PayRail payment identifier.");
51string_newtype!(
52 WebhookEventId,
53 InvalidReference,
54 "Webhook event identifier."
55);
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn new_accepts_reference() {
63 let reference = MerchantReference::new("ORDER-123").expect("reference should be valid");
64
65 assert_eq!(reference.as_str(), "ORDER-123");
66 assert_eq!(reference.into_string(), "ORDER-123");
67 }
68
69 #[test]
70 fn new_rejects_empty_reference() {
71 assert!(matches!(
72 ProviderReference::new(" "),
73 Err(PaymentError::InvalidReference(_))
74 ));
75 }
76}