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