我想要做的事,如:
let x = 123;
let mut buf = [0 as u8; 20];
format_to!(x --> buf);
assert_eq!(&buf[..3], &b"123"[..]);
随着#![no_std]
没有任何的内存分配器。
据我了解,有一个执行core::fmt::Display
为u64
,我想如果可能的话使用它。
换句话说,我要像做format!(...)
但没有一个内存分配器。 我怎样才能做到这一点?
我想要做的事,如:
let x = 123;
let mut buf = [0 as u8; 20];
format_to!(x --> buf);
assert_eq!(&buf[..3], &b"123"[..]);
随着#![no_std]
没有任何的内存分配器。
据我了解,有一个执行core::fmt::Display
为u64
,我想如果可能的话使用它。
换句话说,我要像做format!(...)
但没有一个内存分配器。 我怎样才能做到这一点?
让我们先从标准版本:
use std::io::Write;
fn main() {
let x = 123;
let mut buf = [0 as u8; 20];
write!(&mut buf[..], "{}", x).expect("Can't write");
assert_eq!(&buf[0..3], b"123");
}
如果我们再取出标准库:
#![feature(lang_items)]
#![no_std]
use core::panic::PanicInfo;
#[lang = "eh_personality"]
extern "C" fn eh_personality() {}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
loop {}
}
fn main() {
let x = 123;
let mut buf = [0 as u8; 20];
write!(&mut buf[..], "{}", x).expect("Can't write");
assert_eq!(&buf[0..3], b"123");
}
我们得到的错误
error[E0599]: no method named `write_fmt` found for type `&mut [u8]` in the current scope
--> src/main.rs:17:5
|
17 | write!(&mut buf[..], "{}", x).expect("Can't 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)
write_fmt
在核心库通过实施core::fmt::Write
。 如果我们实现它自己,我们都能够通过该错误:
#![feature(lang_items)]
#![feature(start)]
#![no_std]
use core::panic::PanicInfo;
#[lang = "eh_personality"]
extern "C" fn eh_personality() {}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
loop {}
}
use core::fmt::{self, Write};
struct Wrapper<'a> {
buf: &'a mut [u8],
offset: usize,
}
impl<'a> Wrapper<'a> {
fn new(buf: &'a mut [u8]) -> Self {
Wrapper {
buf: buf,
offset: 0,
}
}
}
impl<'a> fmt::Write for Wrapper<'a> {
fn write_str(&mut self, s: &str) -> fmt::Result {
let bytes = s.as_bytes();
// Skip over already-copied data
let remainder = &mut self.buf[self.offset..];
// Check if there is space remaining (return error instead of panicking)
if remainder.len() < bytes.len() { return Err(core::fmt::Error); }
// Make the two slices the same length
let remainder = &mut remainder[..bytes.len()];
// Copy
remainder.copy_from_slice(bytes);
// Update offset to avoid overwriting
self.offset += bytes.len();
Ok(())
}
}
#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
let x = 123;
let mut buf = [0 as u8; 20];
write!(Wrapper::new(&mut buf), "{}", x).expect("Can't write");
assert_eq!(&buf[0..3], b"123");
0
}
请注意,我们重复的行为io::Cursor
到这个包装。 通常情况下,多次写入一个&mut [u8]
将互相覆盖。 这是很好的重用分配,但不实用,当你有相同的数据的连续写入。
然后,它只是一个,如果你想要写一个宏观的问题。
你也应该能够使用一箱像arrayvec ,已经写了这个代码给你。 这是未经测试:
#![feature(lang_items)]
#![feature(start)]
#![no_std]
use core::panic::PanicInfo;
#[lang = "eh_personality"]
extern "C" fn eh_personality() {}
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
use arrayvec::ArrayString; // 0.4.10
use core::fmt::Write;
#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
let x = 123;
let mut buf = ArrayString::<[u8; 20]>::new();
write!(&mut buf, "{}", x).expect("Can't write");
assert_eq!(&buf, "123");
0
}