2016-09-14 136 views
2

我想要做的事,如:如何使用no_std將整數作爲字符串寫入字節數組?

let x = 123; 
let mut buf = [0 as u8; 20]; 
format_to!(x --> buf); 
assert_eq!(&buf[..3], &b"123"[..]); 

隨着#![no_std],沒有任何的內存分配器。

據我所知,有core::fmt::Displayu64的實現,我想盡可能使用它。

換句話說,我想做一些像format!(...),但沒有內存分配器。我怎樣才能做到這一點?

回答

4

讓我們先從標準版本:

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] 

#[lang = "eh_personality"] extern fn eh_personality() {} 
#[lang = "panic_fmt"] extern fn panic_fmt() -> ! { 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: no method named `write_fmt` found for type `&mut [u8]` in the current scope 
    --> src/main.rs:13:5 
    | 
13 |  write!(&mut buf[..], "{}", x).expect("Can't write"); 
    |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    | 
    = note: this error originates in a macro from the standard library 

write_fmt在覈心中實現圖書館由core::fmt::Write。如果我們實現它自己,我們都能夠通過該錯誤:

#![feature(lang_items)] 
#![feature(start)] 
#![no_std] 

extern crate libc; 

#[lang = "eh_personality"] extern fn eh_personality() {} 
#[lang = "panic_fmt"] extern fn panic_fmt() -> ! { 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..]; 
     // Make the two slices the same length 
     let remainder = &mut remainder[..bytes.len()]; 
     // Copy 
     remainder.copy_from_slice(bytes); 

     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]的多次寫入將相互覆蓋。這對重用分配很有用,但在連續寫入相同數據時無用。

然後這只是一個寫宏的問題,如果你想。

+0

這需要'self.offset + = bytes.len();'在write_str()中,否則這是有效的。想知道爲什麼格式化浮點只打印小數部分。 –

相關問題