| name | writing-rust-topcat |
| description | Guides writing Rust code in Topcat following project conventions for modules, error handling, documentation, and idioms. Use when implementing new features, adding modules, or refactoring existing code. |
Writing Rust in Topcat
Quick Reference
Module Visibility
pub mod analysis;
pub mod file_dag;
mod io_utils;
mod stable_topo;
pub fn build_graph(&mut self) -> Result<(), TopCatError> { }
fn get_file_headers(path: &PathBuf, comment_str: &str) -> Vec<String> { }
Error Handling Pattern
pub fn validate(&self) -> Result<(), TopCatError> {
if self.name.is_empty() {
return Err(TopCatError::InvalidFileHeader(
self.path.clone(),
"Name cannot be empty".to_string(),
));
}
Ok(())
}
match result {
Ok(node) => nodes.push(node),
Err(FileNodeError::NoNameDefined(p)) => {
info!("Ignoring {p:?}: No name defined");
continue;
}
Err(e) => return Err(e.into()),
}
Struct Pattern
#[derive(Debug, Clone)]
pub struct FileNode {
pub name: String,
pub path: PathBuf,
deps: HashSet<String>,
}
impl FileNode {
pub fn new(name: String, path: PathBuf) -> Self {
Self {
name,
path,
deps: HashSet::new(),
}
}
}
Documentation Standard
pub fn build_graph(&mut self) -> Result<(), TopCatError> {
}
Logging Levels
use log::{debug, info, trace, error};
info!("Building dependency graph from {} files", count);
debug!("Processing file: {:?}", path);
trace!("Dependency edge: {} -> {}", from, to);
error!("Failed to read file: {}", err);
Common Patterns
Trait Implementation Order
impl PartialEq for FileNode {
fn eq(&self, other: &Self) -> bool { self.name == other.name }
}
impl Eq for FileNode {}
impl PartialOrd for FileNode { }
impl Ord for FileNode { }
impl Hash for FileNode { }
impl Display for FileNode { }
Iterator Chains
let mut deps: Vec<_> = file_node.deps.iter().collect();
deps.sort();
for dep in deps {
}
nodes
.iter()
.filter(|n| n.layer == "normal")
.map(|n| n.name.clone())
.collect()
Collections Usage
Vec<T> - ordered sequences
HashMap<K, V> - key-value lookups
HashSet<T> - unique membership
VecDeque<T> - queue operations
Checklist for New Code
- [ ] Add rustdoc comments for public items
- [ ] Use Result<T, TopCatError> for fallible operations
- [ ] Derive Debug, Clone for structs (add others as needed)
- [ ] Add logging at appropriate levels
- [ ] Handle errors explicitly (no unwrap in production code)
- [ ] Use meaningful variable names
- [ ] Sort collections when deterministic order required
- [ ] Add unit tests for complex logic
- [ ] Validate inputs early (fail fast)
Reference Documentation
Module Architecture: See reference/modules.md
Error Handling: See reference/error-handling.md
Trait Patterns: See reference/traits.md
Common Idioms: See reference/idioms.md
Quick Tips
- Config structs use lifetimes to borrow instead of clone
- FileSystem trait for testable I/O code
- Match expressions preferred over if-let chains
- String handling: Use
trim(), to_string(), to_lowercase() consistently
- Path handling: Use
PathBuf for owned, &Path for borrowed
- Builder pattern: Implement
new() constructors with sensible defaults