Unable to convert between Bytes and Vec<u8>

Hi, I am working with hyper app server library. and i am trying to modify the incoming frames and send that as the output. But i am unable to complete the map function.

let new_frames = old_frames.map_frame(|frame| { // Error:  The trait bound `Vec<u8>: Buf` is not satisfied
                frame.into_data()
                    .map(|bytes| Frame::data(bytes.to_ascii_uppercase()))
                    .unwrap_or_else(|_| Frame::data(Bytes::new().to_ascii_uppercase()))
            });
            return Ok(Response::new(new_frames.boxed())) // Error: The method `boxed` exists for struct `MapFrame<hyper::body::Incoming, {closure@src\main.rs:50:51: 50:58}>`, but its trait bounds were not satisfied

No matter what i try something or the other breaks in this function. Can you help me with this?

Full function:

async fn echo(req: Request<hyper::body::Incoming>) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> {

    if let Some(response) = match(req.method(), req.uri().path()) {
        (&Method::GET, "/") => Some("Try POST /echo"),
        (&Method::POST, "/echo") => {
            return Ok(Response::new(req.into_body().boxed()))
        }
        (&Method::POST, "/echo/uppercase") => {
            let old_frames = req.into_body();

            /*let new_frames = old_frames.map_frame( |frame| {
                Frame::data(Bytes::from(frame.into_data().unwrap().to_ascii_uppercase()))
            });*/


            let new_frames = old_frames.map_frame(|frame| {
                frame.into_data()
                    .map(|bytes| Frame::data(bytes.to_ascii_uppercase()))
                    .unwrap_or_else(|_| Frame::data(Bytes::new().to_ascii_uppercase()))
            });
            return Ok(Response::new(new_frames.boxed()))
        },
        _=> {
            None
        }
    } {
        let response: BoxBody<Bytes, hyper::Error> = Full::from(response).map_err(|never| match never {  } ).boxed();

        return Ok(Response::new(response))
    };

    let empty = Empty::<Bytes>::new().map_err(|never| match never {  }  ).boxed();
    let not_found = Response::builder().status(StatusCode::NOT_FOUND).body((empty)).unwrap();
    Ok(not_found)
}

1 Like

Use:
Frame::data(Bytes::from(data.to_ascii_uppercase())) instead of
Frame::data(bytes.to_ascii_uppercase())

(&Method::POST, "/echo/uppercase") => {
            let old_frames = req.into_body();

           // map_frame transforms each frame in the body stream
             let new_frames = old_frames.map_frame(|frame| {
                match frame.into_data() {
                    Ok(data) => {
                        // HERE: wrap Vec<u8> in Bytes::from()
                        // data.to_ascii_uppercase() returns Vec<u8>
                        // Frame::data() needs T: Buf, and Bytes: Buf but Vec<u8>: !Buf (not Buf)
                        Frame::data(Bytes::from(data.to_ascii_uppercase()))
                    }

                    Err(original_frame) => {
                        original_frame
                   }
                }
           });

            Ok(Response::new(new_frames.boxed()))
       }

You cannot do that without an allocation because their internal representation is different.