|
|
|
@ -19,6 +19,7 @@
|
|
|
|
|
|
|
|
|
|
use std::cell::RefCell;
|
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
use std::io::{BufRead, Read, Write};
|
|
|
|
|
|
|
|
|
|
static VALUE_MAPPINGS: [&str; 16] = [
|
|
|
|
|
"uwu", "owo", "umu", "nya", "omo", "o_o", "q_p", "u_u", "o~o", "UwU", "OwO", "UmU", "OmO",
|
|
|
|
@ -27,6 +28,19 @@ static VALUE_MAPPINGS: [&str; 16] = [
|
|
|
|
|
thread_local! { static WORD_MAP: RefCell<HashMap<&'static str, u8>> = RefCell::new(get_word_map()); }
|
|
|
|
|
static SEPARATOR: &str = " ";
|
|
|
|
|
|
|
|
|
|
/// Encodes bytes from a reader to a sink writer
|
|
|
|
|
pub fn encode_stream<R: Read, W: Write>(src: &mut R, sink: &mut W) -> std::io::Result<()> {
|
|
|
|
|
let mut buf = [0u8; 1024];
|
|
|
|
|
while let Ok(num_bytes) = src.read(&mut buf) {
|
|
|
|
|
if num_bytes == 0 {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
sink.write_all(encode(&buf[0..num_bytes]).as_bytes())?;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Encodes into the best encoding in existence
|
|
|
|
|
pub fn encode<'a, I: IntoIterator<Item = &'a u8> + 'a>(data: I) -> String {
|
|
|
|
|
data.into_iter()
|
|
|
|
@ -43,6 +57,19 @@ fn encode_byte(byte: u8) -> [&'static str; 2] {
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Decodes a stream of bytes into the raw data
|
|
|
|
|
pub fn decode_stream<R: BufRead, W: Write>(src: &mut R, sink: &mut W) -> std::io::Result<()> {
|
|
|
|
|
let mut buf = String::new();
|
|
|
|
|
while let Ok(num_bytes) = src.read_line(&mut buf) {
|
|
|
|
|
if num_bytes == 0 {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
sink.write_all(&mut decode(&buf))?;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Decodes the best encoding in existence back into bytes
|
|
|
|
|
pub fn decode<S: AsRef<str>>(encoded_data: S) -> Vec<u8> {
|
|
|
|
|
let mut data = Vec::new();
|
|
|
|
@ -78,7 +105,8 @@ fn get_word_map() -> HashMap<&'static str, u8> {
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use crate::{decode, encode};
|
|
|
|
|
use crate::{decode, decode_stream, encode, encode_stream};
|
|
|
|
|
use std::io::Cursor;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn it_encodes() {
|
|
|
|
@ -87,6 +115,15 @@ mod tests {
|
|
|
|
|
assert_eq!(encoded, String::from("uwu uwu owo uwu uwu OmO"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn it_stream_encodes() {
|
|
|
|
|
let data = vec![0u8, 16u8, 12u8];
|
|
|
|
|
let mut output_buf = Vec::new();
|
|
|
|
|
encode_stream(&mut data.as_slice(), &mut output_buf).unwrap();
|
|
|
|
|
let encoded = String::from_utf8(output_buf).unwrap();
|
|
|
|
|
assert_eq!(encoded, String::from("uwu uwu owo uwu uwu OmO"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn it_decodes() {
|
|
|
|
|
let encoded_data = String::from("uwu uwu owo uwu uwu OmO");
|
|
|
|
@ -94,6 +131,14 @@ mod tests {
|
|
|
|
|
assert_eq!(decoded, vec![0u8, 16u8, 12u8])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn it_stream_decodes() {
|
|
|
|
|
let mut data = Cursor::new(String::from("uwu uwu owo uwu uwu OmO"));
|
|
|
|
|
let mut output_buf = Vec::new();
|
|
|
|
|
decode_stream(&mut data, &mut output_buf).unwrap();
|
|
|
|
|
assert_eq!(output_buf, vec![0u8, 16u8, 12u8])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn it_encodes_100000() {
|
|
|
|
|
let data = vec![0u8, 16u8, 12u8];
|
|
|
|
|