1use crate::host;
2use crate::types::account_id::AccountID;
3use crate::types::amount::Amount;
4
5#[derive(Clone, Copy)]
8#[repr(i32)]
9pub enum TraceDataType {
10 Int64 = 1,
12 Uint64 = 2,
14 Xfloat = 3,
16 Account = 4,
18 Amount = 5,
20 AsHex = 6,
22 AsText = 7,
24}
25
26#[inline(always)]
29fn trace_impl(msg: &str, data_type: TraceDataType, data: &[u8]) {
30 unsafe {
31 host::trace(
32 msg.as_ptr(),
33 msg.len(),
34 data_type as i32,
35 data.as_ptr(),
36 data.len(),
37 )
38 }
39}
40
41#[inline(always)] pub fn trace(msg: &str) {
47 trace_impl(msg, TraceDataType::AsText, &[]);
48}
49
50#[inline(always)] pub fn trace_hex(msg: &str, data: &[u8]) {
57 trace_impl(msg, TraceDataType::AsHex, data);
58}
59
60#[inline(always)] pub fn trace_text(msg: &str, data: &[u8]) {
67 trace_impl(msg, TraceDataType::AsText, data);
68}
69
70#[inline(always)]
76pub fn trace_num(msg: &str, number: i64) {
77 trace_impl(msg, TraceDataType::Int64, &number.to_le_bytes());
78}
79
80#[inline(always)]
87pub fn trace_num_unsigned(msg: &str, number: u64) {
88 trace_impl(msg, TraceDataType::Uint64, &number.to_le_bytes());
89}
90
91#[inline(always)]
92pub fn trace_acct_buf(msg: &str, account_id: &[u8; 20]) {
93 trace_impl(msg, TraceDataType::Account, account_id);
94}
95
96#[inline(always)]
97pub fn trace_acct(msg: &str, account_id: &AccountID) {
98 trace_impl(msg, TraceDataType::Account, &account_id.0);
99}
100
101#[inline(always)]
102pub fn trace_amt(msg: &str, amount: &Amount) {
103 let (amount_bytes, len) = amount.to_stamount_bytes();
104
105 trace_impl(msg, TraceDataType::Amount, &amount_bytes[..len]);
106}
107
108#[inline(always)]
110pub fn trace_float(msg: &str, f: &[u8; 8]) {
111 trace_impl(msg, TraceDataType::Xfloat, f);
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117 use crate::host::host_bindings_trait::MockHostBindings;
118 use crate::host::setup_mock;
119 use crate::types::amount::Amount;
120
121 #[test]
122 fn test_trace_amt_xrp() {
123 let mut mock = MockHostBindings::new();
124
125 let message = "Test XRP amount";
126
127 mock.expect_trace()
128 .withf(|_, _, data_type, _, _| *data_type == TraceDataType::Amount as i32)
129 .times(1)
130 .returning(|_, _, _, _, _| ());
131
132 let _guard = setup_mock(mock);
133
134 let amount = Amount::XRP {
136 num_drops: 1_000_000,
137 };
138
139 trace_amt(message, &amount);
140 }
141
142 #[test]
143 fn test_trace_amt_mpt() {
144 let mut mock = MockHostBindings::new();
145
146 let message = "Test MPT amount";
147
148 mock.expect_trace()
149 .withf(|_, _, data_type, _, _| *data_type == TraceDataType::Amount as i32)
150 .times(1)
151 .returning(|_, _, _, _, _| ());
152
153 let _guard = setup_mock(mock);
154
155 use crate::types::account_id::AccountID;
157 use crate::types::mpt_id::MptId;
158
159 const VALUE: u64 = 500_000;
160 const SEQUENCE_NUM: u32 = 12345;
161 const ISSUER_BYTES: [u8; 20] = [1u8; 20];
162
163 let issuer = AccountID::from(ISSUER_BYTES);
164 let mpt_id = MptId::new(SEQUENCE_NUM, issuer);
165 let amount = Amount::MPT {
166 num_units: VALUE,
167 is_positive: true,
168 mpt_id,
169 };
170
171 trace_amt(message, &amount);
172 }
173
174 #[test]
175 fn test_trace_amt_iou() {
176 let mut mock = MockHostBindings::new();
177
178 let message = "Test IOU amount";
179
180 mock.expect_trace()
181 .withf(|_, _, data_type, _, _| *data_type == TraceDataType::Amount as i32)
182 .times(1)
183 .returning(|_, _, _, _, _| ());
184
185 let _guard = setup_mock(mock);
186
187 use crate::types::account_id::AccountID;
189 use crate::types::currency::Currency;
190 use crate::types::iou_number::IOUNumber;
191
192 let currency_bytes = [2u8; 20];
193 let issuer_bytes = [3u8; 20];
194 let amount_bytes = [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39]; let currency = Currency::from(currency_bytes);
197 let issuer = AccountID::from(issuer_bytes);
198 let amount = IOUNumber(amount_bytes);
199
200 let amount = Amount::IOU {
201 amount,
202 issuer,
203 currency,
204 };
205
206 trace_amt(message, &amount);
207 }
208
209 #[test]
210 fn test_trace_amt_negative_xrp() {
211 let mut mock = MockHostBindings::new();
212
213 let message = "Test negative XRP amount";
214
215 mock.expect_trace()
216 .withf(|_, _, data_type, _, _| *data_type == TraceDataType::Amount as i32)
217 .times(1)
218 .returning(|_, _, _, _, _| ());
219
220 let _guard = setup_mock(mock);
221
222 let amount = Amount::XRP {
224 num_drops: -1_000_000,
225 };
226
227 trace_amt(message, &amount);
228 }
229
230 #[test]
231 fn test_trace_bytes_format() {
232 let xrp_amount = Amount::XRP {
234 num_drops: 1_000_000,
235 };
236 let (_bytes, len) = xrp_amount.to_stamount_bytes();
237 assert_eq!(len, 48); let fee_amount = Amount::XRP { num_drops: 10 };
241 let (bytes, len) = fee_amount.to_stamount_bytes();
242 assert_eq!(len, 48); let expected_bytes = [64, 0, 0, 0, 0, 0, 0, 10];
247 assert_eq!(&bytes[0..8], &expected_bytes);
248
249 use crate::types::account_id::AccountID;
251 use crate::types::currency::Currency;
252 use crate::types::iou_number::IOUNumber;
253
254 let currency_bytes = [2u8; 20];
255 let issuer_bytes = [3u8; 20];
256 let amount_bytes = [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39];
257
258 let iou_amount = Amount::IOU {
259 amount: IOUNumber(amount_bytes),
260 issuer: AccountID::from(issuer_bytes),
261 currency: Currency::from(currency_bytes),
262 };
263 let (bytes, len) = iou_amount.to_stamount_bytes();
264 assert_eq!(len, 48); assert_eq!(&bytes[0..8], &amount_bytes); use crate::types::mpt_id::MptId;
269
270 const VALUE: u64 = 500_000;
271 const SEQUENCE_NUM: u32 = 12345;
272 const ISSUER_BYTES: [u8; 20] = [1u8; 20];
273
274 let issuer = AccountID::from(ISSUER_BYTES);
275 let mpt_id = MptId::new(SEQUENCE_NUM, issuer);
276 let mpt_amount = Amount::MPT {
277 num_units: VALUE,
278 is_positive: true,
279 mpt_id,
280 };
281 let (bytes, len) = mpt_amount.to_stamount_bytes();
282 assert_eq!(len, 48); assert_eq!(bytes[0], 0b_0110_0000); assert_eq!(&bytes[1..9], &VALUE.to_be_bytes()); }
286}