Add reader and writer compatible functions for encoding and decoding

Signed-off-by: trivernis <trivernis@protonmail.com>
main
trivernis 3 years ago
parent ed51d413b2
commit 5603eb0d4b
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -1,6 +1,6 @@
[package] [package]
name = "uwucodec" name = "uwucodec"
version = "0.1.0" version = "0.1.1"
edition = "2018" edition = "2018"
license = "Apache-2.0" license = "Apache-2.0"
authors = ["trivernis <trivernis@protonmail.com>"] authors = ["trivernis <trivernis@protonmail.com>"]

@ -1,8 +1,9 @@
use std::fs::{read_to_string, write}; use std::fs::OpenOptions;
use std::io; use std::io;
use std::io::{BufReader, BufWriter, Write};
use std::path::PathBuf; use std::path::PathBuf;
use structopt::StructOpt; use structopt::StructOpt;
use uwucodec::decode; use uwucodec::decode_stream;
#[derive(StructOpt, Debug)] #[derive(StructOpt, Debug)]
#[structopt()] #[structopt()]
@ -17,7 +18,14 @@ struct Opt {
} }
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
let opt: Opt = Opt::from_args(); let opt: Opt = Opt::from_args();
let encoded_data = read_to_string(opt.input)?; let input_file = OpenOptions::new().read(true).open(opt.input)?;
let data = decode(&encoded_data); let mut input_reader = BufReader::new(input_file);
write(opt.output, data) let output_file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(opt.output)?;
let mut output_writer = BufWriter::new(output_file);
decode_stream(&mut input_reader, &mut output_writer)?;
output_writer.flush()
} }

@ -1,8 +1,9 @@
use std::fs::{read, write}; use std::fs::OpenOptions;
use std::io; use std::io;
use std::io::{BufReader, BufWriter, Write};
use std::path::PathBuf; use std::path::PathBuf;
use structopt::StructOpt; use structopt::StructOpt;
use uwucodec::encode; use uwucodec::encode_stream;
#[derive(StructOpt, Debug)] #[derive(StructOpt, Debug)]
#[structopt()] #[structopt()]
@ -17,7 +18,14 @@ struct Opt {
} }
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
let opt: Opt = Opt::from_args(); let opt: Opt = Opt::from_args();
let data = read(opt.input)?; let input_file = OpenOptions::new().read(true).open(opt.input)?;
let encoded_data = encode(&data); let mut input_reader = BufReader::new(input_file);
write(opt.output, encoded_data) let output_file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(opt.output)?;
let mut output_writer = BufWriter::new(output_file);
encode_stream(&mut input_reader, &mut output_writer)?;
output_writer.flush()
} }

@ -19,6 +19,7 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::{BufRead, Read, Write};
static VALUE_MAPPINGS: [&str; 16] = [ static VALUE_MAPPINGS: [&str; 16] = [
"uwu", "owo", "umu", "nya", "omo", "o_o", "q_p", "u_u", "o~o", "UwU", "OwO", "UmU", "OmO", "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()); } thread_local! { static WORD_MAP: RefCell<HashMap<&'static str, u8>> = RefCell::new(get_word_map()); }
static SEPARATOR: &str = " "; 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 /// Encodes into the best encoding in existence
pub fn encode<'a, I: IntoIterator<Item = &'a u8> + 'a>(data: I) -> String { pub fn encode<'a, I: IntoIterator<Item = &'a u8> + 'a>(data: I) -> String {
data.into_iter() 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 /// Decodes the best encoding in existence back into bytes
pub fn decode<S: AsRef<str>>(encoded_data: S) -> Vec<u8> { pub fn decode<S: AsRef<str>>(encoded_data: S) -> Vec<u8> {
let mut data = Vec::new(); let mut data = Vec::new();
@ -78,7 +105,8 @@ fn get_word_map() -> HashMap<&'static str, u8> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{decode, encode}; use crate::{decode, decode_stream, encode, encode_stream};
use std::io::Cursor;
#[test] #[test]
fn it_encodes() { fn it_encodes() {
@ -87,6 +115,15 @@ mod tests {
assert_eq!(encoded, String::from("uwu uwu owo uwu uwu OmO")) 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] #[test]
fn it_decodes() { fn it_decodes() {
let encoded_data = String::from("uwu uwu owo uwu uwu OmO"); let encoded_data = String::from("uwu uwu owo uwu uwu OmO");
@ -94,6 +131,14 @@ mod tests {
assert_eq!(decoded, vec![0u8, 16u8, 12u8]) 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] #[test]
fn it_encodes_100000() { fn it_encodes_100000() {
let data = vec![0u8, 16u8, 12u8]; let data = vec![0u8, 16u8, 12u8];

Loading…
Cancel
Save