feat(core): flesh out CardCore + CardKind
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,25 @@
|
||||
//! Card: number, holder, expiry (MonthYear), CVV, PIN, kind.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
use crate::time::MonthYear;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
pub struct CardCore {}
|
||||
pub struct CardCore {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub number: Option<Zeroizing<String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub holder: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub expiry: Option<MonthYear>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub cvv: Option<Zeroizing<String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub pin: Option<Zeroizing<String>>,
|
||||
#[serde(default)]
|
||||
pub kind: CardKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
@@ -13,3 +31,38 @@ pub enum CardKind {
|
||||
Loyalty,
|
||||
Other,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn card_full_round_trip() {
|
||||
let card = CardCore {
|
||||
number: Some(Zeroizing::new("4111111111111111".into())),
|
||||
holder: Some("Alice Doe".into()),
|
||||
expiry: Some(MonthYear::new(12, 2030).unwrap()),
|
||||
cvv: Some(Zeroizing::new("123".into())),
|
||||
pin: Some(Zeroizing::new("0000".into())),
|
||||
kind: CardKind::Credit,
|
||||
};
|
||||
let json = serde_json::to_string(&card).unwrap();
|
||||
let parsed: CardCore = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(parsed.holder.as_deref(), Some("Alice Doe"));
|
||||
assert_eq!(parsed.kind, CardKind::Credit);
|
||||
assert_eq!(parsed.expiry, Some(MonthYear::new(12, 2030).unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn card_kind_default_is_credit() {
|
||||
let json = "{}";
|
||||
let card: CardCore = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(card.kind, CardKind::Credit);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn card_kind_serializes_snake_case() {
|
||||
let json = serde_json::to_string(&CardKind::Loyalty).unwrap();
|
||||
assert_eq!(json, "\"loyalty\"");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user