ed25519_fast_sv_docs/
lib.rs1#![doc = include_str!("../docs/index.md")]
2#![forbid(unsafe_code)]
3
4#[doc = include_str!("../docs/reading_systemverilog.md")]
6pub mod reading_systemverilog {}
7
8#[doc = include_str!("../docs/overview.md")]
10pub mod overview {}
11
12#[doc = include_str!("../docs/field.md")]
14pub mod field {}
15
16#[doc = include_str!("../docs/sha512.md")]
18pub mod sha512 {}
19
20#[doc = include_str!("../docs/scalar.md")]
22pub mod scalar {}
23
24#[doc = include_str!("../docs/fixed_base.md")]
26pub mod fixed_base {}
27
28#[doc = include_str!("../docs/point_codec.md")]
30pub mod point_codec {}
31
32#[doc = include_str!("../docs/signing_core.md")]
34pub mod signing_core {}
35
36#[doc = include_str!("../docs/shells_and_benchmarks.md")]
38pub mod shells_and_benchmarks {}
39
40#[doc = include_str!("../docs/build_and_verification.md")]
42pub mod build_and_verification {}
43
44#[cfg(test)]
45mod tests {
46 use std::collections::BTreeSet;
47 use std::fs;
48 use std::path::{Path, PathBuf};
49
50 const MANUAL: &str = concat!(
51 include_str!("../docs/index.md"),
52 include_str!("../docs/reading_systemverilog.md"),
53 include_str!("../docs/overview.md"),
54 include_str!("../docs/field.md"),
55 include_str!("../docs/sha512.md"),
56 include_str!("../docs/scalar.md"),
57 include_str!("../docs/fixed_base.md"),
58 include_str!("../docs/point_codec.md"),
59 include_str!("../docs/signing_core.md"),
60 include_str!("../docs/shells_and_benchmarks.md"),
61 include_str!("../docs/build_and_verification.md"),
62 );
63
64 fn repository_root() -> PathBuf {
65 Path::new(env!("CARGO_MANIFEST_DIR"))
66 .join("../..")
67 .canonicalize()
68 .unwrap()
69 }
70
71 fn collect_sv_files(directory: &Path, files: &mut Vec<PathBuf>) {
72 for entry in fs::read_dir(directory).unwrap() {
73 let path = entry.unwrap().path();
74 if path.is_dir() {
75 collect_sv_files(&path, files);
76 } else if path.extension().is_some_and(|extension| extension == "sv") {
77 files.push(path);
78 }
79 }
80 }
81
82 fn fast_sv_files() -> Vec<PathBuf> {
83 let root = repository_root();
84 let mut files = Vec::new();
85 for crate_name in [
86 "rhdl_ed25519_fast_field",
87 "rhdl_ed25519_fast_fixed_base",
88 "rhdl_ed25519_fast_sha512",
89 "rhdl_ed25519_fast_point_codec",
90 "rhdl_ed25519_fast_scalar",
91 "rhdl_ed25519_fast_sign",
92 ] {
93 collect_sv_files(
94 &root.join("crates").join(crate_name).join("rtl"),
95 &mut files,
96 );
97 }
98 for entry in fs::read_dir(root.join("bench/rhdl/rtl")).unwrap() {
99 let path = entry.unwrap().path();
100 if path.extension().is_some_and(|extension| extension == "sv")
101 && path
102 .file_name()
103 .unwrap()
104 .to_string_lossy()
105 .starts_with("fast64_")
106 {
107 files.push(path);
108 }
109 }
110 files.sort();
111 files
112 }
113
114 fn identifier_before_equals(line: &str) -> Option<&str> {
115 let declaration = line.split('=').next()?;
116 declaration.split_whitespace().last()
117 }
118
119 #[test]
120 fn every_fast_sv_source_is_named_in_the_manual() {
121 for path in fast_sv_files() {
122 let file_name = path.file_name().unwrap().to_string_lossy();
123 assert!(
124 MANUAL.contains(&format!("`{file_name}`")),
125 "SystemVerilog source {file_name} is absent from the manual"
126 );
127 }
128 }
129
130 #[test]
131 fn every_module_parameter_and_function_is_named_in_the_manual() {
132 let mut expected = BTreeSet::new();
133 for path in fast_sv_files() {
134 let source = fs::read_to_string(&path).unwrap();
135 for line in source.lines() {
136 let trimmed = line.trim_start();
137 if let Some(rest) = trimmed.strip_prefix("module ") {
138 let name = rest
139 .split(|character: char| {
140 character.is_whitespace() || character == '#' || character == '('
141 })
142 .next()
143 .unwrap();
144 expected.insert(("module", name.to_owned()));
145 } else if trimmed.starts_with("parameter ") {
146 if let Some(name) = identifier_before_equals(trimmed) {
147 expected.insert(("parameter", name.trim_end_matches(',').to_owned()));
148 }
149 } else if let Some(rest) = trimmed.strip_prefix("function automatic ") {
150 let signature = rest.split(';').next().unwrap();
151 let declaration = signature.split('(').next().unwrap();
152 let name = declaration.split_whitespace().last().unwrap();
153 expected.insert(("function", name.to_owned()));
154 }
155 }
156 }
157
158 for (kind, name) in expected {
159 assert!(
160 MANUAL.contains(&format!("`{name}`")),
161 "SystemVerilog {kind} {name} is absent from the manual"
162 );
163 }
164 }
165}