rusty_common/auth/exchanges/
mod.rs

1//! Exchange-specific authentication implementations
2
3pub mod binance;
4pub mod bithumb;
5pub mod bybit;
6/// Coinbase authentication implementation.
7pub mod coinbase;
8pub mod upbit;
9
10use crate::{Result, SmartString};
11use smallvec::SmallVec;
12
13/// URL-encode the provided parameter string using a pre-allocated buffer.
14///
15/// This performs zero-copy encoding to avoid unpredictable heap
16/// allocations on critical paths. Pure function for maximum performance.
17pub fn url_encode_params(params: &str, buffer: &mut SmartString) -> Result<()> {
18    buffer.clear();
19    const HEX: &[u8; 16] = b"0123456789ABCDEF";
20    for &byte in params.as_bytes() {
21        match byte {
22            b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => {
23                buffer.push(byte as char)
24            }
25            _ => {
26                buffer.push('%');
27                buffer.push(HEX[(byte >> 4) as usize] as char);
28                buffer.push(HEX[(byte & 0x0F) as usize] as char);
29            }
30        }
31    }
32    Ok(())
33}
34
35/// Build a query SmartString from key-value pairs (maintaining natural order)
36/// Optimized with SmallVec for stack allocation and minimal heap allocations
37/// Note: No sorting required - exchanges use natural parameter order for signatures
38///
39/// Performance improvement: Removed O(n log n) sorting, now O(n)
40pub fn build_query_smartstring(params: &[(&str, &str)]) -> SmartString {
41    if params.is_empty() {
42        return SmartString::new();
43    }
44
45    // Build parameter strings using SmallVec for stack allocation
46    let mut param_strings: SmallVec<[SmartString; 8]> = SmallVec::with_capacity(params.len());
47
48    for (key, value) in params.iter() {
49        let param = crate::safe_format!("{key}={value}");
50        param_strings.push(param);
51    }
52
53    // Join using iterator to minimize allocations
54    SmartString::from(
55        param_strings
56            .iter()
57            .map(|s| s.as_str())
58            .collect::<SmallVec<[&str; 8]>>()
59            .join("&"),
60    )
61}