Rust rules
Rules I adhere by when writing rust code.
Results vs Options
- Use options where there is no context to be given. A failure in an external command, for example, is not an Option. There's almost always context behind the failure.
- Don't try to be fault tolerant, especially when you have a lot of possible input space and not a lot of output space. It is bound to fail. Fail hard and fail fast. Similar response also goes for running external commands and parsing their output.
- Parse, don't validate.
- Use errors and results to propagate error message contexts.
- Make sure that any error message is good enough to be propagated
upwards as is, unless it's supposed to be a generic function that
just fails on failure. Examples include supac's
run_commandandrun_command_for_stdoutfunctions. These preferably need more specific contexts on what's happening.- The above is true usually when the function is being exported for regular use and does something where the arguments are the principal focus for the side effect being done.
- Prefer using
Errover logging. Only prefer logging if there's scope of recovery/possibility of a default value to be used. Use debug logging for things in gen. - Fail hard and fail fast, even for optional parsing. What's ill-configured is ill-configured.
Custom Error types
- Prefer custom error types to generic libraries like anyhow and color-eyre.
- This does two things: reduce deps, and, give more context to the error messages.
Prefer
mod.rs over <module>.rs for modules
with associated dirs
- Allows to contain everything in a single directory.
- Doesn't give the false impression that the file is self-contained.
Prefer
to only have pub module imports in mod.rs,
lib.rs etc
- Do not hide functionality there.
Function/Struct declaration order
- pub functions first.
- Main struct first, then its impl block, then the substructs, then their impl blocks, and so on.
- pub methods first.
- BFS style. Based on earliest usage.
Logging principles
- Use an INFO log to show major checkpoints in events, like "fully parsed the config" and "installed all extra packages".
- Use DEBUG for minor stuff, but don't rely too much on it.
- Use WARN when it deviates from the norm, but is recoverable.
- I personally never use ERROR, I just propagate the message upwards.