xrpl_wasm_stdlib/
lib.rs

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