xrpl_common_stdlib/types/
mpt_id.rs1use crate::types::account_id::AccountID;
2
3pub const MPT_ID_SIZE: usize = 24;
4pub const MPT_SEQUENCE_NUM_SIZE: usize = 4;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18#[repr(C)]
19pub struct MptId([u8; MPT_ID_SIZE]);
20
21impl MptId {
22 pub fn new(sequence_num: u32, issuer: AccountID) -> Self {
24 let mut bytes = [0u8; MPT_ID_SIZE];
25
26 bytes[0..4].copy_from_slice(&sequence_num.to_be_bytes());
28
29 bytes[4..MPT_ID_SIZE].copy_from_slice(&issuer.0);
31
32 MptId(bytes)
33 }
34
35 pub fn get_sequence_num(&self) -> u32 {
37 u32::from_be_bytes([self.0[0], self.0[1], self.0[2], self.0[3]])
39 }
40
41 pub fn get_issuer(&self) -> AccountID {
43 let mut account_bytes = [0u8; 20]; account_bytes.copy_from_slice(&self.0[4..24]); AccountID::from(account_bytes)
47 }
48
49 pub fn as_bytes(&self) -> &[u8; 24] {
51 &self.0
52 }
53
54 pub fn as_ptr(&self) -> *const u8 {
55 self.0.as_ptr()
56 }
57
58 pub fn len(&self) -> usize {
59 self.0.len()
60 }
61
62 pub fn is_empty(&self) -> bool {
63 self.0.iter().all(|&byte| byte == 0)
64 }
65}
66
67impl From<[u8; 24]> for MptId {
68 fn from(value: [u8; 24]) -> Self {
69 MptId(value)
70 }
71}
72
73impl From<(u32, AccountID)> for MptId {
74 fn from(value: (u32, AccountID)) -> Self {
75 MptId::new(value.0, value.1)
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn test_mpt_id_creation() {
85 let account_bytes = [1u8; 20];
87 let account_id = AccountID::from(account_bytes);
88
89 let sequence_num = 12345u32;
91 let mpt_id = MptId::new(sequence_num, account_id);
92
93 assert_eq!(mpt_id.get_sequence_num(), sequence_num);
95 assert_eq!(mpt_id.get_issuer(), account_id);
96 }
97
98 #[test]
99 fn test_mpt_id_byte_layout() {
100 let sequence_num = 0x12345678u32;
102 let account_id = AccountID::from([0xAA; 20]);
103 let mpt_id = MptId::new(sequence_num, account_id);
104
105 let bytes = mpt_id.as_bytes();
106 assert_eq!(&bytes[0..4], &[0x12, 0x34, 0x56, 0x78]);
108 assert_eq!(&bytes[4..24], &[0xAA; 20]);
110 }
111
112 #[test]
113 fn test_mpt_id_from_bytes() {
114 let mut bytes = [0u8; 24];
116 bytes[0..4].copy_from_slice(&67890u32.to_be_bytes());
118 for byte in bytes.iter_mut().skip(4).take(20) {
120 *byte = 2;
121 }
122
123 let mpt_id = MptId::from(bytes);
125
126 assert_eq!(mpt_id.get_sequence_num(), 67890u32);
128 assert_eq!(mpt_id.get_issuer(), AccountID::from([2u8; 20]));
129 }
130
131 #[test]
132 fn test_mpt_id_as_bytes_and_len() {
133 let issuer = AccountID::from([0xAA; 20]);
134 let mpt_id = MptId::new(42, issuer);
135
136 assert_eq!(mpt_id.len(), 24);
137 assert_eq!(&mpt_id.as_bytes()[0..4], &42u32.to_be_bytes());
138 assert_eq!(&mpt_id.as_bytes()[4..], &[0xAA; 20]);
139
140 let ptr_slice = unsafe { core::slice::from_raw_parts(mpt_id.as_ptr(), mpt_id.len()) };
141 assert_eq!(ptr_slice, mpt_id.as_bytes());
142 }
143
144 #[test]
145 fn test_mpt_id_is_empty() {
146 let empty = MptId::from([0u8; 24]);
147 assert!(empty.is_empty());
148
149 let non_empty = MptId::new(1, AccountID::from([0u8; 20]));
150 assert!(!non_empty.is_empty());
151 }
152
153 #[test]
154 fn test_mpt_id_from_tuple() {
155 let account_bytes = [3u8; 20];
157 let account_id = AccountID::from(account_bytes);
158
159 let sequence_num = 54321u32;
161 let mpt_id = MptId::from((sequence_num, account_id));
162
163 assert_eq!(mpt_id.get_sequence_num(), sequence_num);
165 assert_eq!(mpt_id.get_issuer(), account_id);
166 }
167
168 #[test]
169 fn test_mpt_id_is_empty_when_all_zeros() {
170 let mpt_id = MptId::from([0u8; 24]);
171 assert!(mpt_id.is_empty());
172 }
173
174 #[test]
175 fn test_mpt_id_is_not_empty_when_has_data() {
176 let mut bytes = [0u8; 24];
178 bytes[0] = 1; let mpt_id = MptId::from(bytes);
180 assert!(!mpt_id.is_empty());
181
182 let mut bytes2 = [0u8; 24];
184 bytes2[10] = 0xFF; let mpt_id2 = MptId::from(bytes2);
186 assert!(!mpt_id2.is_empty());
187 }
188
189 #[test]
190 fn test_mpt_id_sequence_num_zero() {
191 let account_id = AccountID::from([0xBB; 20]);
193 let mpt_id = MptId::new(0, account_id);
194
195 assert_eq!(mpt_id.get_sequence_num(), 0);
196 assert_eq!(&mpt_id.as_bytes()[0..4], &[0, 0, 0, 0]);
197 }
198
199 #[test]
200 fn test_mpt_id_sequence_num_max() {
201 let account_id = AccountID::from([0xCC; 20]);
203 let mpt_id = MptId::new(u32::MAX, account_id);
204
205 assert_eq!(mpt_id.get_sequence_num(), u32::MAX);
206 assert_eq!(&mpt_id.as_bytes()[0..4], &[0xFF, 0xFF, 0xFF, 0xFF]);
207 }
208}