├── .gitignore ├── src ├── lib.rs ├── write.rs ├── stats │ └── timer.rs ├── read.rs ├── main.rs ├── args.rs └── stats.rs ├── COPYING ├── Cargo.toml ├── LICENSE ├── README.md └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | **/*.rs.bk 3 | #Cargo.lock 4 | myfile* -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Pipeviewer library documentation, hooray! 2 | 3 | pub mod args; 4 | pub mod read; 5 | pub mod stats; 6 | pub mod write; 7 | 8 | const CHUNK_SIZE: usize = 16 * 1024; 9 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Nathan Stocks 2 | 3 | Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | copied, modified, or distributed except according to those terms. 7 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pipeviewer" 3 | version = "1.0.0" 4 | authors = ["Nathan Stocks "] 5 | edition = "2018" 6 | description = "Educational version of the pv utility" 7 | homepage = "https://github.com/cleancut/pipeviewer" 8 | repository = "https://github.com/cleancut/pipeviewer" 9 | readme = "README.md" 10 | keywords = ["educational"] 11 | categories = ["command-line-utilities"] 12 | license = "MIT OR Apache-2.0" 13 | 14 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 15 | 16 | [dependencies] 17 | clap = "2.33.0" 18 | crossbeam = "0.7.3" 19 | crossterm = "0.14.2" -------------------------------------------------------------------------------- /src/write.rs: -------------------------------------------------------------------------------- 1 | use crossbeam::channel::Receiver; 2 | use std::fs::File; 3 | use std::io::{self, BufWriter, ErrorKind, Result, Write}; 4 | 5 | pub fn write_loop(outfile: &str, write_rx: Receiver>) -> Result<()> { 6 | let mut writer: Box = if !outfile.is_empty() { 7 | Box::new(BufWriter::new(File::create(outfile)?)) 8 | } else { 9 | Box::new(BufWriter::new(io::stdout())) 10 | }; 11 | 12 | loop { 13 | let buffer = write_rx.recv().unwrap(); 14 | if buffer.is_empty() { 15 | break; 16 | } 17 | if let Err(e) = writer.write_all(&buffer) { 18 | if e.kind() == ErrorKind::BrokenPipe { 19 | // stop the program cleanly 20 | return Ok(()); 21 | } 22 | return Err(e); 23 | } 24 | } 25 | 26 | Ok(()) 27 | } 28 | -------------------------------------------------------------------------------- /src/stats/timer.rs: -------------------------------------------------------------------------------- 1 | use std::time::{Duration, Instant}; 2 | 3 | pub struct Timer { 4 | pub last_instant: Instant, 5 | pub delta: Duration, 6 | pub period: Duration, 7 | pub countdown: Duration, 8 | pub ready: bool, 9 | } 10 | 11 | impl Timer { 12 | pub fn new() -> Self { 13 | let now = Instant::now(); 14 | Self { 15 | last_instant: now, 16 | delta: Duration::default(), 17 | period: Duration::from_millis(1000), 18 | countdown: Duration::default(), 19 | ready: true, 20 | } 21 | } 22 | pub fn update(&mut self) { 23 | let now = Instant::now(); 24 | self.delta = now - self.last_instant; 25 | self.last_instant = now; 26 | self.countdown = self.countdown.checked_sub(self.delta).unwrap_or_else(|| { 27 | self.ready = true; 28 | self.period 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/read.rs: -------------------------------------------------------------------------------- 1 | use crate::CHUNK_SIZE; 2 | use crossbeam::channel::Sender; 3 | use std::fs::File; 4 | use std::io::{self, BufReader, Read, Result}; 5 | 6 | pub fn read_loop(infile: &str, stats_tx: Sender, write_tx: Sender>) -> Result<()> { 7 | let mut reader: Box = if !infile.is_empty() { 8 | Box::new(BufReader::new(File::open(infile)?)) 9 | } else { 10 | Box::new(BufReader::new(io::stdin())) 11 | }; 12 | 13 | let mut buffer = [0; CHUNK_SIZE]; 14 | loop { 15 | let num_read = match reader.read(&mut buffer) { 16 | Ok(0) => break, 17 | Ok(x) => x, 18 | Err(_) => break, 19 | }; 20 | let _ = stats_tx.send(num_read); 21 | if write_tx.send(Vec::from(&buffer[..num_read])).is_err() { 22 | break; 23 | } 24 | } 25 | let _ = stats_tx.send(0); 26 | let _ = write_tx.send(Vec::new()); 27 | Ok(()) 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use crossbeam::channel::{bounded, unbounded}; 2 | use pipeviewer::{args::Args, read, stats, write}; 3 | use std::io::Result; 4 | use std::thread; 5 | 6 | fn main() -> Result<()> { 7 | let args = Args::parse(); 8 | let Args { 9 | infile, 10 | outfile, 11 | silent, 12 | } = args; 13 | 14 | let (stats_tx, stats_rx) = unbounded(); 15 | let (write_tx, write_rx) = bounded(1024); 16 | 17 | let read_handle = thread::spawn(move || read::read_loop(&infile, stats_tx, write_tx)); 18 | let stats_handle = thread::spawn(move || stats::stats_loop(silent, stats_rx)); 19 | let write_handle = thread::spawn(move || write::write_loop(&outfile, write_rx)); 20 | 21 | // crash if any threads have crashed 22 | // `.join()` returns a `thread::Result>` 23 | let read_io_result = read_handle.join().unwrap(); 24 | let stats_io_result = stats_handle.join().unwrap(); 25 | let write_io_result = write_handle.join().unwrap(); 26 | 27 | // Return an error if any threads returned an error 28 | read_io_result?; 29 | stats_io_result?; 30 | write_io_result?; 31 | 32 | Ok(()) 33 | } 34 | -------------------------------------------------------------------------------- /src/args.rs: -------------------------------------------------------------------------------- 1 | use clap::{App, Arg}; 2 | use std::env; 3 | 4 | pub struct Args { 5 | pub infile: String, 6 | pub outfile: String, 7 | pub silent: bool, 8 | } 9 | 10 | impl Args { 11 | pub fn parse() -> Self { 12 | let matches = App::new("pipeviewer") 13 | .arg(Arg::with_name("infile").help("Read from a file instead of stdin")) 14 | .arg( 15 | Arg::with_name("outfile") 16 | .short("o") 17 | .long("outfile") 18 | .takes_value(true) 19 | .help("Write output to a file instead of stdout"), 20 | ) 21 | .arg(Arg::with_name("silent").short("s").long("silent")) 22 | .get_matches(); 23 | let infile = matches.value_of("infile").unwrap_or_default().to_string(); 24 | let outfile = matches.value_of("outfile").unwrap_or_default().to_string(); 25 | let silent = if matches.is_present("silent") { 26 | true 27 | } else { 28 | !env::var("PV_SILENT").unwrap_or_default().is_empty() 29 | }; 30 | Self { 31 | infile, 32 | outfile, 33 | silent, 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/stats.rs: -------------------------------------------------------------------------------- 1 | //! The stats module contains the stats loop 2 | //! 3 | //! # Some header 4 | //! More discussion! 5 | 6 | mod timer; 7 | 8 | use crossbeam::channel::Receiver; 9 | use crossterm::{ 10 | cursor, execute, 11 | style::{self, Color, PrintStyledContent}, 12 | terminal::{Clear, ClearType}, 13 | }; 14 | use std::io::{self, Result, Stderr, Write}; 15 | use std::time::Instant; 16 | use timer::Timer; 17 | 18 | pub fn stats_loop(silent: bool, stats_rx: Receiver) -> Result<()> { 19 | let mut total_bytes = 0; 20 | let start = Instant::now(); 21 | let mut timer = Timer::new(); 22 | let mut stderr = io::stderr(); 23 | loop { 24 | let num_bytes = stats_rx.recv().unwrap(); 25 | timer.update(); 26 | let rate_per_second = num_bytes as f64 / timer.delta.as_secs_f64(); 27 | total_bytes += num_bytes; 28 | if !silent && timer.ready { 29 | timer.ready = false; 30 | output_progress( 31 | &mut stderr, 32 | total_bytes, 33 | start.elapsed().as_secs().as_time(), 34 | rate_per_second, 35 | ); 36 | } 37 | if num_bytes == 0 { 38 | break; 39 | } 40 | } 41 | if !silent { 42 | eprintln!(); 43 | } 44 | Ok(()) 45 | } 46 | 47 | fn output_progress(stderr: &mut Stderr, bytes: usize, elapsed: String, rate: f64) { 48 | let bytes = style::style(format!("{} ", bytes)).with(Color::Red); 49 | let elapsed = style::style(elapsed).with(Color::Green); 50 | let rate = style::style(format!(" [{:.0}b/s]", rate)).with(Color::Blue); 51 | let _ = execute!( 52 | stderr, 53 | cursor::MoveToColumn(0), 54 | Clear(ClearType::CurrentLine), 55 | PrintStyledContent(bytes), 56 | PrintStyledContent(elapsed), 57 | PrintStyledContent(rate) 58 | ); 59 | let _ = stderr.flush(); 60 | } 61 | 62 | /// The TimeOutput trait adds a `.as_time()` method to `u64` 63 | /// 64 | /// # Example 65 | /// Here is an example of how to use it. 66 | /// 67 | /// ```rust 68 | /// use pipeviewer::stats::TimeOutput; 69 | /// assert_eq!(65_u64.as_time(), String::from("0:01:05")) 70 | /// ``` 71 | pub trait TimeOutput { 72 | fn as_time(&self) -> String; 73 | } 74 | 75 | impl TimeOutput for u64 { 76 | /// Renders the u64 into a time string 77 | fn as_time(&self) -> String { 78 | let (hours, left) = (*self / 3600, *self % 3600); 79 | let (minutes, seconds) = (left / 60, left % 60); 80 | format!("{}:{:02}:{:02}", hours, minutes, seconds) 81 | } 82 | } 83 | 84 | #[cfg(test)] 85 | mod tests { 86 | use super::TimeOutput; 87 | 88 | #[test] 89 | fn as_time_format() { 90 | let pairs = vec![ 91 | (5_u64, "0:00:05"), 92 | (60_u64, "0:01:00"), 93 | (154_u64, "0:02:34"), 94 | (3603_u64, "1:00:03"), 95 | ]; 96 | for (input, output) in pairs { 97 | assert_eq!(input.as_time().as_str(), output); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Hands-On Systems Programming with Rust [Video] 5 | This is the code repository for [Hands-On Systems Programming with Rust [Video]]( https://www.packtpub.com/programming/hands-on-systems-programming-with-rust-video), published by [Packt](https://www.packtpub.com/?utm_source=github ). It contains all the supporting project files necessary to work through the video course from start to finish. 6 | ## About the Video Course 7 | Scripting languages will provide safety, but not concurrency and speed, while traditional systems programming languages such as C and C++ will definitely give you speed and some concurrency, but forget about safety! If you need safety, concurrency, and speed, then Rust is the only viable option. 8 | 9 | In this course, you will learn how Rust guarantees memory and thread safety at compile-time, yet uses zero-cost abstractions without the runtime overhead of a garbage collector. You'll learn how to monitor the flow of data through a pipeline by building your own middleware utility. You'll learn how to utilize I/O to interact with the command line, work with standard library mpsc channels to perform data flows, and create an ergonomic timer for your project. You'll apply key concepts in every section while creating your own middleware tool in Rust along the way. 10 | 11 | By the end of this practical course, you will feel comfortable designing safe, consistent, parallel, and high-performance applications in Rust using systems programming. 12 | 13 | This course should appeal to intermediate Linux and general Unix programmers, network programmers, and C/C++ programmers interested in learning different approaches to concurrency. Prior knowledge of basic programming concepts is required, and a working knowledge of Rust is assumed.
14 |

What You Will Learn

15 |
16 | 17 |
    18 | • Explore Rust's package registry for discovering and sharing code
    19 | • Use multithreading to unlock the power of multiple cores
    20 | • Get to know data-flow rate and speed through a pipeline
    21 | • Display time-based statistics using stderr
    22 | • Build your own middleware project to control the flow of data between two processes
    23 | • Best practices and techniques to set up your project for success
    24 | •Test and publish your own project on crates.io
    25 |
26 | 27 | ## Instructions and Navigation 28 | ### Assumed Knowledge 29 | If you are already a software developer and want to learn systems programming in Rust practically and quickly, this course is for you! 30 | This course will greatly appeal to intermediate Linux and general Unix programmers, network programmers, and C / C++ programmers interested in learning different approaches to concurrency. Prior knowledge of basic programming concepts is required. A working knowledge of Rust is assumed. 31 | 32 | ### Technical Requirements
33 | #### Minimum Hardware Requirements
34 | For successful completion of this course, students will require computer systems with at least the following:
35 | OS: macOS, Linux, or Windows
36 | Memory: >= 4GB RAM
37 | Storage: >= 1GB
38 | #### Recommended Hardware Requirements
39 | For an optimal experience with hands-on labs and other practical activities, we recommend the following configuration:
40 | OS: macOS, Linux, or Windows
41 | Memory: >= 16GB RAM
42 | Storage: >= 2GB
43 | #### Software Requirements
44 | Rust, latest stable version
45 | Your favourite editor or IDE with a Rust plugin installed
46 |
47 | ## Related Products 48 | * [Mastering GitLab [Video]](https://www.packtpub.com/networking-and-servers/mastering-gitlab-video?utm_source=github&utm_medium=repository&utm_campaign=9781789537642) 49 | 50 | * [Mastering Palo Alto Networks [Video]](https://www.packtpub.com/networking-and-servers/mastering-palo-alto-networks-video) 51 | 52 | * [Azure Cognitive Services for Developers [Video]](https://www.packtpub.com/application-development/azure-cognitive-services-developers-video) 53 | 54 | ### Author can be contacted via contact details on his website [agileperception.com]. 55 | 56 | [pv]: http://www.ivarch.com/programs/pv.shtml 57 | [agileperception.com]: https://agileperception.com 58 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "ansi_term" 5 | version = "0.11.0" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | dependencies = [ 8 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 9 | ] 10 | 11 | [[package]] 12 | name = "arc-swap" 13 | version = "0.4.4" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | 16 | [[package]] 17 | name = "atty" 18 | version = "0.2.13" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | dependencies = [ 21 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 22 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 23 | ] 24 | 25 | [[package]] 26 | name = "autocfg" 27 | version = "0.1.7" 28 | source = "registry+https://github.com/rust-lang/crates.io-index" 29 | 30 | [[package]] 31 | name = "bitflags" 32 | version = "1.2.1" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | 35 | [[package]] 36 | name = "cfg-if" 37 | version = "0.1.10" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | 40 | [[package]] 41 | name = "clap" 42 | version = "2.33.0" 43 | source = "registry+https://github.com/rust-lang/crates.io-index" 44 | dependencies = [ 45 | "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 46 | "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", 47 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 48 | "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 49 | "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 50 | "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 51 | "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", 52 | ] 53 | 54 | [[package]] 55 | name = "cloudabi" 56 | version = "0.0.3" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | dependencies = [ 59 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 60 | ] 61 | 62 | [[package]] 63 | name = "crossbeam" 64 | version = "0.7.3" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | dependencies = [ 67 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 68 | "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 69 | "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 70 | "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 71 | "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 72 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 73 | ] 74 | 75 | [[package]] 76 | name = "crossbeam-channel" 77 | version = "0.4.0" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | dependencies = [ 80 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 81 | ] 82 | 83 | [[package]] 84 | name = "crossbeam-deque" 85 | version = "0.7.2" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | dependencies = [ 88 | "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 89 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 90 | ] 91 | 92 | [[package]] 93 | name = "crossbeam-epoch" 94 | version = "0.8.0" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | dependencies = [ 97 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 98 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 99 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 100 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 101 | "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", 102 | "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 103 | ] 104 | 105 | [[package]] 106 | name = "crossbeam-queue" 107 | version = "0.2.1" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | dependencies = [ 110 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 111 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 112 | ] 113 | 114 | [[package]] 115 | name = "crossbeam-utils" 116 | version = "0.7.0" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | dependencies = [ 119 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 120 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 121 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 122 | ] 123 | 124 | [[package]] 125 | name = "crossterm" 126 | version = "0.14.2" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | dependencies = [ 129 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 130 | "crossterm_winapi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 131 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 132 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 133 | "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", 134 | "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 135 | "signal-hook 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 136 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 137 | ] 138 | 139 | [[package]] 140 | name = "crossterm_winapi" 141 | version = "0.5.1" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | dependencies = [ 144 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 145 | ] 146 | 147 | [[package]] 148 | name = "fuchsia-zircon" 149 | version = "0.3.3" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | dependencies = [ 152 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 153 | "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 154 | ] 155 | 156 | [[package]] 157 | name = "fuchsia-zircon-sys" 158 | version = "0.3.3" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | 161 | [[package]] 162 | name = "iovec" 163 | version = "0.1.4" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | dependencies = [ 166 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 167 | ] 168 | 169 | [[package]] 170 | name = "kernel32-sys" 171 | version = "0.2.2" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | dependencies = [ 174 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 175 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 176 | ] 177 | 178 | [[package]] 179 | name = "lazy_static" 180 | version = "1.4.0" 181 | source = "registry+https://github.com/rust-lang/crates.io-index" 182 | 183 | [[package]] 184 | name = "libc" 185 | version = "0.2.66" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | 188 | [[package]] 189 | name = "lock_api" 190 | version = "0.3.3" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | dependencies = [ 193 | "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 194 | ] 195 | 196 | [[package]] 197 | name = "log" 198 | version = "0.4.8" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | dependencies = [ 201 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 202 | ] 203 | 204 | [[package]] 205 | name = "memoffset" 206 | version = "0.5.3" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | dependencies = [ 209 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 210 | ] 211 | 212 | [[package]] 213 | name = "mio" 214 | version = "0.6.21" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | dependencies = [ 217 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 218 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 219 | "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 220 | "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 221 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 222 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 223 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 224 | "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 225 | "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 226 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 227 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 228 | ] 229 | 230 | [[package]] 231 | name = "miow" 232 | version = "0.2.1" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | dependencies = [ 235 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 236 | "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 237 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 238 | "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 239 | ] 240 | 241 | [[package]] 242 | name = "net2" 243 | version = "0.2.33" 244 | source = "registry+https://github.com/rust-lang/crates.io-index" 245 | dependencies = [ 246 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 247 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 248 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 249 | ] 250 | 251 | [[package]] 252 | name = "parking_lot" 253 | version = "0.10.0" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | dependencies = [ 256 | "lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 257 | "parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 258 | ] 259 | 260 | [[package]] 261 | name = "parking_lot_core" 262 | version = "0.7.0" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | dependencies = [ 265 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 266 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 267 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 268 | "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", 269 | "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 270 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 271 | ] 272 | 273 | [[package]] 274 | name = "pipeviewer" 275 | version = "1.0.0" 276 | dependencies = [ 277 | "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", 278 | "crossbeam 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", 279 | "crossterm 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", 280 | ] 281 | 282 | [[package]] 283 | name = "redox_syscall" 284 | version = "0.1.56" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | 287 | [[package]] 288 | name = "rustc_version" 289 | version = "0.2.3" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | dependencies = [ 292 | "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 293 | ] 294 | 295 | [[package]] 296 | name = "scopeguard" 297 | version = "1.0.0" 298 | source = "registry+https://github.com/rust-lang/crates.io-index" 299 | 300 | [[package]] 301 | name = "semver" 302 | version = "0.9.0" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | dependencies = [ 305 | "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 306 | ] 307 | 308 | [[package]] 309 | name = "semver-parser" 310 | version = "0.7.0" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | 313 | [[package]] 314 | name = "signal-hook" 315 | version = "0.1.12" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | dependencies = [ 318 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 319 | "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", 320 | "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 321 | ] 322 | 323 | [[package]] 324 | name = "signal-hook-registry" 325 | version = "1.2.0" 326 | source = "registry+https://github.com/rust-lang/crates.io-index" 327 | dependencies = [ 328 | "arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 329 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 330 | ] 331 | 332 | [[package]] 333 | name = "slab" 334 | version = "0.4.2" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | 337 | [[package]] 338 | name = "smallvec" 339 | version = "1.1.0" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | 342 | [[package]] 343 | name = "strsim" 344 | version = "0.8.0" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | 347 | [[package]] 348 | name = "textwrap" 349 | version = "0.11.0" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | dependencies = [ 352 | "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 353 | ] 354 | 355 | [[package]] 356 | name = "unicode-width" 357 | version = "0.1.7" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | 360 | [[package]] 361 | name = "vec_map" 362 | version = "0.8.1" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | 365 | [[package]] 366 | name = "winapi" 367 | version = "0.2.8" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | 370 | [[package]] 371 | name = "winapi" 372 | version = "0.3.8" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | dependencies = [ 375 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 376 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 377 | ] 378 | 379 | [[package]] 380 | name = "winapi-build" 381 | version = "0.1.1" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | 384 | [[package]] 385 | name = "winapi-i686-pc-windows-gnu" 386 | version = "0.4.0" 387 | source = "registry+https://github.com/rust-lang/crates.io-index" 388 | 389 | [[package]] 390 | name = "winapi-x86_64-pc-windows-gnu" 391 | version = "0.4.0" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | 394 | [[package]] 395 | name = "ws2_32-sys" 396 | version = "0.2.1" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | dependencies = [ 399 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 400 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 401 | ] 402 | 403 | [metadata] 404 | "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" 405 | "checksum arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" 406 | "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" 407 | "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" 408 | "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 409 | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 410 | "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" 411 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 412 | "checksum crossbeam 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "69323bff1fb41c635347b8ead484a5ca6c3f11914d784170b158d8449ab07f8e" 413 | "checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" 414 | "checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" 415 | "checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" 416 | "checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" 417 | "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" 418 | "checksum crossterm 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5750773d74a7dc612eac2ded3f55e9cdeeaa072210cd17c0192aedb48adb3618" 419 | "checksum crossterm_winapi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8777c700901e2d5b50c406f736ed6b8f9e43645c7e104ddb74f8bc42b8ae62f6" 420 | "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" 421 | "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" 422 | "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" 423 | "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 424 | "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 425 | "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" 426 | "checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" 427 | "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 428 | "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" 429 | "checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" 430 | "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" 431 | "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" 432 | "checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" 433 | "checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" 434 | "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" 435 | "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 436 | "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" 437 | "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 438 | "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 439 | "checksum signal-hook 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "7a9c17dd3ba2d36023a5c9472ecddeda07e27fd0b05436e8c1e0c8f178185652" 440 | "checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" 441 | "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" 442 | "checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4" 443 | "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 444 | "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 445 | "checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" 446 | "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" 447 | "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 448 | "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" 449 | "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 450 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 451 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 452 | "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" 453 | --------------------------------------------------------------------------------