Skip to main content

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