1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use std::io::{self, BufReader, BufWriter, IntoInnerError, Read, Write};

enum BufIO<RW: Read + Write> {
    Reader(BufReader<RW>),
    Writer(BufWriter<RW>),
}

impl<RW: Read + Write> BufIO<RW> {
    fn new_writer(rw: RW) -> BufIO<RW> {
        BufIO::Writer(BufWriter::new(rw))
    }

    fn new_reader(rw: RW) -> BufIO<RW> {
        BufIO::Reader(BufReader::new(rw))
    }

    fn get_mut(&mut self) -> &mut RW {
        match self {
            BufIO::Reader(r) => r.get_mut(),
            BufIO::Writer(w) => w.get_mut(),
        }
    }

    fn get_ref(&self) -> &RW {
        match self {
            BufIO::Reader(r) => r.get_ref(),
            BufIO::Writer(w) => w.get_ref(),
        }
    }

    fn into_inner(self) -> Result<RW, IntoInnerError<BufWriter<RW>>> {
        match self {
            BufIO::Reader(r) => Ok(r.into_inner()),
            BufIO::Writer(w) => Ok(w.into_inner()?),
        }
    }
}

pub struct BufReaderWriterSeq<RW: Read + Write> {
    inner: Option<BufIO<RW>>,
    buffer: Box<Vec<u8>>,
    pos: usize,
}

impl<RW: Read + Write> BufReaderWriterSeq<RW> {
    /// Returns a new BufReaderWriterSeq instance, expecting a write as the first operation.
    pub fn new_writer(rw: RW) -> BufReaderWriterSeq<RW> {
        BufReaderWriterSeq {
            inner: Some(BufIO::new_writer(rw)),
            buffer: Box::new(vec![]),
            pos: 0,
        }
    }

    /// Returns a new BufReaderWriter instance, expecting a read as the first operation.
    pub fn new_reader(rw: RW) -> BufReaderWriterSeq<RW> {
        BufReaderWriterSeq {
            inner: Some(BufIO::new_reader(rw)),
            buffer: Box::new(vec![]),
            pos: 0,
        }
    }

    /// Gets a mutable reference to the underlying reader/writer.
    pub fn get_mut(&mut self) -> &mut RW {
        self.inner.as_mut().unwrap().get_mut()
    }

    /// Gets a reference to the underlying reader/writer.
    pub fn get_ref(&self) -> &RW {
        self.inner.as_ref().unwrap().get_ref()
    }

    /// Unwraps this `BufReaderWriter`, returning the underlying reader/writer.
    pub fn into_inner(self) -> Result<RW, IntoInnerError<BufWriter<RW>>> {
        self.inner.unwrap().into_inner()
    }
}

impl<RW: Read + Write> Read for BufReaderWriterSeq<RW> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match self.inner.as_mut().unwrap() {
            BufIO::Reader(r) => {
                if self.pos >= self.buffer.len() {
                    r.read(buf)
                } else {
                    let datalen = self.buffer.len() - self.pos;
                    let readlen = buf.len();
                    if datalen >= readlen {
                        buf.copy_from_slice(&self.buffer[self.pos..self.pos + readlen]);
                        self.pos += readlen;
                        Ok(readlen)
                    } else {
                        self.buffer.resize(self.pos + readlen, 0);
                        match r.read(&mut self.buffer[self.pos + datalen..self.pos + readlen]) {
                            Ok(n) => {
                                buf.copy_from_slice(&self.buffer[self.pos..self.pos + readlen]);
                                self.buffer.truncate(0);
                                self.pos = 0;
                                Ok(datalen + n)
                            }
                            Err(e) => Err(e),
                        }
                    }
                }
            }
            BufIO::Writer(w) => {
                w.flush()?;
                let rw = self.inner.take().unwrap().into_inner()?;
                self.inner = Some(BufIO::Reader(BufReader::new(rw)));
                self.read(buf)
            }
        }
    }
}

impl<RW: Read + Write> Write for BufReaderWriterSeq<RW> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match self.inner.as_mut().unwrap() {
            BufIO::Writer(w) => w.write(buf),
            BufIO::Reader(r) => {
                self.buffer = Box::new(r.buffer().to_vec());
                self.pos = 0;
                let rw = self.inner.take().unwrap().into_inner()?;
                self.inner = Some(BufIO::Writer(BufWriter::new(rw)));
                self.write(buf)
            }
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match self.inner.as_mut() {
            Some(BufIO::Writer(w)) => Ok(w.flush()?),
            _ => Ok(()),
        }
    }
}