Function accept type argument

125 views Asked by At

I am working on a client server application where i send messages to / from each as protocol buffers using the rust crate prost. currently i have a generic send_message function that can take any struct that implements the prost::Message trait. I'm trying to create a similar function for reading a type that implements prost::Message. I believe the issue is that decode which is a method for types that implement prost::Message is an associated function and not an instance method. the actual instance of the object that implements prost::Message is created within the function.

Im wondering if there is a way to make a generic read_message function that can accept any type that implements prost::Message and use the associated function decode on that type.

This is my current send_message function:

pub fn send_message<M>(message: M, stream: &mut TcpStream) -> io::Result<()>
where
    M: Message,
{
    let length = message.encoded_len() as i32;
    let mut buf: Vec<u8> = Vec::with_capacity(length as usize);
    message.encode(&mut buf)?;
    stream.write_all(&length.to_le_bytes())?;
    stream.write_all(&buf)?;
    Ok(())
}

and right now i have two read_TYPE_message functions:

pub fn read_response_message(stream: &mut TcpStream) -> io::Result<message::Response> {
    let mut len_buf = [0u8; 4];
    stream.read_exact(&mut len_buf)?;
    let len = i32::from_le_bytes(len_buf);
    println!("Incoming message length: {}", len);
    let mut buf = vec![0u8; len as usize];
    stream.read_exact(&mut buf)?;
    let response = message::Response::decode(&mut buf.as_slice())?;
    Ok(response)
}

fn read_request_message(stream: &mut TcpStream) -> io::Result<message::Request> {
    let mut len_buf = [0u8; 4];
    stream.read_exact(&mut len_buf)?;
    let len = i32::from_le_bytes(len_buf);
    println!("Incoming message length: {}", len);
    let mut buf = vec![0u8; len as usize];
    stream.read_exact(&mut buf)?;
    let user_input = message::Request::decode(&mut buf.as_slice())?;
    Ok(user_input)
}

When i tried the below:

fn read_message<M: Message>(msg: M, stream: &mut TcpStream) -> io::Result<M> {
    let mut len_buf = [0u8; 4];
    stream.read_exact(&mut len_buf)?;
    let len = i32::from_le_bytes(len_buf);
    println!("Incoming message length: {}", len);
    let mut buf = vec![0u8; len as usize];
    stream.read_exact(&mut buf)?;
    let pb_msg = msg::decode(&mut buf.as_slice())?;
    Ok(pb_msg)
}

I get the error

failed to resolve: use of undeclared crate or module `msg` use of undeclared crate or module `msg`

i was hoping to be able use the function something like this:

let input = read_message(message::Request, &mut stream)?;
let input = read_message(message::Response, &mut stream)?;
0

There are 0 answers