Getting started in Rust
Installing Rust:
Using Rustup:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Note: It is also possible to install rust via
homebrew
howeverrustup
is the community recommended approach which allows for multiple versions of rust on the same computer. source
Cargo
Cargo is a build tool for Rust. It is also used to manage packages of libraries and applications. When installing Rustup you will get the latest stable version of cargo.
cargo --version
- To check the version of rust you are running
cargo new ${project-name}
- Create a new project
cargo build
- build your project
cargo run
- run your project
cargo test
- test your project
cargo doc
- build documentation for your project
cargo publish
- publish a library to crates.io
Example: Streaming Math
cargo new streaming-math
Will create the following project:
---
title: Streaming Math Directory
---
flowchart LR
project(streaming-math) --> src(src) --> main[/main/]
src --> Cargo[/Cargo.toml/]
Cargo.toml
- The manifest file for Rust. Project metadata and dependencies are defined here.
src/main.rs
- The source directory and entry point for your code.
source: streaming-math
Running the initial project
Enter the project (cd streaming-math
) and run (cargo run
) and you will see the following
Hello, world!
Initial implementation:
For this project I aim to create a simple app which streams 2 files summing up corresponding lines between each file. We will provide some safety by checking for Ok Results and handling non-matching results.
- Opens 2 files passed in by argument (Accepting Command Line Arguments)
- Streams through both files (BufReader.lines)
- Zips both streams together (Iterator.zip)
- Parses each line as an int (parse)
- Sums up both rows
use std::env;
use std::fs::File;
use std::io::{self,BufRead,BufReader,Result,Lines};
use std::path::Path;
fn main() {
let args: Vec<String> = env::args().collect();
let path1 = &args[1];
let path2 = &args[2];
if let (Ok(lines1), Ok(lines2)) = (read_lines(path1), read_lines(path2)) {
for (line1, line2) in lines1.zip(lines2) {
if let (Ok(one), Ok(two)) = (line1, line2) {
if let(Ok(one_int), Ok(two_int)) = (one.parse::<i32>(), two.parse::<i32>()) {
println!("{}", one_int + two_int )
} else {
println!("Unable to add {}<from: {}> + {}<from: {}>", one, path1, two, path2);
}
}
}
} else {
println!("Unable to open both files: {} or {}", path1, path2)
}
}
fn read_lines<P>(path: P) -> Result<Lines<BufReader<File>>>
where P: AsRef<Path>, {
let file = File::open(path)?;
Ok(io::BufReader::new(file).lines())
}
Testing the results:
When we execute:
cargo run -- <(for num in 1 2 3 4 5; echo $num) <(for num in 9 8 7 6 5; echo $num)
We get the following:
Compiling streaming-math v0.1.0 (/Users/stephen/source/StephenSmithwick.github.io/streaming-math)
Finished dev [unoptimized + debuginfo] target(s) in 0.87s
Running `target/debug/streaming-math /dev/fd/11 /dev/fd/13`
10
10
10
10
10
More reading: