Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.toml must contain entries in the form <crate-name> = { version = "X.Y", default-features = false}.
  • The members Cargo.toml must 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.toml while 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-trivial TODO should have their associated issue indicated in parenthesis (e.g TODO(#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 a FIXME like 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.