xrpl_common_stdlib/types/
currency.rs1use crate::fields::decoder::{FieldDecoder, FromLedger, decode_exact};
2use crate::types::decode_error::DecodeError;
3
4pub const CURRENCY_SIZE: usize = 20;
5pub const STANDARD_CURRENCY_SIZE: usize = 3; #[derive(Debug, Clone, Copy, PartialEq, Eq)]
19#[repr(C)]
20pub struct Currency(pub [u8; CURRENCY_SIZE]);
21
22impl Currency {
23 pub fn new(code: [u8; CURRENCY_SIZE]) -> Self {
25 Currency(code)
26 }
27
28 pub fn as_bytes(&self) -> &[u8; CURRENCY_SIZE] {
30 &self.0
31 }
32}
33
34impl From<[u8; CURRENCY_SIZE]> for Currency {
35 fn from(value: [u8; CURRENCY_SIZE]) -> Self {
36 Currency(value)
37 }
38}
39
40impl From<[u8; STANDARD_CURRENCY_SIZE]> for Currency {
42 fn from(bytes: [u8; STANDARD_CURRENCY_SIZE]) -> Self {
43 let mut arr = [0u8; CURRENCY_SIZE];
44 arr[12..15].copy_from_slice(&bytes);
45 Self(arr)
46 }
47}
48
49impl FieldDecoder for Currency {
52 type Buffer = [u8; CURRENCY_SIZE];
53
54 #[inline]
55 fn empty_buffer() -> Self::Buffer {
56 [0u8; CURRENCY_SIZE]
57 }
58
59 #[inline]
60 fn decode(buf: Self::Buffer, bytes_written: usize) -> core::result::Result<Self, DecodeError> {
61 decode_exact(buf, bytes_written)
62 }
63}
64
65impl FromLedger for Currency {}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn test_currency_from_standard_bytes() {
73 let standard_bytes = *b"USD";
75 let currency = Currency::from(standard_bytes);
76
77 let mut expected = [0u8; CURRENCY_SIZE];
78 expected[12..15].copy_from_slice(&standard_bytes);
79
80 assert_eq!(currency.as_bytes(), &expected);
81 }
82
83 #[test]
84 fn test_standard_currency_byte_layout() {
85 let eur = Currency::from(*b"EUR");
87 let bytes = eur.as_bytes();
88
89 assert_eq!(&bytes[0..12], &[0u8; 12]);
91 assert_eq!(&bytes[12..15], b"EUR");
93 assert_eq!(&bytes[15..20], &[0u8; 5]);
95 }
96
97 #[test]
98 fn test_currency_new_and_from_20_bytes() {
99 let original: [u8; CURRENCY_SIZE] = [
101 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
102 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
103 ];
104
105 let currency_new = Currency::new(original);
107 assert_eq!(currency_new.as_bytes(), &original);
108
109 let currency_from = Currency::from(original);
111 assert_eq!(currency_from.as_bytes(), &original);
112
113 assert_eq!(currency_new, currency_from);
115 }
116
117 #[test]
118 fn test_currency_equality() {
119 let code1 = Currency::new([3u8; CURRENCY_SIZE]);
121 let code2 = Currency::new([3u8; CURRENCY_SIZE]);
122 assert_eq!(code1, code2);
123
124 let code3 = Currency::new([4u8; CURRENCY_SIZE]);
126 assert_ne!(code1, code3);
127
128 assert_ne!(Currency::from(*b"USD"), Currency::from(*b"EUR"));
130 }
131}