Skip to content

Commit 6d9b545

Browse files
committed
Move algorithms/randomness to crates
This takes a slightly different approach to the way that the web crate works by moving all rust code to proper rust files and checking if the code compiles in CI.
1 parent 408e7bf commit 6d9b545

File tree

17 files changed

+192
-166
lines changed

17 files changed

+192
-166
lines changed

.github/workflows/mdbook-test.yml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- name: Set up Rust
1717
uses: actions-rust-lang/setup-rust-toolchain@v1
1818
with:
19-
cache: 'true'
19+
cache: "true"
2020
toolchain: stable
2121

2222
- name: Run tests
@@ -33,3 +33,20 @@ jobs:
3333
echo "❌ Some tests failed. Check the logs above for details."
3434
exit 1
3535
fi
36+
check-workspace:
37+
# this job incrementally replaces the skeptic tests above as we convert examples to be written
38+
# as workspace crates rather than inline in the mdbook
39+
runs-on: ubuntu-latest
40+
steps:
41+
- uses: actions/checkout@v5
42+
- uses: actions-rust-lang/setup-rust-toolchain@v1
43+
- run: cargo check --workspace
44+
- name: Check Results
45+
if: always()
46+
run: |
47+
if [ ${{ steps.cargo_check.outcome }} == 'success' ]; then
48+
echo "✅ Workspace check passed!"
49+
else
50+
echo "❌ Workspace check failed. Check the logs above for details."
51+
exit 1
52+
fi

Cargo.toml

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,35 @@
1+
[workspace]
2+
members = ["crates/algorithms/*", "crates/web"]
3+
4+
[workspace.package]
5+
edition = "2024"
6+
version = "1.1.0"
7+
authors = ["Brian Anderson <[email protected]>", "Andrew Gauger <[email protected]>"]
8+
license = "MIT OR Apache-2.0"
9+
publish = false
10+
111
[package]
212
name = "rust-cookbook"
313
version = "1.1.0"
414
authors = ["Brian Anderson <[email protected]>", "Andrew Gauger <[email protected]>"]
515
edition = "2018"
6-
license = "MIT/Apache-2.0"
16+
license = "MIT OR Apache-2.0"
717
publish = false
818
build = "build.rs"
919

1020
[features]
1121
default = []
12-
test-rand = []
1322

23+
[workspace.dependencies]
24+
rand = "0.9"
25+
rand_distr = "0.5"
26+
27+
# NOTE: These dependencies add dependencies to the rust playground (play.rust-lang.org).
28+
# Be wary removing or changing these without considering this fact.
29+
# See https://github.com/rust-lang/rust-playground/blob/f8d7de52a3c139a0df4fe116bbbff19c30668c99/top-crates/src/lib.rs#L134-L161
1430
[dependencies]
1531
ansi_term = "0.11.0"
32+
anyhow = "1.0"
1633
approx = "0.3"
1734
base64 = "0.22.1"
1835
bitflags = "1.3.2"
@@ -28,7 +45,6 @@ env_logger = "0.11.3"
2845
flate2 = "1.0"
2946
glob = "0.3"
3047
image = "0.24"
31-
3248
lazy_static = "1.0"
3349
log = "0.4"
3450
log4rs = "0.8"
@@ -50,7 +66,6 @@ ring = "0.17"
5066
rusqlite = { version = "0.32", features = ["chrono"] }
5167
same-file = "1.0"
5268
select = "0.6.0"
53-
5469
semver = "1.0"
5570
serde = { version = "1.0", features = ["derive"] }
5671
serde_derive = "1.0"
@@ -59,10 +74,9 @@ sha2 = "0.10"
5974
tar = "0.4"
6075
tempfile = "3.14"
6176
thiserror = "2"
62-
anyhow = "1.0"
6377
threadpool = "1.8"
64-
toml = "0.8"
6578
tokio = { version = "1", features = ["full"] }
79+
toml = "0.8"
6680
unicode-segmentation = "1.2.1"
6781
url = "2.5"
6882
walkdir = "2.5"

build.rs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,17 @@ const REMOVED_TESTS: &[&str] = &[
55
"./src/web/clients/api/rate-limited.md",
66
];
77

