pub mod consts;
pub mod v1;
pub use v1::*;
pub mod emu_buxn;
pub mod emu_cuxn;
pub mod emu_uxn;
pub fn percent_decode_or_original(s: &str) -> String {
if !s.as_bytes().contains(&b'%') {
return s.to_string();
}
let mut out = Vec::with_capacity(s.len());
let bytes = s.as_bytes();
let mut i = 0;
while i < bytes.len() {
if bytes[i] == b'%' && i + 2 < bytes.len() {
if let (Some(h), Some(l)) = (hex_val(bytes[i + 1]), hex_val(bytes[i + 2])) {
out.push((h << 4) | l);
i += 3;
continue;
}
out.push(b'%');
i += 1;
} else {
out.push(bytes[i]);
i += 1;
}
}
match std::str::from_utf8(&out) {
Ok(decoded) => decoded.to_string(),
Err(_) => s.to_string(),
}
}
fn hex_val(b: u8) -> Option<u8> {
match b {
b'0'..=b'9' => Some(b - b'0'),
b'a'..=b'f' => Some(b - b'a' + 10),
b'A'..=b'F' => Some(b - b'A' + 10),
_ => None,
}
}