Skip to main content

xrpl_common_stdlib/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(target_arch = "wasm32", no_std)]
3
4#[cfg(not(target_arch = "wasm32"))]
5extern crate std;
6
7// Re-export macros for convenient access
8pub use xrpl_macros::blob;
9pub use xrpl_macros::currency;
10pub use xrpl_macros::hash256;
11pub use xrpl_macros::pubkey;
12pub use xrpl_macros::r_address;
13pub use xrpl_macros::smart_contract;
14pub use xrpl_macros::smart_escrow;
15pub mod crypto;
16pub mod ctx;
17pub mod current_tx;
18pub mod fields;
19pub mod host;
20pub mod ledger_entry_ids;
21pub mod objects;
22pub mod sfield;
23pub(crate) mod tx_flags;
24pub mod types;
25
26/// Complete Developer Guide
27///
28/// This comprehensive guide covers everything you need to develop smart escrows using
29/// the XRPL WebAssembly Standard Library, from getting started to advanced development.
30///
31/// All internal links work properly within this single documentation page.
32#[cfg(doc)]
33#[doc = include_str!("../docs/comprehensive-guide.md")]
34pub mod guide {}
35
36/// This function is called on panic but only in the WASM architecture. In non-WASM (e.g., in the
37/// Host Simulator) the standard lib is available, which includes a panic handler.
38#[cfg(target_arch = "wasm32")]
39#[panic_handler]
40fn panic(_info: &::core::panic::PanicInfo) -> ! {
41    // This instruction will halt execution of the WASM module.
42    // It's the WASM equivalent of a trap or an unrecoverable error.
43    ::core::arch::wasm32::unreachable();
44}
45
46#[inline(always)]
47fn hex_char_to_nibble(c: u8) -> Option<u8> {
48    // WASM-optimized hex decoding with branch conditions for better performance
49    #[cfg(target_arch = "wasm32")]
50    {
51        // Use branchless computation optimized for WASM
52        if c >= b'0' && c <= b'9' {
53            Some(c - b'0')
54        } else if c >= b'a' && c <= b'f' {
55            Some(c - b'a' + 10)
56        } else if c >= b'A' && c <= b'F' {
57            Some(c - b'A' + 10)
58        } else {
59            None
60        }
61    }
62    #[cfg(not(target_arch = "wasm32"))]
63    {
64        // Use pattern matching for non-WASM targets; this is more idiomatic and may have different compiler
65        // optimization characteristics but is functionally equivalent to the WASM branch.
66        match c {
67            b'0'..=b'9' => Some(c - b'0'),
68            b'a'..=b'f' => Some(c - b'a' + 10),
69            b'A'..=b'F' => Some(c - b'A' + 10),
70            _ => None,
71        }
72    }
73}
74
75/// Decode a 64-hex-character string into a 32-byte array.
76///
77/// The input must be exactly 64 hexadecimal ASCII bytes (lower- or upper-case).
78/// Returns `None` if any character is not a valid hex digit.
79///
80/// Example:
81/// ```
82/// # use xrpl_common_stdlib::decode_hex_32;
83/// let hex = *b"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
84/// let bytes = decode_hex_32(&hex).unwrap();
85/// assert_eq!(bytes.len(), 32);
86/// ```
87#[inline(always)]
88pub fn decode_hex_32(hex: &[u8; 64]) -> Option<[u8; 32]> {
89    let mut out = [0u8; 32];
90
91    // Unrolled loop for better WASM performance - eliminates loop counter overhead
92    macro_rules! decode_byte {
93        ($i:expr) => {{
94            let high = hex_char_to_nibble(hex[$i * 2])?;
95            let low = hex_char_to_nibble(hex[$i * 2 + 1])?;
96            out[$i] = (high << 4) | low;
97        }};
98    }
99
100    decode_byte!(0);
101    decode_byte!(1);
102    decode_byte!(2);
103    decode_byte!(3);
104    decode_byte!(4);
105    decode_byte!(5);
106    decode_byte!(6);
107    decode_byte!(7);
108    decode_byte!(8);
109    decode_byte!(9);
110    decode_byte!(10);
111    decode_byte!(11);
112    decode_byte!(12);
113    decode_byte!(13);
114    decode_byte!(14);
115    decode_byte!(15);
116    decode_byte!(16);
117    decode_byte!(17);
118    decode_byte!(18);
119    decode_byte!(19);
120    decode_byte!(20);
121    decode_byte!(21);
122    decode_byte!(22);
123    decode_byte!(23);
124    decode_byte!(24);
125    decode_byte!(25);
126    decode_byte!(26);
127    decode_byte!(27);
128    decode_byte!(28);
129    decode_byte!(29);
130    decode_byte!(30);
131    decode_byte!(31);
132
133    Some(out)
134}
135
136/// Decode a 40-hex-character string into a 20-byte array.
137///
138/// The input must be exactly 40 hexadecimal ASCII bytes.
139/// Returns `None` if any character is not a valid hex digit.
140///
141/// Example:
142/// ```
143/// # use xrpl_common_stdlib::decode_hex_20;
144/// let hex = *b"00112233445566778899aabbccddeeff00112233";
145/// let bytes = decode_hex_20(&hex).unwrap();
146/// assert_eq!(bytes.len(), 20);
147/// ```
148#[inline(always)]
149pub fn decode_hex_20(hex: &[u8; 40]) -> Option<[u8; 20]> {
150    let mut out = [0u8; 20];
151
152    // Unrolled loop for better WASM performance - eliminates loop counter overhead
153    macro_rules! decode_byte {
154        ($i:expr) => {{
155            let high = hex_char_to_nibble(hex[$i * 2])?;
156            let low = hex_char_to_nibble(hex[$i * 2 + 1])?;
157            out[$i] = (high << 4) | low;
158        }};
159    }
160
161    decode_byte!(0);
162    decode_byte!(1);
163    decode_byte!(2);
164    decode_byte!(3);
165    decode_byte!(4);
166    decode_byte!(5);
167    decode_byte!(6);
168    decode_byte!(7);
169    decode_byte!(8);
170    decode_byte!(9);
171    decode_byte!(10);
172    decode_byte!(11);
173    decode_byte!(12);
174    decode_byte!(13);
175    decode_byte!(14);
176    decode_byte!(15);
177    decode_byte!(16);
178    decode_byte!(17);
179    decode_byte!(18);
180    decode_byte!(19);
181
182    Some(out)
183}