Migration from GitHub
This commit is contained in:
121
LICENSE
Normal file
121
LICENSE
Normal file
@@ -0,0 +1,121 @@
|
||||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
||||
65
README.md
Normal file
65
README.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# getting_rusty
|
||||
|
||||
- Original Repo: https://github.com/rarmknecht/getting_rusty
|
||||
- Rust Lang Book: https://doc.rust-lang.org/stable/book/
|
||||
- Journey Began: 2021 May 9th
|
||||
|
||||
## Purpose
|
||||
|
||||
This repo is to hold code and exercises as I journey through *The Rust Programming Language* book.
|
||||
|
||||
## Status
|
||||
| Chapter | Status | Date | Notes |
|
||||
|---------|--------|-------|-----|
|
||||
|01 Getting Started|Complete|2021 May 09|Intro to Cargo|
|
||||
|02 Guessing Game|Complete|2021 May 09|First Program|
|
||||
|03 Common Concepts|Complete|2021 May 09|First "Homework"|
|
||||
|04 Understanding Ownership|Complete|2021 May 10| - |
|
||||
|05 Structs|Complete|2021 May 10|Rectangles|
|
||||
|06 Enums & Patterns| - | - | - |
|
||||
|07 Packages, Crates, Modules| - | - | - |
|
||||
|08 Common Collections| - | - | - |
|
||||
|09 Error Handling| - | - | - |
|
||||
|10 Generics| - | - | - |
|
||||
|11 Automated Tests| - | - | - |
|
||||
|12 An I/O Project| - | - | - |
|
||||
|13 Functional Features| - | - | - |
|
||||
|14 Cargo and Crates.io| - | - | - |
|
||||
|15 Smart Pointers| - | - | - |
|
||||
|16 Fearless Concurrency| - | - | - |
|
||||
|17 OOP Features| - | - | - |
|
||||
|18 Patterns & Matching| - | - | - |
|
||||
|19 Advanced Features| - | - | - |
|
||||
|20 Project: Web Server| - | - | - |
|
||||
<br/>
|
||||
|
||||
## History of Travels
|
||||
|
||||
### 2021 May 09
|
||||
|
||||
Began the journey after a news headline informed me that the Windows API was now rust accessible.
|
||||
https://blogs.windows.com/windowsdeveloper/2021/05/06/announcing-rust-for-windows-v0-9/
|
||||
|
||||
This triggered me to watch a few rust videos on youtube, and even read a rust book on "Kindle Unlimited". These left me intrigued and thinking it'd be fun to update my media pipeline with some rust tooling.
|
||||
|
||||
Starting the journey on my Arch Linux system despite the lead-in with the windows announcement.
|
||||
|
||||
#### Cross Compilation
|
||||
|
||||
Today I learned how to do cross compilation, which is super nice since my use cases find me potentially wanting to execute my code on either x64 linux, armv7, or windows.
|
||||
|
||||
1. List targets with:
|
||||
|
||||
`> rustc --print target-list`
|
||||
|
||||
2. Add the desired target
|
||||
|
||||
`> rustup target add <target_name>`
|
||||
|
||||
3. Add (if not already installed) the cross package
|
||||
|
||||
`> cargo install cross`
|
||||
|
||||
4. Cross Build the project
|
||||
|
||||
`> ~/.cargo/bin/cross build --target <target_name>`
|
||||
5
chapter_01/hello_cargo/Cargo.lock
generated
Normal file
5
chapter_01/hello_cargo/Cargo.lock
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "hello_cargo"
|
||||
version = "0.1.0"
|
||||
9
chapter_01/hello_cargo/Cargo.toml
Normal file
9
chapter_01/hello_cargo/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "hello_cargo"
|
||||
version = "0.1.0"
|
||||
authors = ["rarmknecht <rarmknecht@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
3
chapter_01/hello_cargo/src/main.rs
Normal file
3
chapter_01/hello_cargo/src/main.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
BIN
chapter_01/hello_world/main
Executable file
BIN
chapter_01/hello_world/main
Executable file
Binary file not shown.
3
chapter_01/hello_world/main.rs
Normal file
3
chapter_01/hello_world/main.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
83
chapter_02/guessing_game/Cargo.lock
generated
Normal file
83
chapter_02/guessing_game/Cargo.lock
generated
Normal file
@@ -0,0 +1,83 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "guessing_game"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
10
chapter_02/guessing_game/Cargo.toml
Normal file
10
chapter_02/guessing_game/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "guessing_game"
|
||||
version = "0.1.0"
|
||||
authors = ["rarmknecht <rarmknecht@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
rand = "0.8.3"
|
||||
39
chapter_02/guessing_game/src/main.rs
Normal file
39
chapter_02/guessing_game/src/main.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
use std::io;
|
||||
use std::cmp::Ordering;
|
||||
use rand::Rng;
|
||||
|
||||
fn main() {
|
||||
println!("Guess the Number!");
|
||||
|
||||
let secret_number = rand::thread_rng().gen_range(1..101);
|
||||
|
||||
println!("Secret is: {}", secret_number);
|
||||
loop {
|
||||
println!("Please input your guess:");
|
||||
|
||||
let mut guess = String::new();
|
||||
|
||||
io::stdin()
|
||||
.read_line(&mut guess)
|
||||
.expect("Failed to read line :(");
|
||||
|
||||
println!("You guessed: {}", guess);
|
||||
|
||||
let guess: u32 = match guess.trim().parse() {
|
||||
Ok(num) => num,
|
||||
Err(_) => {
|
||||
println!("!!! Only Numbers !!!");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
match guess.cmp(&secret_number) {
|
||||
Ordering::Greater => println!("You Guessed HIGH"),
|
||||
Ordering::Less => println!("You Guessed LOW"),
|
||||
Ordering::Equal => {
|
||||
println!("WOW! You got it!!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
5
chapter_03/tempconverter/Cargo.lock
generated
Normal file
5
chapter_03/tempconverter/Cargo.lock
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "tempconverter"
|
||||
version = "0.1.0"
|
||||
9
chapter_03/tempconverter/Cargo.toml
Normal file
9
chapter_03/tempconverter/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "tempconverter"
|
||||
version = "0.1.0"
|
||||
authors = ["rarmknecht <rarmknecht@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
61
chapter_03/tempconverter/src/main.rs
Normal file
61
chapter_03/tempconverter/src/main.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
use std::io;
|
||||
|
||||
fn main() {
|
||||
|
||||
println!("Welcome to Temp Converter!");
|
||||
|
||||
// Loop the Main Menu
|
||||
loop {
|
||||
println!("Chose:\n\t[1] F to C\n\t[2] C to F\n\t[3] Quit");
|
||||
|
||||
let mut choice = String::new();
|
||||
io::stdin()
|
||||
.read_line(&mut choice)
|
||||
.expect("Failed to read line");
|
||||
let choice = choice.trim();
|
||||
|
||||
match choice {
|
||||
"1" => {
|
||||
println!("F to C it is!");
|
||||
let c = f_to_c(get_temp());
|
||||
println!("That's {} in Celsius", c);
|
||||
}
|
||||
"2" => {
|
||||
println!("C to F it is!");
|
||||
let f = c_to_f(get_temp());
|
||||
println!("That's {} in Fahrenheit", f);
|
||||
}
|
||||
"3" => {
|
||||
println!("Good Bye!");
|
||||
break;
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn f_to_c(f: f64) -> f64 {
|
||||
(f - 32.0) * (5.0/9.0)
|
||||
}
|
||||
|
||||
fn c_to_f(c: f64) -> f64 {
|
||||
(c * (9.0/5.0)) + 32.0
|
||||
}
|
||||
|
||||
fn get_temp() -> f64 {
|
||||
loop {
|
||||
println!("Enter your starting temp:");
|
||||
let mut temp = String::new();
|
||||
io::stdin()
|
||||
.read_line(&mut temp)
|
||||
.expect("Failed to read line");
|
||||
let temp = temp.trim();
|
||||
|
||||
let f : f64 = match temp.parse() {
|
||||
Ok(num) => num,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
return f
|
||||
}
|
||||
}
|
||||
5
chapter_05/rectangles/Cargo.lock
generated
Normal file
5
chapter_05/rectangles/Cargo.lock
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "rectangles"
|
||||
version = "0.1.0"
|
||||
9
chapter_05/rectangles/Cargo.toml
Normal file
9
chapter_05/rectangles/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "rectangles"
|
||||
version = "0.1.0"
|
||||
authors = ["rarmknecht <rarmknecht@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
45
chapter_05/rectangles/src/main.rs
Normal file
45
chapter_05/rectangles/src/main.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
#[derive(Debug)]
|
||||
struct Rectangle {
|
||||
width: u32,
|
||||
height: u32,
|
||||
}
|
||||
|
||||
impl Rectangle {
|
||||
fn area(&self) -> u32 {
|
||||
self.width * self.height
|
||||
}
|
||||
|
||||
fn can_hold(&self, other: &Rectangle) -> bool {
|
||||
self.width > other.width && self.height > other.height
|
||||
}
|
||||
|
||||
fn square(size: u32) -> Rectangle {
|
||||
Rectangle {
|
||||
width: size,
|
||||
height: size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let rect1 = Rectangle {
|
||||
width: 30,
|
||||
height: 50,
|
||||
};
|
||||
|
||||
println!(
|
||||
"The area of the rectangle is {} square pixels.",
|
||||
rect1.area()
|
||||
);
|
||||
|
||||
println!(
|
||||
"This rectangle fits inside: {}",
|
||||
rect1.can_hold(&Rectangle {width: 20, height: 30,})
|
||||
);
|
||||
|
||||
println!(
|
||||
"This is a square! {:?}",
|
||||
Rectangle::square(32)
|
||||
);
|
||||
|
||||
}
|
||||
16
chapter_05/rectangles/src/main.rs.basic
Normal file
16
chapter_05/rectangles/src/main.rs.basic
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
fn main() {
|
||||
|
||||
let widthl = 30;
|
||||
let heightl = 50;
|
||||
|
||||
println!(
|
||||
"The area of the rectangle is {} square pixels",
|
||||
area(widthl, heightl)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
fn area(width: u32, height: u32) -> u32 {
|
||||
width * height
|
||||
}
|
||||
20
chapter_05/rectangles/src/main.rs.struct
Normal file
20
chapter_05/rectangles/src/main.rs.struct
Normal file
@@ -0,0 +1,20 @@
|
||||
struct Rectangle {
|
||||
width: u32,
|
||||
height: u32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let rect1 = Rectangle {
|
||||
width: 30,
|
||||
height: 50,
|
||||
};
|
||||
|
||||
println!(
|
||||
"The area of the rectangle is {} square pixels.",
|
||||
area(&rect1)
|
||||
);
|
||||
}
|
||||
|
||||
fn area(rectangle: &Rectangle) -> u32 {
|
||||
rectangle.width * rectangle.height
|
||||
}
|
||||
1
practical_rust_projects/tracking.md
Normal file
1
practical_rust_projects/tracking.md
Normal file
@@ -0,0 +1 @@
|
||||
[] Chapter 2 - Building a Command Line Program
|
||||
1032
warp_tutorial/holodeck/Cargo.lock
generated
Normal file
1032
warp_tutorial/holodeck/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
12
warp_tutorial/holodeck/Cargo.toml
Normal file
12
warp_tutorial/holodeck/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "holodeck"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
warp = "0.3"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
214
warp_tutorial/holodeck/src/lib.rs
Normal file
214
warp_tutorial/holodeck/src/lib.rs
Normal file
@@ -0,0 +1,214 @@
|
||||
mod models {
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Simulation {
|
||||
pub id: u64,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl PartialEq for Simulation {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id == other.id
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Simulation {}
|
||||
|
||||
impl Hash for Simulation {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.id.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_simulation<'a>(sims: &'a HashSet<Simulation>, id: u64) -> Option<&'a Simulation> {
|
||||
sims.get(&Simulation{
|
||||
id,
|
||||
name: String::new(),
|
||||
})
|
||||
}
|
||||
|
||||
pub type Db = Arc<Mutex<HashSet<Simulation>>>;
|
||||
|
||||
pub fn new_db() -> Db {
|
||||
Arc::new(Mutex::new(HashSet::new()))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod filters {
|
||||
use warp::Filter;
|
||||
use super::{handlers,models};
|
||||
|
||||
pub fn list_sims(db: models::Db) -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone{
|
||||
let db_map = warp::any()
|
||||
.map(move || db.clone());
|
||||
|
||||
let opt = warp::path::param::<u64>()
|
||||
.map(Some)
|
||||
.or_else(|_| async {
|
||||
// Ok(None)
|
||||
Ok::<(Option<u64>,), std::convert::Infallible>((None,))
|
||||
});
|
||||
|
||||
warp::path!("holodeck" / ..)
|
||||
.and(opt)
|
||||
.and(warp::path::end())
|
||||
.and(db_map)
|
||||
.and_then(handlers::handle_list_sims)
|
||||
}
|
||||
|
||||
fn json_body() -> impl Filter<Extract = (models::Simulation,), Error = warp::Rejection> + Clone{
|
||||
warp::body::content_length_limit(1024 * 16)
|
||||
.and(warp::body::json())
|
||||
}
|
||||
|
||||
pub fn post_sim(db : models::Db) -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone{
|
||||
let db_map = warp::any()
|
||||
.map(move || db.clone());
|
||||
|
||||
warp::path!("holodeck")
|
||||
.and(warp::post())
|
||||
.and(json_body())
|
||||
.and(db_map)
|
||||
.and_then(handlers::handle_create_sim)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod handlers {
|
||||
use warp::http::StatusCode;
|
||||
use std::convert::Infallible;
|
||||
use super::models;
|
||||
|
||||
pub async fn handle_list_sims(param: u64, db: models::Db) -> Result<impl warp::Reply, Infallible> {
|
||||
let mut result = db.lock().await.clone();
|
||||
if param > 0 {
|
||||
result.retain(|k| k.id == param);
|
||||
};
|
||||
Ok(warp::reply::json(&result))
|
||||
}
|
||||
|
||||
pub async fn handle_create_sim(sim: models::Simulation, db: models::Db) -> Result<impl warp::Reply, Infallible> {
|
||||
let mut map = db.lock().await;
|
||||
|
||||
if let Some(result) = map.get(&sim) {
|
||||
return Ok(warp::reply::with_status(
|
||||
format!("Simulation #{} already exists under the name {}", result.id, result.name),
|
||||
StatusCode::BAD_REQUEST,
|
||||
));
|
||||
}
|
||||
|
||||
map.insert(sim.clone());
|
||||
Ok(warp::reply::with_status(format!("Simulation #{} created", sim.id), StatusCode::CREATED))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use warp::http::StatusCode;
|
||||
use warp::test::request;
|
||||
use std::collections::HashSet;
|
||||
use super::{filters,models};
|
||||
|
||||
#[tokio::test]
|
||||
async fn try_list() {
|
||||
use std::str;
|
||||
use serde_json;
|
||||
|
||||
let simulation1 = models::Simulation{
|
||||
id: 1,
|
||||
name: String::from("The Big Goodbye"),
|
||||
};
|
||||
|
||||
let simulation2 = models::Simulation{
|
||||
id: 2,
|
||||
name: String::from("Bride of Chaos!"),
|
||||
};
|
||||
|
||||
let db = models::new_db();
|
||||
db.lock().await.insert(simulation1.clone());
|
||||
db.lock().await.insert(simulation2.clone());
|
||||
|
||||
let api = filters::list_sims(db);
|
||||
|
||||
let response = request()
|
||||
.method("GET")
|
||||
.path("/holodeck")
|
||||
.reply(&api)
|
||||
.await;
|
||||
|
||||
let result: Vec<u8> = response.into_body().into_iter().collect();
|
||||
let result = str::from_utf8(&result).unwrap();
|
||||
let result: HashSet<models::Simulation> = serde_json::from_str(result).unwrap();
|
||||
assert_eq!(models::get_simulation(&result, 1).unwrap(), &simulation1);
|
||||
assert_eq!(models::get_simulation(&result, 2).unwrap(), &simulation2);
|
||||
|
||||
let response = request()
|
||||
.method("GET")
|
||||
.path("/holodeck/2")
|
||||
.reply(&api)
|
||||
.await;
|
||||
|
||||
let result: Vec<u8> = response.into_body().into_iter().collect();
|
||||
let result = str::from_utf8(&result).unwrap();
|
||||
let result: HashSet<models::Simulation> = serde_json::from_str(result).unwrap();
|
||||
assert_eq!(result.len(), 1);
|
||||
assert_eq!(models::get_simulation(&result, 2).unwrap(), &simulation2);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn try_create() {
|
||||
let db = models::new_db();
|
||||
let api = filters::post_sim(db);
|
||||
|
||||
let response = request()
|
||||
.method("POST")
|
||||
.path("/holodeck")
|
||||
.json(&models::Simulation{
|
||||
id: 1,
|
||||
name: String::from("The Big Goodbye")
|
||||
})
|
||||
.reply(&api)
|
||||
.await;
|
||||
|
||||
assert_eq!(response.status(), StatusCode::CREATED);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn try_create_duplicates() {
|
||||
let db = models::new_db();
|
||||
let api = filters::post_sim(db);
|
||||
|
||||
let response = request()
|
||||
.method("POST")
|
||||
.path("/holodeck")
|
||||
.json(&models::Simulation{
|
||||
id: 1,
|
||||
name: String::from("Bride of Chaos!")
|
||||
})
|
||||
.reply(&api)
|
||||
.await;
|
||||
|
||||
assert_eq!(response.status(), StatusCode::CREATED);
|
||||
|
||||
let response = request()
|
||||
.method("POST")
|
||||
.path("/holodeck")
|
||||
.json(&models::Simulation{
|
||||
id: 1,
|
||||
name: String::from("Bride of Chaos!")
|
||||
})
|
||||
.reply(&api)
|
||||
.await;
|
||||
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
1182
waytoodeep/Cargo.lock
generated
Normal file
1182
waytoodeep/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
14
waytoodeep/Cargo.toml
Normal file
14
waytoodeep/Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "waytoodeep"
|
||||
version = "0.1.0"
|
||||
authors = ["rarmknecht <rarmknecht@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
color-eyre = "0.5.11"
|
||||
reqwest = { version = "0.11.4", features = ["rustls-tls"], default-features = false }
|
||||
tokio = { version = "1.9.0", features = ["full"] }
|
||||
tracing = "0.1.26"
|
||||
tracing-subscriber = "0.2.19"
|
||||
54
waytoodeep/src/main.rs
Normal file
54
waytoodeep/src/main.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
// Understanding Rust Futures: Way Too Deep
|
||||
// https://fasterthanli.me/articles/understanding-rust-futures-by-going-way-too-deep
|
||||
//
|
||||
|
||||
// Began: 2021 Jul 26
|
||||
// Completed:
|
||||
|
||||
use color_eyre::Report;
|
||||
use tracing::info;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use reqwest::Client;
|
||||
|
||||
pub const URL_1: &str = "https://fasterthanli.me/articles/whats-in-the-box";
|
||||
pub const URL_2: &str = "https://fasterthanli.me/series/advent-of-code-2020/part-13";
|
||||
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Report> {
|
||||
setup()?;
|
||||
|
||||
info!("Hello from a comfy nest we've made ourselves!");
|
||||
|
||||
let client = Client::new();
|
||||
//let url = "https://fasterthanli.me";
|
||||
//let res = client.get(url).send().await?.error_for_status()?;
|
||||
//info!(%url, content_type = ?res.headers().get("content-type"), "Got a response!");
|
||||
|
||||
fetch_thing(&client, URL_1).await?;
|
||||
fetch_thing(&client, URL_2).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn setup() -> Result<(), Report> {
|
||||
if std::env::var("RUST_LIB_BACKTRACE").is_err() {
|
||||
std::env::set_var("RUST_LIB_BACKTRACE", "1")
|
||||
}
|
||||
color_eyre::install()?;
|
||||
|
||||
if std::env::var("RUST_LOG").is_err() {
|
||||
std::env::set_var("RUST_LOG", "info")
|
||||
}
|
||||
tracing_subscriber::fmt::fmt()
|
||||
.with_env_filter(EnvFilter::from_default_env())
|
||||
.init();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn fetch_thing(client: &Client, url: &str) -> Result<(), Report> {
|
||||
let res = client.get(url).send().await?.error_for_status()?;
|
||||
info!(%url, content_type = ?res.headers().get("content-type"), "Got a response!");
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user