Rust
Summary - no_std and embedded
Combine no_std, alloc and panic_handler to write an embedded skeleton.
no_std and embedded summary
Layers: core (everywhere), alloc (if there's an allocator), std (if there's an operating system). #![no_std] libraries can be used in any environment; binaries additionally need a #[panic_handler] and an entry point. In the embedded world drivers are written against embedded-hal traits and tested with mock hardware. For WebAssembly, the wasm32 targets and wasm-bindgen. For formatting without a heap, fixed-capacity buffers implementing core::fmt::Write are used.
A fixed-capacity buffer
fmt::Write needs a single method: write_str. Returning an error on a write that doesn't fit reports the overflow safely:
use core::fmt;
struct Tampon {
veri: [u8; 32],
uzunluk: usize,
}
impl fmt::Write for Tampon {
fn write_str(&mut self, s: &str) -> fmt::Result {
let b = s.as_bytes();
let son = self.uzunluk + b.len();
if son > self.veri.len() {
return Err(fmt::Error);
}
self.veri[self.uzunluk..son].copy_from_slice(b);
self.uzunluk = son;
Ok(())
}
}
Exercise Heap-free formatting
Write the Tampon type above and add fn as_str(&self) -> &str (core::str::from_utf8). Write with write!(t, "x={}", 42) and print the text; then try writing a 40-character text and print whether an error was returned, separated by a space.
Show example solution
use core::fmt::{self, Write};
struct Tampon {
veri: [u8; 32],
uzunluk: usize,
}
impl Tampon {
fn as_str(&self) -> &str {
core::str::from_utf8(&self.veri[..self.uzunluk]).unwrap_or("")
}
}
impl fmt::Write for Tampon {
fn write_str(&mut self, s: &str) -> fmt::Result {
let b = s.as_bytes();
let son = self.uzunluk + b.len();
if son > self.veri.len() {
return Err(fmt::Error);
}
self.veri[self.uzunluk..son].copy_from_slice(b);
self.uzunluk = son;
Ok(())
}
}
fn main() {
let mut t = Tampon { veri: [0; 32], uzunluk: 0 };
write!(t, "x={}", 42).unwrap();
let metin = t.as_str().to_string();
let tasti = t.write_str(&"a".repeat(40)).is_err();
println!("{} {}", metin, tasti);
}
Test yourself
-
How is formatting text with <code>write!</code> possible without a heap?
- With println!
- By writing into a fixed-size buffer implementing core::fmt::Write
- It isn't possible
- With a String
Show answer
By writing into a fixed-size buffer implementing core::fmt::Write — The heapless crate offers this pattern with ready types like String<N> and Vec<T, N>.
-
Copy the bytes
self.veri[self.uzunluk..son].____(b);
Show answer
self.veri[self.uzunluk..son].copy_from_slice(b);
-
Group summary
- #![no_std]
- Only core
- extern crate alloc
- Heap types
- #[panic_handler]
- Your own panic handler
- fmt::Write
- Heap-free formatting
Next lesson: build.rs