Summary - no_std and embedded
- Rust course
- Expert
- Lesson 36/46
- 5 min
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(())
}
}Practice 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.
Starter code
use core::fmt::{self, Write};
fn main() {
// buraya yaz
}Sample 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);
}Expected output
x=42 true
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 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 Correct answer
- It isn't possible
- With a String
Explanation: The heapless crate offers this pattern with ready types like String<N> and Vec<T, N>.
2 Copy the bytes
self.veri[self.uzunluk..son].____(b);
self.veri[self.uzunluk..son].copy_from_slice(b);
Explanation: copy_from_slice copies the bytes of a slice of the same length.
3 Group summary
| Term | Meaning |
|---|---|
#![no_std] |
Only core |
extern crate alloc |
Heap types |
#[panic_handler] |
Your own panic handler |
fmt::Write |
Heap-free formatting |