Let's assume your C SDK defines MY_GPIO as a pointer to a volatile memory mapped I/O register. Lets further assume that your project uses interrupts (or preemptive multitasking).
Your trivial one-liner is an example of terribly seductive simplicity enabled by a broken design. It works until MY_GPIO is concurrently modified. Which can happen if the memory mapped peripheral changes the register content on its own or if other code can preempt read/modify/write sequence. To make it worse unless MY_GPIO is heavily contested it will work most of the time.
I'm not familiar with embedded Rust, but it looks like APIs are designed to make the programmer explicitly lay claim hardware peripheral (or fail trying) instead of corrupting the system state. Most of the unwrap() and unsafe code is executed once during setup. Once the hardware resources are divided up and configured the normal runtime code should be a lot less verbose (from a quick look at the API documentation).
The rust version includes reference counting, state verification (preventing access before initialisation) and locking. All "for free" by wrapping the original value.
In C you would have to write all that out. And still have a good chance of getting something wrong first try.
Not the OP, but I do not like reading one line expression bonanzas. I would rather read implementations of different subsystems and then calling them.
I mean, I find this simpler
procedure x_component
..
end
procedure y_component
..
end
procedure assembly
x_component
y_component
..
end
In python, rust, C++, java, lisp people seem to form very long procedures with lambdas and some ninja fu to save lines of code and it may look elegant to some people, but I can't read it.
Pretty much. The issue is that the C version is horribly error prone and unsafe. Any time you lose by writing a load of `borrow()`s you will get back 100 times over by not having to debug races on a microcontroller!