1use serde::{Deserialize, Deserializer, Serialize};
2
3pub type Result<T> = std::result::Result<T, Error>;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
7pub enum Error {
9 #[error("money amount must contain at least one minor unit")]
10 EmptyAmount,
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
15pub struct MinorUnits(u32);
17
18impl MinorUnits {
19 pub fn try_new(value: u32) -> Result<Self> {
21 if value == 0 {
22 return Err(Error::EmptyAmount);
23 }
24 Ok(Self(value))
25 }
26
27 pub const fn get(self) -> u32 {
29 self.0
30 }
31}
32
33impl<'de> Deserialize<'de> for MinorUnits {
34 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
35 where
36 D: Deserializer<'de>,
37 {
38 Self::try_new(u32::deserialize(deserializer)?).map_err(serde::de::Error::custom)
39 }
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
43pub enum Currency {
45 Usd,
47}
48
49#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
50pub struct Money {
52 minor_units: MinorUnits,
53 currency: Currency,
54}
55
56impl Money {
57 pub const fn new(minor_units: MinorUnits, currency: Currency) -> Self {
59 Self {
60 minor_units,
61 currency,
62 }
63 }
64
65 pub const fn minor_units(&self) -> MinorUnits {
67 self.minor_units
68 }
69
70 pub const fn currency(&self) -> Currency {
72 self.currency
73 }
74}