8-
fn main() {
9-
#[cfg(feature = "test-rand")]
10-
{
11-
let rand_paths = vec![
12-
"./src/algorithms/randomness/rand.md",
13-
"./src/algorithms/randomness/rand-range.md",
14-
"./src/algorithms/randomness/rand-dist.md",
15-
"./src/algorithms/randomness/rand-custom.md",
16-
"./src/algorithms/randomness/rand-passwd.md",
17-
"./src/algorithms/randomness/rand-choose.md",
18-
];
19-
skeptic::generate_doc_tests(&rand_paths[..]);
20-
return;
21-
}
8+
const REMOVED_PREFIXES: &[&str] = &["./src/algorithms/randomness/"];
229

23-
let paths = WalkDir::new("./src/").into_iter()
10+
fn main() {
11+
let paths = WalkDir::new("./src/")
12+
.into_iter()
2413
// convert paths to Strings
2514
.map(|p| p.unwrap().path().to_str().unwrap().to_string())
2615
// only compile markdown files
2716
.filter(|p| p.ends_with(".md"))
2817
.filter(|p| !REMOVED_TESTS.contains(&p.as_ref()))
18+
.filter(|p| !REMOVED_PREFIXES.iter().any(|prefix| p.starts_with(prefix)))
2919
.collect::<Vec<_>>();
3020

3121
skeptic::generate_doc_tests(&paths[..]);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "randomness"
3+
version.workspace = true
4+
authors.workspace = true
5+
edition.workspace = true
6+
license.workspace = true
7+
publish.workspace = true
8+
9+
[dependencies]
10+
rand.workspace = true
11+
rand_distr.workspace = true
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use rand::Rng;
2+
3+
const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
4+
abcdefghijklmnopqrstuvwxyz\
5+
0123456789)(*&^%$#@!~";
6+
const PASSWORD_LEN: usize = 30;
7+
8+
fn main() {
9+
let mut rng = rand::rng();
10+
11+
let password: String = (0..PASSWORD_LEN)
12+
.map(|_| {
13+
let idx = rng.random_range(0..CHARSET.len());
14+
char::from(CHARSET[idx])
15+
})
16+
.collect();
17+
18+
println!("{password}");
19+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#![allow(dead_code)]
2+
use rand::Rng;
3+
4+
#[derive(Debug)]
5+
struct Point {
6+
x: i32,
7+
y: i32,
8+
}
9+
10+
impl Point {
11+
fn random<R: Rng>(rng: &mut R) -> Self {
12+
Point {
13+
x: rng.random(),
14+
y: rng.random(),
15+
}
16+
}
17+
}
18+
19+
fn main() {
20+
let mut rng = rand::rng();
21+
let rand_tuple = rng.random::<(i32, bool, f64)>();
22+
let rand_point = Point::random(&mut rng);
23+
println!("Random tuple: {:?}", rand_tuple);
24+
println!("Random Point: {:?}", rand_point);
25+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use rand_distr::{Distribution, LogNormal, Normal};
2+
3+
fn main() {
4+
let mut rng = rand::rng();
5+
let normal = Normal::new(2.0, 3.0).expect("Failed to create normal distribution");
6+
let log_normal = LogNormal::new(1.0, 0.5).expect("Failed to create log-normal distribution");
7+
8+
let v = normal.sample(&mut rng);
9+
println!("{} is from a N(2, 9) distribution", v);
10+
let v = log_normal.sample(&mut rng);
11+
println!("{} is from an ln N(1, 0.25) distribution", v);
12+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use rand::Rng;
2+
use rand_distr::Alphanumeric;
3+
4+
fn main() {
5+
const PASSWORD_LEN: usize = 30;
6+
let mut rng = rand::rng();
7+
8+
let password: String = (0..PASSWORD_LEN)
9+
.map(|_| rng.sample(Alphanumeric) as char)
10+
.collect();
11+
12+
println!("{password}");
13+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
use rand::Rng;
2+
3+
fn main() {
4+
let mut rng = rand::rng();
5+
let random_number: u32 = rng.random();
6+
println!("Random number: {random_number}");
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
use rand::Rng;
2+
3+
fn main() {
4+
let mut rng = rand::rng();
5+
println!("Integer: {}", rng.random_range(0..10));
6+
println!("Float: {}", rng.random_range(0.0..10.0));
7+
}

0 commit comments

Comments
 (0)