http/encoding/
chunked.rs

1use std::io::{Read, Result, Write};
2
3const CHUNK_SIZE: usize = 1024;
4pub struct Chunked<R: Read> {
5    reader: R,
6    chunk: Vec<u8>,
7    offset: usize,
8    finish: bool,
9}
10
11impl<R: Read> Chunked<R> {
12    pub fn new(reader: R) -> Self {
13        Self {
14            reader,
15            chunk: Vec::with_capacity(CHUNK_SIZE + 8),
16            offset: 0,
17            finish: false,
18        }
19    }
20    fn next_chunk(&mut self) -> Result<bool> {
21        if self.finish {
22            return Ok(false);
23        }
24        self.chunk.clear();
25        self.offset = 0;
26
27        let mut tmpbuf: [u8; CHUNK_SIZE] = [0; CHUNK_SIZE];
28        let n = self.reader.read(&mut tmpbuf)?;
29        if n == 0 {
30            self.finish = true;
31        }
32        self.chunk.write_all(format!("{n:X}\r\n").as_bytes())?;
33        self.chunk.write_all(&tmpbuf[0..n])?;
34        self.chunk.write_all(b"\r\n")?;
35        Ok(true)
36    }
37}
38
39impl<R: Read> Read for Chunked<R> {
40    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
41        if self.offset >= self.chunk.len() && !self.next_chunk()? {
42            return Ok(0);
43        }
44        let mut n = self.chunk.len() - self.offset;
45        if n > buf.len() {
46            n = buf.len();
47        }
48        buf.as_mut()
49            .write_all(&self.chunk[self.offset..self.offset + n])?;
50        self.offset += n;
51        Ok(n)
52    }
53}