odos_sdk/types/
referral.rs

1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5/// Type-safe referral code
6///
7/// Provides a clear, type-safe wrapper around referral codes with
8/// convenient constants for common values.
9///
10/// # Examples
11///
12/// ```rust
13/// use odos_sdk::ReferralCode;
14///
15/// // No referral code
16/// let code = ReferralCode::NONE;
17/// assert_eq!(code.code(), 0);
18///
19/// // Custom referral code
20/// let code = ReferralCode::new(42);
21/// assert_eq!(code.code(), 42);
22/// ```
23#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
24#[serde(transparent)]
25pub struct ReferralCode(u32);
26
27impl ReferralCode {
28    /// No referral code (value: 0)
29    ///
30    /// This is the most common case - no referral program participation.
31    ///
32    /// # Examples
33    ///
34    /// ```rust
35    /// use odos_sdk::ReferralCode;
36    ///
37    /// let code = ReferralCode::NONE;
38    /// assert_eq!(code.code(), 0);
39    /// ```
40    pub const NONE: Self = Self(0);
41
42    /// Create a new referral code
43    ///
44    /// # Arguments
45    ///
46    /// * `code` - The referral code value
47    ///
48    /// # Examples
49    ///
50    /// ```rust
51    /// use odos_sdk::ReferralCode;
52    ///
53    /// let code = ReferralCode::new(42);
54    /// assert_eq!(code.code(), 42);
55    ///
56    /// let code = ReferralCode::new(1234);
57    /// assert_eq!(code.code(), 1234);
58    /// ```
59    pub const fn new(code: u32) -> Self {
60        Self(code)
61    }
62
63    /// Get the referral code value
64    ///
65    /// # Examples
66    ///
67    /// ```rust
68    /// use odos_sdk::ReferralCode;
69    ///
70    /// let code = ReferralCode::new(42);
71    /// assert_eq!(code.code(), 42);
72    /// ```
73    pub const fn code(&self) -> u32 {
74        self.0
75    }
76
77    /// Check if this is the NONE referral code
78    ///
79    /// # Examples
80    ///
81    /// ```rust
82    /// use odos_sdk::ReferralCode;
83    ///
84    /// assert!(ReferralCode::NONE.is_none());
85    /// assert!(!ReferralCode::new(42).is_none());
86    /// ```
87    pub const fn is_none(&self) -> bool {
88        self.0 == 0
89    }
90
91    /// Check if this is a valid referral code (non-zero)
92    ///
93    /// # Examples
94    ///
95    /// ```rust
96    /// use odos_sdk::ReferralCode;
97    ///
98    /// assert!(!ReferralCode::NONE.is_some());
99    /// assert!(ReferralCode::new(42).is_some());
100    /// ```
101    pub const fn is_some(&self) -> bool {
102        self.0 != 0
103    }
104}
105
106impl Default for ReferralCode {
107    /// Default referral code is NONE (0)
108    fn default() -> Self {
109        Self::NONE
110    }
111}
112
113impl fmt::Display for ReferralCode {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        if self.is_none() {
116            write!(f, "None")
117        } else {
118            write!(f, "{}", self.0)
119        }
120    }
121}
122
123impl From<ReferralCode> for u32 {
124    fn from(code: ReferralCode) -> Self {
125        code.0
126    }
127}
128
129impl From<u32> for ReferralCode {
130    fn from(code: u32) -> Self {
131        Self(code)
132    }
133}
134
135#[cfg(test)]
136mod tests {
137    use super::*;
138
139    #[test]
140    fn test_none_constant() {
141        assert_eq!(ReferralCode::NONE.code(), 0);
142        assert!(ReferralCode::NONE.is_none());
143        assert!(!ReferralCode::NONE.is_some());
144    }
145
146    #[test]
147    fn test_new() {
148        let code = ReferralCode::new(42);
149        assert_eq!(code.code(), 42);
150        assert!(!code.is_none());
151        assert!(code.is_some());
152
153        let code = ReferralCode::new(0);
154        assert_eq!(code.code(), 0);
155        assert!(code.is_none());
156        assert!(!code.is_some());
157
158        let code = ReferralCode::new(u32::MAX);
159        assert_eq!(code.code(), u32::MAX);
160        assert!(code.is_some());
161    }
162
163    #[test]
164    fn test_default() {
165        let code = ReferralCode::default();
166        assert_eq!(code, ReferralCode::NONE);
167        assert_eq!(code.code(), 0);
168    }
169
170    #[test]
171    fn test_display() {
172        assert_eq!(format!("{}", ReferralCode::NONE), "None");
173        assert_eq!(format!("{}", ReferralCode::new(42)), "42");
174        assert_eq!(format!("{}", ReferralCode::new(1234)), "1234");
175    }
176
177    #[test]
178    fn test_conversions() {
179        // From ReferralCode to u32
180        let code = ReferralCode::new(42);
181        let value: u32 = code.into();
182        assert_eq!(value, 42);
183
184        // From u32 to ReferralCode
185        let code: ReferralCode = 42u32.into();
186        assert_eq!(code.code(), 42);
187    }
188
189    #[test]
190    fn test_equality() {
191        assert_eq!(ReferralCode::new(42), ReferralCode::new(42));
192        assert_ne!(ReferralCode::new(42), ReferralCode::new(43));
193        assert_eq!(ReferralCode::NONE, ReferralCode::new(0));
194    }
195
196    #[test]
197    fn test_ordering() {
198        assert!(ReferralCode::new(1) < ReferralCode::new(2));
199        assert!(ReferralCode::new(100) > ReferralCode::new(50));
200        assert!(ReferralCode::NONE < ReferralCode::new(1));
201    }
202
203    #[test]
204    fn test_serialization() {
205        let code = ReferralCode::new(42);
206
207        // Serialize
208        let json = serde_json::to_string(&code).unwrap();
209        assert_eq!(json, "42");
210
211        // Deserialize
212        let deserialized: ReferralCode = serde_json::from_str(&json).unwrap();
213        assert_eq!(deserialized.code(), 42);
214
215        // Serialize NONE
216        let json = serde_json::to_string(&ReferralCode::NONE).unwrap();
217        assert_eq!(json, "0");
218    }
219}