Using the Encoder from tokio-util -- Need an example

Hi
I have the following code using the LengthDelimitedCodec . I want to convert this to a Decoder. I am not sure how to start. I want to replace the code I have with the example provided (i.e.) the StringDecoder provided here. tokio_util::codec - Rust

The question I have is that the StringDecoder for example does not have a stream input . I am not clear on how to use the decoder / framed part.

Server

async fn process(stream: TcpStream, tid: u32) -> Result<(), Box<dyn Error>> {
.....
....
let mut framed = LengthDelimitedCodec::builder()
        .length_field_offset(0) // length of hdr1
        .length_field_length(4)
        .length_adjustment(0) // length of hdr2
        .num_skip(4) // leaving the header byte , Does not work if 0
        .new_read(stream);
while let Some(request) = framed.next().await {
...
...
}

I'm not quite sure exactly what exactly you're asking. Are you wondering how the framed.next() can work without an stream input? It actually does have one; the .new_read(stream) hands over the ownership of the TcpStream to the FramedRead object being created.

The basic idea is that you create a codec which has a decoder and one or more encoders. The decoder gets fed a chunk of data and it is responsible for consuming a complete data entity from the input and returning the parsed data in whatever format is suitable. The encoders take in a generic parameter specifying the type that the encoder should be able to encode, and uses that input to populate a BytesMut.

Perhaps it's easier to understand the components involved by creating a (two-way) Framed explicitly, and pass in the stream and codec:

use futures::sink::SinkExt;
use tokio_stream::StreamExt;

// Create the stream encoder/decoder
let codec = LengthDelimitedCodec::new();

// Create an object for sending/receiving data on a
// frame-by-frame basis, telling it what stream it should
// read/write from and what codec is used to
// encode/decode each frame.
let framed = Framed::new(stream, codec);

Reading data:

// Get next incoming frame
// Will call the Decoder, until it receives a complete frame
while let Some(f) = framed.next().await {
}

Writing data:

// Send a frame
// Will call the Encoder for <SomeEncodeType>
let data = SomeEncodeType {
  // blah
};
framed.send(data).await;

Note that the encoder/decoder doesn't see the stream directly, instead it sees buffers it either needs to read from or write to.

If this is in no way is helpful to you, could you rephrase your question?

Sorry if I was not clear .
I understand how the LengthDelimitedCodec works.

I want to write a new codec . I am trying to follow the example given in the tokio-util page and I want to base my codec on that .

The example implements the Decoder trait and that does not take a stream .

So in the above example I would like to replace LengthDelimitedCodec with the new codec and that is my confusion

Once you have built a custom codec, you will create a Framed, FramedRead or FramedWrite by combining the codec with your IO resource. The Framed and FramedRead types implement Stream.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.