cargo +nightly fmt
- Standard library
- External crates
- Symbols from local crate & parent module
- Local modules definition
- Symbols from local modules (optional)
// Standard library
use std::collections::HashMap;
use std::sync::Arc;
use std::{mem, time};
// External crates
use serde::{Serialize, Deserialize};
use tokio::sync::{oneshot, RwLock};
// Symbols from local crate & parent module
use crate::{common, Node};
use super::Shared;
// Local modules definition
mod config;
mod types;
// Symbols from local modules (optional)
use config::ContextConfig;
use types::BroadcastMessage;
NOT ALLOWED:
use core::{
future::{pending, Future},
pin::Pin,
str,
};
use std::{thread, time::Duration};
ALLOWED:
use core::future::{pending, Future};
use core::pin::Pin;
use core::str;
use std::thread;
use std::time::Duration;
Instead, export modules from files named according to their context.
For example:
crates/meroctl/src/cli/app.rs
Contains:
mod get;
mod install;
mod list;
And we would have these individual files:
crates/meroctl/src/cli/app/get.rs
crates/meroctl/src/cli/app/install.rs
crates/meroctl/src/cli/app/list.rs
use eyre::{Result as EyreResult};
Only introduce them when you have maximum confidence it will NEVER panic, or if it does, it's a fatal error from which we cannot recover and aborting the node is the best thing to do. In this case, introduce a comment stating why
On values that may return errors, use .map_err()
to map the error into the appropriate Error type used in that crate/module
// NOT RECOMMENDED:
if some_condition {
// ... (lots of code)
} else {
return Err(YourError::Something);
}
// RECOMMENDED:
if !some_condition {
return Err(YourError::Something);
}
// Continue with main code path...
When using if let..else
with the consequent block extending beyond just a couple of lines and the alternative effectively bails, prefer the let..else
syntax to reduce indentation.
// NOT RECOMMENDED:
if let Ok(val) = thing {
func(val);
do_ok_1;
do_ok_2;
do_ok_3;
} else {
do_else_1;
return;
}
// RECOMMENDED:
let Ok(val) = thing else {
do_else_1;
return;
};
func(val);
do_ok_1;
do_ok_2;
do_ok_3;
This syntax helps flatten out indentation and keeps short-circuits closer to the condition that triggered them, making code easier to read.
// NOT RECOMMENDED:
std::fs::File::open("data.txt")
// RECOMMENDED:
use std::fs::File;
File::open("data.txt")
- Types shall be
PascalCase
- Enum variants shall be
PascalCase
- Struct fields shall be
snake_case
- Function and method names shall be
snake_case
- Local variables shall be
snake_case
- Macro names shall be
snake_case
- Constants (consts and immutable statics) shall be
SCREAMING_SNAKE_CASE