1use crate::host::error_codes::match_result_code;
2
3use crate::core::types::account_id::AccountID;
4use crate::core::types::amount::Amount;
5use crate::host;
6use crate::host::Result;
7use core::ptr;
8
9#[derive(Clone, Copy)]
11pub enum DataRepr {
12 AsUTF8 = 0,
14 AsHex = 1,
16}
17
18#[inline(always)] pub fn trace(msg: &str) -> Result<i32> {
30 let null_ptr: *const u8 = ptr::null::<u8>();
31
32 let result_code = unsafe {
33 host::trace(
34 msg.as_ptr(),
35 msg.len(),
36 null_ptr,
37 0usize,
38 DataRepr::AsUTF8 as _,
39 )
40 };
41
42 match_result_code(result_code, || result_code)
43}
44
45#[inline(always)] pub fn trace_data(msg: &str, data: &[u8], data_repr: DataRepr) -> Result<i32> {
57 let result_code = unsafe {
58 let data_ptr = data.as_ptr();
59 let data_len = data.len();
60 host::trace(msg.as_ptr(), msg.len(), data_ptr, data_len, data_repr as _)
61 };
62
63 match_result_code(result_code, || result_code)
64}
65
66#[inline(always)]
78pub fn trace_num(msg: &str, number: i64) -> Result<i32> {
79 let result_code = unsafe { host::trace_num(msg.as_ptr(), msg.len(), number) };
80 match_result_code(result_code, || result_code)
81}
82
83#[inline(always)]
84pub fn trace_account_buf(msg: &str, account_id: &[u8; 20]) -> Result<i32> {
85 let result_code = unsafe {
86 host::trace_account(
87 msg.as_ptr(),
88 msg.len(),
89 account_id.as_ptr(),
90 account_id.len(),
91 )
92 };
93 match_result_code(result_code, || result_code)
94}
95
96#[inline(always)]
97pub fn trace_account(msg: &str, account_id: &AccountID) -> Result<i32> {
98 let result_code = unsafe {
99 host::trace_account(
100 msg.as_ptr(),
101 msg.len(),
102 account_id.0.as_ptr(),
103 account_id.0.len(),
104 )
105 };
106 match_result_code(result_code, || result_code)
107}
108
109#[inline(always)]
110pub fn trace_amount(msg: &str, amount: &Amount) -> Result<i32> {
111 let (amount_bytes, len) = amount.to_stamount_bytes();
113
114 let result_code =
115 unsafe { host::trace_amount(msg.as_ptr(), msg.len(), amount_bytes.as_ptr(), len) };
116
117 match_result_code(result_code, || result_code)
118}
119
120#[inline(always)]
122pub fn trace_float(msg: &str, f: &[u8; 8]) -> Result<i32> {
123 let result_code = unsafe { host::trace_opaque_float(msg.as_ptr(), msg.len(), f.as_ptr(), 8) };
124 match_result_code(result_code, || result_code)
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130 use crate::core::types::amount::Amount;
131
132 #[test]
133 fn test_trace_amount_xrp() {
134 let amount = Amount::XRP {
136 num_drops: 1_000_000,
137 };
138 let message = "Test XRP amount";
139
140 let result = trace_amount(message, &amount);
142
143 assert!(result.is_ok());
145 }
146
147 #[test]
148 fn test_trace_amount_mpt() {
149 use crate::core::types::account_id::AccountID;
151 use crate::core::types::mpt_id::MptId;
152
153 const VALUE: u64 = 500_000;
154 const SEQUENCE_NUM: u32 = 12345;
155 const ISSUER_BYTES: [u8; 20] = [1u8; 20];
156
157 let issuer = AccountID::from(ISSUER_BYTES);
158 let mpt_id = MptId::new(SEQUENCE_NUM, issuer);
159 let amount = Amount::MPT {
160 num_units: VALUE,
161 is_positive: true,
162 mpt_id,
163 };
164
165 let message = "Test MPT amount";
166
167 let result = trace_amount(message, &amount);
169
170 assert!(result.is_ok());
172 }
173
174 #[test]
175 fn test_trace_amount_iou() {
176 use crate::core::types::account_id::AccountID;
178 use crate::core::types::currency::Currency;
179 use crate::core::types::opaque_float::OpaqueFloat;
180
181 let currency_bytes = [2u8; 20];
182 let issuer_bytes = [3u8; 20];
183 let amount_bytes = [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39]; let currency = Currency::from(currency_bytes);
186 let issuer = AccountID::from(issuer_bytes);
187 let amount = OpaqueFloat(amount_bytes);
188
189 let amount = Amount::IOU {
190 amount,
191 issuer,
192 currency,
193 };
194
195 let message = "Test IOU amount";
196
197 let result = trace_amount(message, &amount);
199
200 assert!(result.is_ok());
202 }
203
204 #[test]
205 fn test_trace_amount_negative_xrp() {
206 let amount = Amount::XRP {
208 num_drops: -1_000_000,
209 };
210 let message = "Test negative XRP amount";
211
212 let result = trace_amount(message, &amount);
214
215 assert!(result.is_ok());
217 }
218
219 #[test]
220 fn test_trace_bytes_format() {
221 let xrp_amount = Amount::XRP {
223 num_drops: 1_000_000,
224 };
225 let (_bytes, len) = xrp_amount.to_stamount_bytes();
226 assert_eq!(len, 48); let fee_amount = Amount::XRP { num_drops: 10 };
230 let (bytes, len) = fee_amount.to_stamount_bytes();
231 assert_eq!(len, 48); let expected_bytes = 10u64.to_be_bytes();
236 assert_eq!(&bytes[0..8], &expected_bytes);
237
238 use crate::core::types::account_id::AccountID;
240 use crate::core::types::currency::Currency;
241 use crate::core::types::opaque_float::OpaqueFloat;
242
243 let currency_bytes = [2u8; 20];
244 let issuer_bytes = [3u8; 20];
245 let amount_bytes = [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39];
246
247 let iou_amount = Amount::IOU {
248 amount: OpaqueFloat(amount_bytes),
249 issuer: AccountID::from(issuer_bytes),
250 currency: Currency::from(currency_bytes),
251 };
252 let (bytes, len) = iou_amount.to_stamount_bytes();
253 assert_eq!(len, 48); assert_eq!(&bytes[0..8], &amount_bytes); use crate::core::types::mpt_id::MptId;
258
259 const VALUE: u64 = 500_000;
260 const SEQUENCE_NUM: u32 = 12345;
261 const ISSUER_BYTES: [u8; 20] = [1u8; 20];
262
263 let issuer = AccountID::from(ISSUER_BYTES);
264 let mpt_id = MptId::new(SEQUENCE_NUM, issuer);
265 let mpt_amount = Amount::MPT {
266 num_units: VALUE,
267 is_positive: true,
268 mpt_id,
269 };
270 let (bytes, len) = mpt_amount.to_stamount_bytes();
271 assert_eq!(len, 48); assert_eq!(bytes[0], 0b_0110_0000); assert_eq!(&bytes[1..9], &VALUE.to_be_bytes()); }
275}