I'm using Rust for an embedded environment where we don't have an OS and we are building are target as no_std
.
We have implemented a special pathway for the device to log error messages in case of panic -- I'm trying to implement a panic_handler
lang item.
Our initial version (working) looks like this:
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
let mut buf = String::new();
write!(&mut buf, "{}", info).unwrap();
unsafe { report_panic_message(buf.as_ptr(), buf.len()) };
unsafe { abort() }
}
Here we are using alloc::string::String
to act as the buffer into which we format the panic message.
However, this implementation is bad because allocating the string could fail, potentially leading to a panic, and then the panic handler will likely fail.
Instead, we would like to format into a fixed-size buffer on the stack, and drop the dependency on alloc
crate.
The attempted fix is like this:
// Maximum supported message length
const MAX_MSG_SIZE: usize = 4096;
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
let mut buf = [0u8; MAX_MSG_SIZE];
match write!(&mut buf, "{}", info) {
Ok(n) => {
unsafe { report_panic_message(buf.as_ptr(), n) };
}
Err(_) => {
let err_msg = "panic: The panic message exceeded MAX_MSG_SIZE bytes";
unsafe { report_panic_message(err_msg.as_ptr(), err_msg.len()) };
}
};
unsafe { abort() }
}
However this fails with an error message:
error[E0599]: no method named `write_fmt` found for type `&mut [u8; 4096]` in the current scope
--> /src/lib.rs:36:11
|
36 | match write!(& mut buf, "{}", info) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the method `write_fmt` exists but the following trait bounds were not satisfied:
`&mut [u8; 4096] : core::fmt::Write`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
It appears that the trait std::io::Write
is implemented for &mut[u8]
, c.f. but it isn't implemented for core::fmt::Write
. I cannot implement core::fmt::Write
for a built-in type, due to the orphan rules.
What is the most idiomatic way to do this?