shape-runtime 0.3.1

Bytecode compiler, builtins, and runtime infrastructure for Shape
Documentation
/// @module std::core::encoding
/// Encoding Utilities
///
/// URL encoding/decoding and other text encoding helpers.
/// For base64 and hex encoding, use the crypto module:
///   crypto.base64_encode(), crypto.base64_decode()
///   crypto.hex_encode(), crypto.hex_decode()

/// URL-encode a string (percent encoding).
///
/// Encodes all characters except unreserved ones (A-Z, a-z, 0-9, -, _, ., ~).
/// Spaces are encoded as %20 (not +).
///
/// @param s - string to encode
/// @returns URL-encoded string
pub fn url_encode(s: string) {
    var result = "";
    for i in range(0, s.len()) {
        let ch = s[i];
        if is_url_unreserved(ch) {
            result = result + ch;
        } else if ch == " " {
            result = result + "%20";
        } else {
            // For ASCII printable chars, encode as %HH
            result = result + "%" + char_to_hex(ch);
        }
    }
    result
}

/// URL-decode a percent-encoded string.
///
/// @param s - URL-encoded string
/// @returns decoded string
pub fn url_decode(s: string) {
    var result = "";
    var i = 0;
    let n = s.len();
    while i < n {
        let ch = s[i];
        if ch == "%" && i + 2 < n {
            let hex_str = s[i + 1] + s[i + 2];
            let decoded = hex_to_char(hex_str);
            result = result + decoded;
            i = i + 3;
        } else if ch == "+" {
            result = result + " ";
            i = i + 1;
        } else {
            result = result + ch;
            i = i + 1;
        }
    }
    result
}

// ===== Helpers =====

function is_url_unreserved(ch) {
    let c = __intrinsic_char_code(ch);
    (c >= 65 && c <= 90) ||
    (c >= 97 && c <= 122) ||
    (c >= 48 && c <= 57) ||
    ch == "-" || ch == "_" || ch == "." || ch == "~"
}

function char_to_hex(ch) {
    let hex_chars = "0123456789ABCDEF";
    // Use char code to get hex representation
    let code = __intrinsic_char_code(ch);
    let hi = code / 16;
    let lo = code % 16;
    hex_chars[floor(hi)] + hex_chars[floor(lo)]
}

function hex_to_char(hex_str) {
    let hi = hex_digit_value(hex_str[0]);
    let lo = hex_digit_value(hex_str[1]);
    __intrinsic_from_char_code(hi * 16 + lo)
}

function hex_digit_value(ch) {
    let c = __intrinsic_char_code(ch);
    if c >= 48 && c <= 57 {
        c - 48
    } else if c >= 65 && c <= 70 {
        c - 65 + 10
    } else if c >= 97 && c <= 102 {
        c - 97 + 10
    } else {
        0
    }
}