Search code examples
udpbufferrustmio

Working with UDP using mio and getting an error "MutBuf is not implemented for the type MutSliceBuf"


For learning purposes I am currently trying to write small program which will implement echo-server for UDP packets which will work on a certain set of ports (say 10000-60000). So as it wouldn't be so good to spam 50k threads for this I need to use asynchronous IO and mio is excellent match for this task. But I've got a problem right from the start with this code:

extern crate mio;
extern crate bytes;
use mio::udp::*;
use bytes::MutSliceBuf;

fn main() {
    let addr = "127.0.0.1:10000".parse().unwrap();

    let socket = UdpSocket::bound(&addr).unwrap();

    let mut buf = [0; 128];
    socket.recv_from(&mut MutSliceBuf::wrap(&mut buf));
}

It is almost full copypaste from of mio's test_udp_socket.rs.But while mio's tests successfully pass through, then I try to compile this code I am getting following error:

src/main.rs:12:12: 12:55 error: the trait `bytes::buf::MutBuf` is not implemented for the type `bytes::buf::slice::MutSliceBuf<'_>` [E0277]
src/main.rs:12     socket.recv_from(&mut MutSliceBuf::wrap(&mut buf));
                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:12:12: 12:55 help: run `rustc --explain E0277` to see a detailed explanation

But examining code of src/buf/slice.rs from bytes crate (local copy of it too) we can clearly see what this trait was implemented:

impl<'a> MutBuf for MutSliceBuf<'a> {
    fn remaining(&self) -> usize {
        self.bytes.len() - self.pos
    }

    fn advance(&mut self, mut cnt: usize) {
        cnt = cmp::min(cnt, self.remaining());
        self.pos += cnt;
    }

    unsafe fn mut_bytes<'b>(&'b mut self) -> &'b mut [u8] {
        &mut self.bytes[self.pos..]
    }
}

It's probably something trivial, but I can't find it... What could be a problem which causes this error?

I am using rustc 1.3.0 (9a92aaf19 2015-09-15), crates mio and bytes is gotten straight from github.


Solution

  • Using Cargo with

    [dependencies]
    mio = "*"
    bytes = "*"
    

    this runs for me. Using the Github dependency,

    [dependencies.mio]
    git = "https://github.com/carllerche/mio.git"
    

    gives the error you mention.

    Strangely, version 0.4 depends on

    bytes = "0.2.11"
    

    whereas master depends on

    git = "https://github.com/carllerche/bytes"
    rev = "7edb577d0a"
    

    which is only version 0.2.10. Strange.

    The problem is that you end up getting two bytes dependencies compiled, so the error is more like

    the trait `mio::bytes::buf::MutBuf` is not implemented for the type `self::bytes::buf::slice::MutSliceBuf<'_>`
    

    The simplest way I see to fix this is to just use both packages from crates.io.

    [dependencies]
    mio = "*"
    bytes = "*"
    

    Another way is to use

    [dependencies.bytes]
    git = "https://github.com/carllerche/bytes"
    rev = "7edb577d0a"
    

    in your own Cargo.toml, such that you share versions.