diff --git a/src/uucore/Cargo.toml b/src/uucore/Cargo.toml index 37f16289c..98b8282dd 100644 --- a/src/uucore/Cargo.toml +++ b/src/uucore/Cargo.toml @@ -5,8 +5,10 @@ authors = [] [dependencies] getopts = "0.2.14" +failure = { version = "0.1.1", optional = true } +failure_derive = { version = "0.1.1", optional = true } time = { version = "0.1.38", optional = true } -data-encoding = { version = "^1.1", optional = true } +data-encoding = { version = "^2.1", optional = true } libc = { version = "0.2.34", optional = true } [target.'cfg(target_os = "redox")'.dependencies] @@ -15,7 +17,7 @@ termion = "1.5" [features] fs = ["libc"] utf8 = [] -encoding = ["data-encoding"] +encoding = ["data-encoding", "failure", "failure_derive"] parse_time = [] mode = ["libc"] utmpx = ["time", "libc"] diff --git a/src/uucore/encoding.rs b/src/uucore/encoding.rs index f2ff75dd2..0bc8d5be8 100644 --- a/src/uucore/encoding.rs +++ b/src/uucore/encoding.rs @@ -7,10 +7,30 @@ // extern crate data_encoding; -use self::data_encoding::{decode, base32, base64}; -use std::io::Read; +use self::data_encoding::{DecodeError, BASE32, BASE64}; +use std::io::{self, Read, Write}; -pub type DecodeResult = Result, decode::Error>; +#[derive(Fail, Debug)] +pub enum EncodingError { + #[fail(display = "{}", _0)] + Decode(#[cause] DecodeError), + #[fail(display = "{}", _0)] + Io(#[cause] io::Error), +} + +impl From for EncodingError { + fn from(err: io::Error) -> EncodingError { + EncodingError::Io(err) + } +} + +impl From for EncodingError { + fn from(err: DecodeError) -> EncodingError { + EncodingError::Decode(err) + } +} + +pub type DecodeResult = Result, EncodingError>; #[derive(Clone, Copy)] pub enum Format { @@ -21,16 +41,16 @@ use self::Format::*; pub fn encode(f: Format, input: &[u8]) -> String { match f { - Base32 => base32::encode(input), - Base64 => base64::encode(input), + Base32 => BASE32.encode(input), + Base64 => BASE64.encode(input), } } pub fn decode(f: Format, input: &[u8]) -> DecodeResult { - match f { - Base32 => base32::decode(input), - Base64 => base64::decode(input), - } + Ok(match f { + Base32 => BASE32.decode(input)?, + Base64 => BASE64.decode(input)?, + }) } pub struct Data { @@ -38,7 +58,7 @@ pub struct Data { ignore_garbage: bool, input: R, format: Format, - alphabet: &'static str, + alphabet: &'static [u8], } impl Data { @@ -49,8 +69,8 @@ impl Data { input: input, format: format, alphabet: match format { - Base32 => "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=", - Base64 => "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789=+/", + Base32 => b"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=", + Base64 => b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789=+/", }, } } @@ -66,18 +86,14 @@ impl Data { } pub fn decode(&mut self) -> DecodeResult { - let mut buf = String::new(); - self.input.read_to_string(&mut buf).unwrap(); - let clean = if self.ignore_garbage { - buf.chars() - .filter(|&c| self.alphabet.contains(c)) - .collect::() + let mut buf = vec![]; + self.input.read_to_end(&mut buf)?; + if self.ignore_garbage { + buf.retain(|c| self.alphabet.contains(c)); } else { - buf.chars() - .filter(|&c| c != '\r' && c != '\n') - .collect::() + buf.retain(|&c| c != b'\r' && c != b'\n'); }; - decode(self.format, clean.as_bytes()) + decode(self.format, &buf) } pub fn encode(&mut self) -> String { @@ -87,15 +103,25 @@ impl Data { } } +// NOTE: this will likely be phased out at some point pub fn wrap_print(line_wrap: usize, res: String) { - if line_wrap == 0 { - return print!("{}", res); - } + let stdout = io::stdout(); + wrap_write(stdout.lock(), line_wrap, res).unwrap(); +} + +pub fn wrap_write(mut writer: W, line_wrap: usize, res: String) -> io::Result<()> { use std::cmp::min; + + if line_wrap == 0 { + return write!(writer, "{}", res); + } + let mut start = 0; while start < res.len() { let end = min(start + line_wrap, res.len()); - println!("{}", &res[start..end]); + writeln!(writer, "{}", &res[start..end])?; start = end; } + + Ok(()) } diff --git a/src/uucore/lib.rs b/src/uucore/lib.rs index dbbc1b825..bfa111564 100644 --- a/src/uucore/lib.rs +++ b/src/uucore/lib.rs @@ -2,6 +2,11 @@ pub extern crate libc; #[cfg(feature = "winapi")] pub extern crate winapi; +#[cfg(feature = "failure")] +extern crate failure; +#[cfg(feature = "failure_derive")] +#[macro_use] +extern crate failure_derive; #[macro_use] mod macros;