Read :: read是否保证附加数据而不覆盖任何现有数据?

时间:2015-05-20 01:19:09

标签: rust

我正在开发一个SMTP库,它使用缓冲的阅读器读取网络上的线路。

我想要一种不错的,安全的方式从网络读取数据,而不依赖于Rust内部,以确保代码按预期工作。具体来说,我想知道Read trait是否保证将Read::read读取的数据附加到作为参数传递的缓冲区,而不是完全覆盖缓冲区。

目前,I use a Range确保现有数据不会被覆盖,而不依赖于Rust内部。

然而,鉴于Rust used to have是一个很好的方法来做我想要的,我想知道当前的代码是否可以改进,也可能删除unsafe块。

1 个答案:

答案 0 :(得分:6)

不,它不能保证:

use std::io::prelude::*;
use std::str;

fn main() {
    let mut source1 = "hello, world!".as_bytes();
    let mut source2 = "moo".as_bytes();

    let mut dest = [0; 128];
    source1.read(&mut dest).unwrap();
    source2.read(&mut dest).unwrap();

    let s = str::from_utf8(&dest[..16]).unwrap();

    println!("{:?}", s)
}

打印

"moolo, world!\u{0}\u{0}\u{0}"

具体来说,它完全不基于类型签名而无法做到你想要的东西:

fn read(&mut self, buf: &mut [u8]) -> Result<usize>;

read方法可以访问的所有内容都是你的可变切片 - 没有地方可以存储诸如“你在缓冲区中有多远”之类的信息。此外,您不允许“扩展”具有更多元素的可变切片 - 您只能改变切片中的值。

对于您的具体情况,您可能需要查看BufRead::read_until。这是一个几乎没有经过考验的例子:

use std::io::{BufRead,BufReader};
use std::str;

fn main() {
    let source1 = "header 1\r\nheader 2\r\n".as_bytes();
    let mut reader = BufReader::new(source1);

    let mut buf = vec![];
    buf.reserve(128); // Maybe more efficient?

    loop {
        match reader.read_until(b'\n', &mut buf) {
            Ok(0) => break,
            Ok(_) => {},
            Err(_) => panic!("Handle errors"),
        }

        if buf.len() < 2 { continue }

        if buf[buf.len() - 2] == b'\r' {
            {
                let s = str::from_utf8(&buf).unwrap();
                println!("Got a header {:?}", s);
            }
            buf.clear();
        }
    }
}