🎓 A1Learner
🔍

Rust API Naming

Rust API naming is a shared set of habits for naming types, methods and values. A method then feels familiar even in a crate met for the first time.

Acronyms count as one word

Inside a type name, an acronym is written like an ordinary word, not in all capitals.

struct Uuid(u64);        // not UUID
struct HttpServer;      // not HTTPServer

Getters drop the get_

A method that simply hands back a field is named after the field itself. get_ survives only where exactly one obvious thing is gotten, like Cell::get.

impl Song {
    fn title(&self) -> &str { &self.title }              // not get_title
    fn title_mut(&mut self) -> &mut String { &mut self.title }
}

Conversions: as_, to_, into_

The prefix advertises the cost and the ownership before you read any code.

let view = text.as_bytes();       // as_: free, borrowed in, borrowed out
let loud = text.to_uppercase();   // to_: does real work, builds a new value
let raw = text.into_bytes();      // into_: takes ownership of text

Iterators come in threes

A collection offers the same three names, and the return types match them: Iter, IterMut, IntoIter.

fn iter(&self) -> Iter            // hands out &Item
fn iter_mut(&mut self) -> IterMut // hands out &mut Item
fn into_iter(self) -> IntoIter    // hands out Item, consumes the collection

Feature names: no filler words

A feature is named after what it switches on.

// Cargo.toml
[features]
std = []          // named std — never use-std or with-std

Example

struct Song {
    title: String,
    seconds: u32,
}
impl Song {
    fn new(title: &str, seconds: u32) -> Song {
        Song { title: title.to_string(), seconds }
    }
    fn title(&self) -> &str {
        &self.title
    }
    fn to_label(&self) -> String {
        format!("{} ({}:{:02})", self.title, self.seconds / 60, self.seconds % 60)
    }
    fn into_title(self) -> String {
        self.title
    }
}
fn main() {
    let song = Song::new("Blue Sky", 185);
    println!("title = {}", song.title());
    println!("label = {}", song.to_label());
    println!("owned = {}", song.into_title());
}

Key points

  • Code gets read more often than it gets written.
  • Names are the first thing a reader meets.
  • Naming habits are one shared vocabulary: the same name means the same thing in every crate.
  • Types and traits are UpperCamelCase, values and functions are snake_case, constants are SCREAMING_SNAKE_CASE
  • A wrapper type that hides one value offers into_inner() when a caller needs the value back
  • Name crate packages without -rs or -rust suffixes: every crate here is Rust
  • Keep one word order everywhere in a crate: if you say load_config, the sibling is save_config, never config_save
  • They are reading habits, not syntax — the compiler will not save a reader from a surprising name.
  • The habits are written down in the Rust API Guidelines.

In this example, Song follows the naming habits end to end. title() is a plain getter, so it carries no get_ prefix. to_label() does real work — formatting the length as 3:05 — and builds a fresh String, so it earns the to_ prefix. into_title() consumes the song with self and hands back the owned String inside, so it is into_. Even the arithmetic reads predictably: 185 seconds is 3 minutes and 5 leftover seconds. A reader who has never seen Song can guess every call before reading the impl.

Note

Clippy and rustfmt cannot check most of these habits.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

A method borrows a value and returns a borrowed view of it, doing no real work. Which prefix fits it?