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