From 06f771f64db2fe64d422b6a4748017bfd76a5c69 Mon Sep 17 00:00:00 2001 From: Sondre Nilsen Date: Sun, 9 May 2021 17:10:53 +0200 Subject: [PATCH 1/3] Use unbuffered IO for faster printing to stdout --- src/formatter.rs | 19 ++++++++++++------- src/main.rs | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/formatter.rs b/src/formatter.rs index e2553c41..34610ee3 100644 --- a/src/formatter.rs +++ b/src/formatter.rs @@ -1,6 +1,6 @@ //! Functions related to formatting and printing lines from a `Tokenizer`. -use std::io::BufRead; +use std::io::{BufRead, Write}; use ansi_term::{ANSIString, ANSIStrings}; use log::debug; @@ -63,16 +63,17 @@ fn format_code(command: &str, text: &str, config: &Config) -> String { } /// Print a token stream to an ANSI terminal. -pub fn print_lines(tokenizer: &mut Tokenizer, config: &Config) +pub fn print_lines(writer: &mut T, tokenizer: &mut Tokenizer, config: &Config) where R: BufRead, + T: Write, { let mut command = String::new(); while let Some(token) = tokenizer.next_token() { match token { LineType::Empty => { if !config.display.compact { - println!() + writeln!(writer).unwrap(); } } LineType::Title(title) => { @@ -83,13 +84,17 @@ where command = title; debug!("Detected command name: {}", &command); } - LineType::Description(text) => println!(" {}", config.style.description.paint(text)), - LineType::ExampleText(text) => println!(" {}", config.style.example_text.paint(text)), + LineType::Description(text) => { + writeln!(writer, " {}", config.style.description.paint(text)).unwrap(); + } + LineType::ExampleText(text) => { + writeln!(writer, " {}", config.style.example_text.paint(text)).unwrap(); + } LineType::ExampleCode(text) => { - println!(" {}", &format_code(&command, &text, &config)) + writeln!(writer, " {}", &format_code(&command, &text, &config)).unwrap(); } LineType::Other(text) => debug!("Unknown line type: {:?}", text), } } - println!(); + writeln!(writer).unwrap(); } diff --git a/src/main.rs b/src/main.rs index 90f265c9..c3f79465 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,13 +14,13 @@ #![allow(clippy::module_name_repetitions)] #![allow(clippy::too_many_lines)] -use std::env; use std::fs::File; use std::io::BufRead; use std::io::BufReader; use std::iter; use std::path::PathBuf; use std::process; +use std::{env, io::Write}; use ansi_term::{Color, Style}; use app_dirs::AppInfo; @@ -84,7 +84,9 @@ fn print_page( enable_markdown: bool, config: &Config, ) -> Result<(), String> { - // Open file + let stdout = std::io::stdout(); + let mut handle = stdout.lock(); + for path in page.paths() { let file = File::open(path).map_err(|msg| format!("Could not open file: {}", msg))?; let reader = BufReader::new(file); @@ -92,15 +94,21 @@ fn print_page( if enable_markdown { // Print the raw markdown of the file. for line in reader.lines() { - println!("{}", line.unwrap()); + writeln!(handle, "{}", line.unwrap()) + .map_err(|_| "Could not write to stdout".to_string())?; } } else { // Create tokenizer and print output let mut tokenizer = Tokenizer::new(reader); - print_lines(&mut tokenizer, &config); + print_lines(&mut handle, &mut tokenizer, &config) + .map_err(|_| "Could not write to stdout".to_string())?; }; } + handle + .flush() + .map_err(|_| "Could not flush stdout".to_string())?; + Ok(()) } From 22693c09bace8873de9f7f5afdc42eaa195cd700 Mon Sep 17 00:00:00 2001 From: Sondre Nilsen Date: Sun, 9 May 2021 17:11:17 +0200 Subject: [PATCH 2/3] Use rustls for TLS to avoid dynamic linking --- Cargo.lock | 243 ++++++++++++++++++++++++----------------------------- Cargo.toml | 2 +- 2 files changed, 110 insertions(+), 135 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f6cee684..8e8acd3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -162,22 +162,6 @@ dependencies = [ "unreachable", ] -[[package]] -name = "core-foundation" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" - [[package]] name = "crc32fast" version = "1.2.0" @@ -338,21 +322,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -390,6 +359,18 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789" +[[package]] +name = "futures-macro" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.5" @@ -413,10 +394,13 @@ checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" dependencies = [ "futures-core", "futures-io", + "futures-macro", "futures-task", "memchr", "pin-project", "pin-utils", + "proc-macro-hack", + "proc-macro-nested", "slab", ] @@ -541,16 +525,19 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.4.3" +name = "hyper-rustls" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d979acc56dcb5b8dddba3917601745e877576475aa046df3226eabdecef78eed" +checksum = "37743cc83e8ee85eacfce90f2f4102030d9ff0a95244098d781e9bee4a90abb6" dependencies = [ "bytes", + "futures-util", "hyper", - "native-tls", + "log", + "rustls", "tokio", - "tokio-tls", + "tokio-rustls", + "webpki", ] [[package]] @@ -723,24 +710,6 @@ dependencies = [ "ws2_32-sys", ] -[[package]] -name = "native-tls" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "ndk" version = "0.1.0" @@ -842,39 +811,6 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad" -[[package]] -name = "openssl" -version = "0.10.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d575eff3665419f9b83678ff2815858ad9d11567e082f5ac1814baba4e2bcb4" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "lazy_static", - "libc", - "openssl-sys", -] - -[[package]] -name = "openssl-probe" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" - -[[package]] -name = "openssl-sys" -version = "0.9.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de" -dependencies = [ - "autocfg", - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "pager" version = "0.15.0" @@ -923,12 +859,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkg-config" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" - [[package]] name = "ppv-lite86" version = "0.2.9" @@ -973,6 +903,18 @@ dependencies = [ "toml", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + +[[package]] +name = "proc-macro-nested" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" + [[package]] name = "proc-macro2" version = "1.0.19" @@ -1085,33 +1027,62 @@ dependencies = [ "http", "http-body", "hyper", - "hyper-tls", + "hyper-rustls", "ipnet", "js-sys", "lazy_static", "log", "mime", "mime_guess", - "native-tls", "percent-encoding", "pin-project-lite", + "rustls", "serde", "serde_urlencoded", "tokio", - "tokio-tls", + "tokio-rustls", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", "winreg", ] +[[package]] +name = "ring" +version = "0.16.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b72b84d47e8ec5a4f2872e8262b8f8256c5be1c938a7d6d3a867a3ba8f722f74" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi 0.3.9", +] + [[package]] name = "rustc-demangle" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +[[package]] +name = "rustls" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" +dependencies = [ + "base64", + "log", + "ring", + "sct", + "webpki", +] + [[package]] name = "ryu" version = "1.0.5" @@ -1128,36 +1099,13 @@ dependencies = [ ] [[package]] -name = "schannel" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" -dependencies = [ - "lazy_static", - "winapi 0.3.9", -] - -[[package]] -name = "security-framework" -version = "0.4.4" +name = "sct" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535" +checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" -dependencies = [ - "core-foundation-sys", - "libc", + "ring", + "untrusted", ] [[package]] @@ -1221,6 +1169,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "strsim" version = "0.9.3" @@ -1344,13 +1298,15 @@ dependencies = [ ] [[package]] -name = "tokio-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343" +checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a" dependencies = [ - "native-tls", + "futures-core", + "rustls", "tokio", + "webpki", ] [[package]] @@ -1456,6 +1412,12 @@ dependencies = [ "void", ] +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "url" version = "2.1.1" @@ -1467,12 +1429,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "vcpkg" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" - [[package]] name = "version_check" version = "0.9.2" @@ -1605,6 +1561,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab146130f5f790d45f82aeeb09e55a256573373ec64409fc19a6fb82fb1032ae" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8eff4b7516a57307f9349c64bf34caa34b940b66fed4b2fb3136cb7386e5739" +dependencies = [ + "webpki", +] + [[package]] name = "winapi" version = "0.2.8" diff --git a/Cargo.toml b/Cargo.toml index 930c2d94..bbbd3529 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ docopt = "1" env_logger = { version = "0.7", optional = true } flate2 = "1" log = "0.4" -reqwest = { version = "0.10.3", features = ["blocking", "native-tls"], default-features = false } +reqwest = { version = "0.10.3", features = ["blocking", "rustls-tls"], default-features = false } serde = "1.0.21" serde_derive = "1.0.21" tar = "0.4.14" From feb20d8c5c79494a827f6b3c51592dcd7df6edce Mon Sep 17 00:00:00 2001 From: Sondre Nilsen Date: Thu, 20 May 2021 12:25:10 +0200 Subject: [PATCH 3/3] Add WriteError type, convert print_lines to return a result --- src/error.rs | 13 +++++++++++++ src/formatter.rs | 22 +++++++++++++++------- src/main.rs | 22 +++++----------------- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/error.rs b/src/error.rs index fdac30f4..ffd61997 100644 --- a/src/error.rs +++ b/src/error.rs @@ -7,6 +7,18 @@ pub enum TealdeerError { CacheError(String), ConfigError(String), UpdateError(String), + WriteError(String), +} + +impl TealdeerError { + pub fn message(&self) -> &str { + match self { + Self::CacheError(msg) + | Self::ConfigError(msg) + | Self::UpdateError(msg) + | Self::WriteError(msg) => msg, + } + } } impl From for TealdeerError { @@ -21,6 +33,7 @@ impl fmt::Display for TealdeerError { Self::CacheError(e) => write!(f, "CacheError: {}", e), Self::ConfigError(e) => write!(f, "ConfigError: {}", e), Self::UpdateError(e) => write!(f, "UpdateError: {}", e), + Self::WriteError(e) => write!(f, "WriteError: {}", e), } } } diff --git a/src/formatter.rs b/src/formatter.rs index 34610ee3..887df6be 100644 --- a/src/formatter.rs +++ b/src/formatter.rs @@ -6,6 +6,7 @@ use ansi_term::{ANSIString, ANSIStrings}; use log::debug; use crate::config::Config; +use crate::error::TealdeerError::{self, WriteError}; use crate::tokenizer::Tokenizer; use crate::types::LineType; @@ -63,17 +64,21 @@ fn format_code(command: &str, text: &str, config: &Config) -> String { } /// Print a token stream to an ANSI terminal. -pub fn print_lines(writer: &mut T, tokenizer: &mut Tokenizer, config: &Config) +pub fn print_lines( + writer: &mut T, + tokenizer: &mut Tokenizer, + config: &Config, +) -> Result<(), TealdeerError> where - R: BufRead, T: Write, + R: BufRead, { let mut command = String::new(); while let Some(token) = tokenizer.next_token() { match token { LineType::Empty => { if !config.display.compact { - writeln!(writer).unwrap(); + writeln!(writer).map_err(|e| WriteError(e.to_string()))?; } } LineType::Title(title) => { @@ -85,16 +90,19 @@ where debug!("Detected command name: {}", &command); } LineType::Description(text) => { - writeln!(writer, " {}", config.style.description.paint(text)).unwrap(); + writeln!(writer, " {}", config.style.description.paint(text)) + .map_err(|e| WriteError(e.to_string()))?; } LineType::ExampleText(text) => { - writeln!(writer, " {}", config.style.example_text.paint(text)).unwrap(); + writeln!(writer, " {}", config.style.example_text.paint(text)) + .map_err(|e| WriteError(e.to_string()))?; } LineType::ExampleCode(text) => { - writeln!(writer, " {}", &format_code(&command, &text, &config)).unwrap(); + writeln!(writer, " {}", &format_code(&command, &text, &config)) + .map_err(|e| WriteError(e.to_string()))?; } LineType::Other(text) => debug!("Unknown line type: {:?}", text), } } - writeln!(writer).unwrap(); + writeln!(writer).map_err(|e| WriteError(e.to_string())) } diff --git a/src/main.rs b/src/main.rs index c3f79465..58efc7e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,7 +41,7 @@ mod types; use crate::cache::{Cache, PageLookupResult}; use crate::config::{get_config_dir, get_config_path, make_default_config, Config, MAX_CACHE_AGE}; use crate::dedup::Dedup; -use crate::error::TealdeerError::{CacheError, ConfigError, UpdateError}; +use crate::error::TealdeerError::ConfigError; use crate::formatter::print_lines; use crate::tokenizer::Tokenizer; use crate::types::{ColorOptions, OsType}; @@ -101,7 +101,7 @@ fn print_page( // Create tokenizer and print output let mut tokenizer = Tokenizer::new(reader); print_lines(&mut handle, &mut tokenizer, &config) - .map_err(|_| "Could not write to stdout".to_string())?; + .map_err(|e| format!("Could not write to stdout: {}", e.message()))?; }; } @@ -164,11 +164,7 @@ fn check_cache(args: &Args, enable_styles: bool) { /// Clear the cache fn clear_cache(quietly: bool) { Cache::clear().unwrap_or_else(|e| { - match e { - CacheError(msg) | ConfigError(msg) | UpdateError(msg) => { - eprintln!("Could not delete cache: {}", msg) - } - }; + eprintln!("Could not delete cache: {}", e.message()); process::exit(1); }); if !quietly { @@ -179,11 +175,7 @@ fn clear_cache(quietly: bool) { /// Update the cache fn update_cache(cache: &Cache, quietly: bool) { cache.update().unwrap_or_else(|e| { - match e { - CacheError(msg) | ConfigError(msg) | UpdateError(msg) => { - eprintln!("Could not update cache: {}", msg) - } - }; + eprintln!("Could not update cache: {}", e.message()); process::exit(1); }); if !quietly { @@ -461,11 +453,7 @@ fn main() { // Get list of pages let pages = cache.list_pages().unwrap_or_else(|e| { - match e { - CacheError(msg) | ConfigError(msg) | UpdateError(msg) => { - eprintln!("Could not get list of pages: {}", msg) - } - } + eprintln!("Could not get list of pages: {}", e.message()); process::exit(1); });