Coding Style
Centralized Crates Versions
All dependency crate versions are declared in the root Cargo.toml. Member crates should declare
any required features in their own Cargo.toml files.
In practice, it means that:
- The root
Cargo.tomlmust contain entries in the form<crate-name> = { version = "X.Y", default-features = false}. - The members
Cargo.tomlmust contain entries in the form<crate-name> = { workspace = true, features = [<features>] }.
Note
Some crates will not compile without a minimum set of features declared. In that case, only enable these features in the root
Cargo.tomlwhile still disabling the default ones (e.g<crate-name> = { version = "x.y.z", default-features = false, features = [<mandatory-features>] }).
Additionally, patch versions are omitted from version declarations (e.g. 1.0 instead of 1.0.5).
API Endpoint Function Signatures
We generally follow the same template for our API endpoints, to make the code easier to navigate.
Here is the template to apply for any handler:
/// Handler for `<METHOD> <ENDPOINT>` (See <URL>).
///
/// Optional: Additional description.
///
/// Optional: Notes,warnings, precisions if needed.
async fn ENDPOINT_handler(
RumaRequest(create_tag_request): RumaRequest<ENDPOINT::Request>,
) -> Result<ArminiusResponse<ENDPOINT::Response>, InternalServerError> {
An example:
/// Handler for `PUT /_matrix/client/v3/user/{userId}/rooms/{roomId}/tags/{tag}`
/// (See <https://spec.matrix.org/latest/client-server-api/#put_matrixclientv3useruseridroomsroomidtagstag>).
///
/// This endpoint is used to add user tags to rooms.
///
/// Warning: The name of a tag MUST NOT exceed 255 bytes.
async fn create_tag_handler(
database: State<DefaultDb>,
AuthenticatedClaims(claims): AuthenticatedClaims,
RumaRequest(create_tag_request): RumaRequest<tag::create_tag::v3::Request>,
) -> Result<ArminiusResponse<tag::create_tag::v3::Response>, AddTagError> {
Working with Time
If you can, use std::time::Instant. For instance, if you’re just measuring time passing inside of a process, this is the way to go, because this API is robust against clock jumps, and generally faster than SystemTime or calendar time.
If you need to store time somewhere else, you should use chrono. time is not allowed in this project, since we already have chrono. This is also checked by forbidden_deps.sh. See the Database Architecture docs for conventions on storing timestamps in PostgreSQL.
FIXMEs and TODOs
The three following syntaxes are supported.
TODO: <reason>: These indicate areas where the current code works correctly but could be optimized, refactored or improved. Every non-trivialTODOshould have their associated issue indicated in parenthesis (e.gTODO(#123): Add cross-signing keys to the response.).FIXME(#<issue>): <reason>: These indicate something that is wrong, incorrect, incomplete and must be fixed before reaching a production ready codebase. All of these must mention a corresponding existing issue.FIXME(PR): <reason>: These help clarify topics that needs to be addressed before being able to merge the Pull Request. They can be used to ask questions to reviewers, or simply be used as reminders for the developer.
Tip
This section is about comments, not the Rust built-in
todo!()macro. If you use such macro, it should therefore be preceded by aFIXMElike so:fn x_squared(x: usize) -> usize { // FIXME(#123): Implement the rest of this function. todo!() }
Module Documentation
Rust supports two kinds of documentation for modules:
/// Below is a module which produces foos
mod foo_producer {
fn produce_foo() {
}
}
and
mod foo_producer {
//! This module produces foos
fn produce_foo() {
}
}
This project prefers the second module-internal documentation style, and for consistency this is enforced by a rule with ast-grep.