uri-template-core 0.1.0

RFC6570 URI Template library for Rust, with parsing, expansion, compile-time checked macros, and no_std support.
Documentation
pub const fn decode_pct_hex(c0: &char, c1: &char) -> Result<u8, ()> {
    if let Ok(higher) = decode_hex(c0)
        && let Ok(lower) = decode_hex(c1)
    {
        Ok((higher << 4) | lower)
    } else {
        Err(())
    }
}

pub const fn decode_hex(c: &char) -> Result<u8, ()> {
    let byte = match c {
        '0'..='9' => *c as u8 - b'0',
        'a'..='f' => *c as u8 - b'a' + 10,
        'A'..='F' => *c as u8 - b'A' + 10,
        _ => return Err(()),
    };
    Ok(byte)
}

pub const fn decode_digit(c: &char) -> Result<u8, ()> {
    let byte = match c {
        '0'..='9' => *c as u8 - b'0',
        _ => return Err(()),
    };
    Ok(byte)
}

pub const fn pct_encode_byte(byte: &u8) -> [char; 3] {
    const HEX_CHARS: &[u8; 16] = b"0123456789ABCDEF";
    [
        '%',
        HEX_CHARS[(*byte >> 4) as usize] as char,
        HEX_CHARS[(*byte & 0x0F) as usize] as char,
    ]
}

#[inline(always)]
pub fn truncate_str(s: &str, n: usize) -> &str {
    match s.char_indices().nth(n) {
        None => s,
        Some((idx, _)) => &s[0..idx],
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_truncate_str() {
        assert_eq!(truncate_str("Hello, World!", 3), "Hel");
        assert_eq!(truncate_str("Hello, World!", 13), "Hello, World!");
        assert_eq!(truncate_str("Hello, World!", 20), "Hello, World!");
        assert_eq!(truncate_str("你好,世界!", 1), "你");
        assert_eq!(truncate_str("你好,世界!", 2), "你好");
        assert_eq!(truncate_str("你好,世界!", 6), "你好,世界!");
        assert_eq!(truncate_str("你好,世界!", 10), "你好,世界!");
    }
}