cookie_factory/
async_bufwriter.rs1use futures::io::{AsyncWrite, AsyncWriteExt};
2
3pub struct AsyncBufWriter<W: AsyncWrite + Unpin> {
4 inner: W,
5 buf: Vec<u8>,
6 pos: usize,
7}
8
9const DEFAULT_BUF_SIZE: usize = 8 * 1024;
10
11impl<W: AsyncWrite + Unpin> AsyncBufWriter<W> {
12 pub fn new(inner: W) -> AsyncBufWriter<W> {
13 AsyncBufWriter::with_capacity(DEFAULT_BUF_SIZE, inner)
14 }
15
16 pub fn with_capacity(capacity: usize, inner: W) -> AsyncBufWriter<W> {
17 let buf = vec![0; capacity];
18 AsyncBufWriter { inner, buf, pos: 0 }
19 }
20
21 pub async fn flush(&mut self) -> std::io::Result<usize> {
22 let sz = self.inner.write(&self.buf[..self.pos]).await?;
23
24 if sz < self.pos {
27 for i in 0..(self.pos - sz) {
28 self.buf[i] = self.buf[sz + i]
29 }
30 }
31
32 self.pos -= sz;
33
34 Ok(sz)
35 }
36
37 pub fn remaining(&self) -> usize {
38 self.pos
39 }
40
41 pub fn into_parts(mut self) -> (W, Vec<u8>) {
42 self.buf.truncate(self.pos);
43 (self.inner, self.buf)
44 }
45}
46
47impl<W: AsyncWrite + Unpin> std::io::Write for AsyncBufWriter<W> {
48 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
49 let sz = (&mut self.buf[self.pos..]).write(buf)?;
50 self.pos += sz;
51 Ok(sz)
52 }
53
54 fn flush(&mut self) -> std::io::Result<()> {
55 Ok(())
56 }
57}
58
59pub async fn gen<W: AsyncWrite + Unpin, F: crate::internal::SerializeFn<AsyncBufWriter<W>>>(
60 f: F,
61 w: AsyncBufWriter<W>,
62) -> Result<(AsyncBufWriter<W>, u64), crate::internal::GenError> {
63 match f(crate::internal::WriteContext::from(w)).map(|ctx| ctx.into_inner()) {
64 Err(e) => Err(e),
65 Ok((mut w, _)) => {
66 let sz = w.flush().await?;
67 Ok((w, sz as u64))
68 }
69 }
70}