Rust style guidelines
Ensure the entire codebase adheres to the guidelines below. There should be no exceptions to these guidelines, failure to enforce them will result in a failed review.
Do not use emojis and avoid excessive comments. Write self-explanatory code instead.
Do not use decorations around println, etc.
Consistentently name types and methods.
Provide accessors and mutators for struct fields, avoid pub fields. E.g., for a field named timeout, provide:
fn timeout(&self) -> ... { ... }
fn set_timeout(&mut self, to: ...) { ... }
Use fluent style method names.
Organise imports in the following order: 1) standard library imports, 2) external library imports next, 3) same crate imports next. Use appropriate whitespace to separate groups of related imports.
Do not nest modules in imports--DO NOT do this: use module1::blah::{module2::bleep::Type, module3::Bleh}.
CORRECT:
use module1::blah::module2::bleep::Type;
use module1::blah::module3::Bleh;
CORRECT:
use std::collections::{HashMap, HashSet};
use std::path::{Path, PathBuf};
use serde::Serialize;
use tokio::fs;
use crate::models::DataModel;
use crate::utils::helper;
INCORRECT:
rust use std::{collections::{HashMap, HashSet}, path::{Path, PathBuf}};
INCORRECT:
rust use std::collections::HashMap; use std::collections::HashSet;
For module layout, use mod.rs and directories when a module may have sub-modules or module_name.rs for leaf modules. Do not use new-style module paths.
Handle errors, DO NOT silently ignore them without good reason.
For error messages, always use lower-case unless you have a proper noun or acronym at the start of the string, i.e., prefer “component not found: reason” over “Component not found: Reason”, but keep "I/O error: reason" and "HTTP error: reason".
Make use of “borrowed” types rather than owned variants if possible:
- Prefer
impl AsRef<Borrowed> vs &Owned or impl AsRef<Owned> unless the owned variant is really needed.
- Prefer
impl AsRef<str> or &str over &String
- Prefer
impl AsRef<[u8]> or &[u8] over &Vec<u8>
- Prefer
impl AsRef<Path> or &Path over &PathBuf
Prefer to use methods that indicate intent: avoid usage of to_string on &str and opt for to_owned or String::from instead.
Avoid useless imports, e.g, use log;; this is superfluous, since log will already be in scope if you have log as a dependency.
For collections, prefer Vec::new() over vec![] for empty vectors.
When using Option and Result, prefer the ? operator for propagating errors and unwrapping values instead of using .unwrap() or .expect().
Do not annotate types via their let bindings, ALWAYS use turbo-fish syntax or rely on type inference. For example, use:
let value = Vec::<u8>::new();
or
let value = Vec::new();
over
let value: Vec<u8> = Vec::new();
When formatting to build strings, log, or to print to the console, ensure you format as below:
let name = "Alice";
let greeting = format!("Hello, {name}!");
println!("Hello, {name}!");
DO NOT:
let name = "Alice";
let greeting = format!("Hello, {}!", name);
println!("Hello, {}!", name);
DO NOT call FFI functions in methods that operate on an IDB or derived types without binding the owning type to the lifetime of the IDB. For exmaple:
pub struct MyStruct<'a> {
_marker: PhantomData<&'a IDB>,
}
- Use the following tools to help enforce these guidelines:
cargo fmt -- --config imports_granularity=Module,group_imports=StdExternalCrate to format your code.
cargo clippy --no-deps to lint your code and cargo clippy --fix to automatically fix issues where possible.
cargo dylint --git https://github.com/xorpse/rust-style --pattern '*' to run the custom lints for this project. If dylint does not run correctly, ensure it is installed: cargo install cargo-dylint dylint-link.
1---2name: idalib-rust-style3description: Best practices for contributing to IDALIB Rust bindings4---56# Rust style guidelines78Ensure the entire codebase adheres to the guidelines below. There should be no exceptions to these guidelines, failure to enforce them will result in a failed review.910<guidelines>11Follow these instructions strictly to ensure high-quality Rust code:1213- Do not use emojis and avoid excessive comments. Write self-explanatory code instead.1415- Do not use decorations around println, etc.1617- Consistentently name types and methods.1819- Provide accessors and mutators for struct fields, avoid `pub` fields. E.g., for a field named `timeout`, provide:20 ```rust21 fn timeout(&self) -> ... { ... }22 fn set_timeout(&mut self, to: ...) { ... }2324- Use fluent style method names.2526- Organise imports in the following order: 1) standard library imports, 2) external library imports next, 3) same crate imports next. Use appropriate whitespace to separate groups of related imports. 2728- Do not nest modules in imports--DO NOT do this: `use module1::blah::{module2::bleep::Type, module3::Bleh}`.2930CORRECT:31 ```rust32 use module1::blah::module2::bleep::Type;33 use module1::blah::module3::Bleh;34 ```3536CORRECT:37 ```rust38 use std::collections::{HashMap, HashSet};39 use std::path::{Path, PathBuf};4041 use serde::Serialize;42 use tokio::fs;4344 use crate::models::DataModel;45 use crate::utils::helper;46 ```4748INCORRECT:49 ```rust50 use std::{collections::{HashMap, HashSet}, path::{Path, PathBuf}};51 ```5253INCORRECT:54 ```rust55 use std::collections::HashMap;56 use std::collections::HashSet;57 ```5859- For module layout, use mod.rs and directories when a module may have sub-modules or module_name.rs for leaf modules. Do not use new-style module paths.6061- Handle errors, DO NOT silently ignore them without good reason.6263- For error messages, always use lower-case unless you have a proper noun or acronym at the start of the string, i.e., prefer “component not found: reason” over “Component not found: Reason”, but keep "I/O error: reason" and "HTTP error: reason".6465- Make use of “borrowed” types rather than owned variants if possible:66 - Prefer `impl AsRef<Borrowed>` vs `&Owned` or `impl AsRef<Owned>` unless the owned variant is really needed.67 - Prefer `impl AsRef<str>` or `&str` over `&String`68 - Prefer `impl AsRef<[u8]>` or `&[u8]` over `&Vec<u8>`69 - Prefer `impl AsRef<Path>` or `&Path` over `&PathBuf`7071- Prefer to use methods that indicate intent: avoid usage of `to_string` on ``&str`` and opt for `to_owned` or `String::from` instead.7273- Avoid useless imports, e.g, `use log;`; this is superfluous, since `log` will already be in scope if you have `log` as a dependency.7475- For collections, prefer `Vec::new()` over `vec![]` for empty vectors.7677- When using `Option` and `Result`, prefer the `?` operator for propagating errors and unwrapping values instead of using `.unwrap()` or `.expect()`.7879- Do not annotate types via their let bindings, ALWAYS use turbo-fish syntax or rely on type inference. For example, use:80 ```rust81 let value = Vec::<u8>::new();82 ```83 or84 ```rust85 let value = Vec::new();86 ```87 over88 ```rust89 let value: Vec<u8> = Vec::new();90 ```9192- When formatting to build strings, log, or to print to the console, ensure you format as below:9394 ```rust95 let name = "Alice";96 let greeting = format!("Hello, {name}!");97 println!("Hello, {name}!");98 ```99100 DO NOT:101102 ```rust103 let name = "Alice";104 let greeting = format!("Hello, {}!", name);105 println!("Hello, {}!", name);106 ```107108- DO NOT call FFI functions in methods that operate on an IDB or derived types without binding the owning type to the lifetime of the IDB. For exmaple:109110```rust111pub struct MyStruct<'a> {112 _marker: PhantomData<&'a IDB>,113}114```115116- Use the following tools to help enforce these guidelines:117 - `cargo fmt -- --config imports_granularity=Module,group_imports=StdExternalCrate` to format your code.118 - `cargo clippy --no-deps` to lint your code and `cargo clippy --fix` to automatically fix issues where possible.119 - `cargo dylint --git https://github.com/xorpse/rust-style --pattern '*'` to run the custom lints for this project. If `dylint` does not run correctly, ensure it is installed: `cargo install cargo-dylint dylint-link`.120121</guidelines>