My Rust journey: Attributes

On this Blog, I begin to narrate my experience and what I think it is important in some Rust learning topics. I also have some others topics to write here, so, I have to choose the Attribute to begin.

What is Attributes?

"An attribute is metadata applied to some module, crate or item." Of course, this isn't to explain much about what is it, but it is a good beginning. Let me tray to define what is metadata. According to Wikipedia, metadata is "data that provides information about other data", in others words, in Rust programming context, it can be related to functions, crates, compiler, tests and so on. To be more specific, this is a list of where Rust attributes can be used.

  • conditional compilation of code
  • set crate name, version and type (binary or library)
  • disable lints (warnings)
  • enable compiler features (macros, glob imports, etc.)
  • link to a foreign library
  • mark functions as unit tests
  • mark functions that will be part of a benchmark

As I like too many examples, here it comes one. This is a code snippet from Actix, a rust web framework.

use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};

#[get("/")] // This is a Actix a Attribute to work with http get request
async fn hello() -> impl Responder {
    HttpResponse::Ok().body("Hello world!")
}

#[post("/echo")] // This one to post request
async fn echo(req_body: String) -> impl Responder {
    HttpResponse::Ok().body(req_body)
}

async fn manual_hello() -> impl Responder {
    HttpResponse::Ok().body("Hey there!")
}

Rust has two types of Attributes: "local" and "global". A "local"(InnerAttribute) Attribute is setted to a module or item, what happens in this Actix code snippet, and a "global", setted to a whole crate or inside a block. Builded-in Rust has some Attributes what can be used to define configurations, stop warning and other, as said above. Between this built-in Attributes are:

#![crate_name = "mylib"]
#![crate_type = "lib"]

Those two are "global"(OuterAttribute) and concerned to give a name and a type to a crate, even thought both there aren't many uses in real life because of Cargo what define this in a right place.

The form of both are similar, they begin with #, has square brackets [] and some data, but it needs to be specified.

InnerAttribute or "local" :

# ! [ att ]

OuterAttribute or "global":

# [ att ]

Where att can be:

  • attribute = "value"
  • attribute(key = "value")
  • attribute(key = "value", key2 = "value2")
  • attribute(value, value2, value3)
  • ...

Another good example can be to compile code to afford the OS who is building the source. The example below is direct from Rust by Example

// This function only gets compiled if the target OS is linux
#[cfg(target_os = "linux")]
fn are_you_on_linux() {
    println!("You are running linux!");
}

// And this function only gets compiled if the target OS is *not* linux
#[cfg(not(target_os = "linux"))]
fn are_you_on_linux() {
    println!("You are *not* running linux!");
}

This time here was used the #cfg[...] and the key target_os to choose the platform, However, it is possible to write custom attributes passing they to the compiler rustc through the --cfg flag or passing them directly to the compiler, setting RUSTFLAGS environment variable with your flags.

Another example from Rust by Example

#[cfg(some_condition)]
fn conditional_function() {
    println!("condition met!");
}

fn main() {
    conditional_function();
}
rustc --cfg some_condition custom.rs && ./custom
condition met!

or setting the environmental variable:

RUSTFLAGS="--cfg some_condition"

My Blog was a try to simplify this Rust subject and became this more affordable for my and other learners. There are much more build-in Attributes in rust which is worth to search and learn your use cases, so feel free to goes to the documentation or free online books available.

This topic is one of the most different that I found in Rust referring others programming languages, although C has some like it. I'm planing writing about that differences I found in my Rust learning journey like traits, macros and others.

Thank you for reading and I hope this helped you in some way.

No Comments Yet