How to read Rust code — Display trait and macro
What happened?

What happened?
Today, while messing around with stuffs, i came across a very weird thing in Rust, so i decided to dig in a little bit to see what’s the magic behind this. Let’s get started.
A look
In the code above, the function pid
returns the struct Pid
. The thing is, when put the id
in the println!
i get 8016
which is really weird since the Pid
struct is not an i32
or any number type.

Let’s go to the implementation of the struct to see what kind of magic is this :))

Oh no, it’s defined in a macro. As you might know, macro is something magic and evil at the same time for beginner. Panic not, we are gonna have just a sneak peek into it and no deep dive, i promise ✋
First, what is the cfg_if::cfg_if
! right there?
It has a !
, then it must be a macro, right? After a while looking up, i found it on crates.io, just a crate to support if else condition base on a bunch of configuration. 😌

Why do we need it? have a look at the code below:

If you try to run this code, the compiler will scream like a lil kid. cfg_if with it’s magic macro came to the rescue and makes the code compile.
What is the if and the condition here?

What is this? have a look at Conditional compilation here.
The most outer predicate is all(), it means every predicate inside the all() must be true
The not() here tells us that the feature “unknow-ci” must not be enabled
the any() tells us that if the code is ran in any target os here the condition will be true
In conclusion, we can translate the condition like this:
If the feature “unknown-ci” is not enabled and target is one of these (“freebsd”, “linux”, “android”, “macos”, “ios”), the code in this block will run.
I run my code on Windows &Linux, so what?

It has only 2 lines of code. 1 line for using and another line is a macro call.
According to the docs here,libc - Raw FFI bindings to platforms’ system libraries.
The platform here is Windows, Linux or whatever the system you are using. They have API exposed for us to use in our code. Unfortunately, all of them are written in C or C++. If we want to use it in Rust, we must do a FFI (foreign function interface) to bind from C, C++ to Rust.
The pid_t
here is just a type alias for i32
: pub type pid_t = i32;
which means this statement pid_decl!(pid_t)
here can be translated like thispid_decl!(i32)
Let’s have a look at pid_decl!
First, if you want to use {} inside the println! macro, the type must implement Display trait.
When implementing the Display
method, you need to explicitly describe how you want to display the struct and that’s what we are gonna look into.
Fortunately, the code in this macro is long but not complicated. Since the code inside the macro is long, i will only cut off the part we need (Display
trait implementation)

The method just prints out the self.0
Let’s have a look at the Struct declaration in the macro as well.

The struct Pid
has one property with type $typ
which is the parameter for the macro in the above section (i32
). We can translate the code like this
pub struct Pid(i32);
Now, self.0
should return an i32
, which is the 8016
in my example.
Conclusion
Rust prefer explication to implication but sometimes you find the complex of the code makes everything implicit. I think the lesson we learnt today is: Keep your code explicit and embrace the KISS principle.