访问& str as& [u8]

时间:2014-01-02 20:30:30

标签: tcp rust

我用这个来驱动自己疯狂,因为根据文档判断它应该是无痛的:我如何将字符串转换为&[u8]所以我可以通过TCP或UDP通过线路发送它? bytes!()宏似乎只能直接用于文字。

这是TCP应用程序的框架,完全来自其他来源。现在它作为回声服务器工作。我遇到的绊脚石是弄清楚如何在终端上打印& [u8]字符串,或者如何将字符串从io::stdin().read_line()转换为& [u8]以通过电线发送,聊天风格。

这无法在error: mismatched types: expected `&[u8]` but found `&str` (expected vector but found &str)上编译:

fn run_tcp_test_server(listen_addr: SocketAddr) {
    let mut acceptor = TcpListener::bind(listen_addr).listen().unwrap();
    println("[ INFO ] listener is ready.");

    loop {
        let stream = Cell::new(acceptor.accept().unwrap());
        do spawn {
            println("[ INFO ] got a request.");

            let mut stream = stream.take();

            let mut my_read_buff = ~[0, ..1024];
            match stream.read(my_read_buff) {
                Some(n) => {
                    stream.write(my_read_buff.slice_to(n));
                },
                _ => ()
            }

            let out_msg = "Hello World\r\n";
            stream.write(out_msg);
        }
    }
}

我也不认为let mut my_read_buff = ~[0, ..1024]可能是正确的,这似乎是C风格的溢出等待发生,我认为Rust应该修复。

我对此非常困惑,我的理解是&str&[u8]而且我被类型系统所困扰,但无法通过这个。我试图在不安全的区块中实现std::str::raw的一些功能,但也没有运气。

1 个答案:

答案 0 :(得分:7)

&str具有与&[u8]相同的表示形式,但它有一个额外的不变量:内容始终是有效的UTF-8,因此它不是同一类型,即你必须明确地“强制转换” “它们之间(有点类似于u8i8具有相同的表示但需要显式强制转换才能使用它们。此“强制转换”由.as_bytes()完成,从&str&[u8]开始,std::str::from_utf8用于另一个方向(在0.8上,反向投射为from_utf8_slice FWIW)。 &str&[u8]演员阵容非常便宜;优化它实际上是零成本(另一个方向必须检查有效的UTF-8,因此是O(n)),并且关闭它仍然是对一个具有非常少量的函数的函数调用指令。

因此,您需要:

stream.write(out_msg.as_bytes());

(如果out_msg始终是相同的消息,您实际上可以使用b前缀来获取编译时字节文字:

stream.write(b"Hello World\r\n")


  

我也不认为let mut my_read_buff =〜[0,..1024]可能是正确的,这似乎是C风格的溢出等待发生,我认为Rust应该修复。

不,矢量和切片的长度存储在其中,因此.read调用知道允许填充多少空间,并且不会/不能写入超出它的末尾。

(FWIW,如果您的缓冲区始终是固定长度,则可以删除~,即let mut my_read_buff = [0, ..1024];,以便my_read_buf具有类型[u8, .. 1024],即修复1024 u8的长度向量。这可以避免堆分配。)