snap_buf/
cursor.rs

1use crate::SnapBuf;
2use std::io::{Read, Seek, SeekFrom, Write};
3
4/// A file-like abstraction around SnapBuf implementing std-io traits.
5pub struct SnapBufCursor {
6    cursor: usize,
7    buf: SnapBuf,
8}
9
10impl SnapBufCursor {
11    /// Wraps an existing `SnapBuf`.
12    ///
13    /// Initially, the cursor is at the start of the buffer
14    pub fn new(snap_buf: SnapBuf) -> Self {
15        SnapBufCursor {
16            cursor: 0,
17            buf: snap_buf,
18        }
19    }
20
21    /// Returns the contained `SnapBuf`.
22    ///
23    /// The cursor position is discarded.
24    pub fn into_inner(self) -> SnapBuf {
25        self.buf
26    }
27}
28
29impl Seek for SnapBufCursor {
30    fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
31        let new_pos = match pos {
32            SeekFrom::Start(x) => {
33                self.cursor = x.try_into().unwrap();
34                return Ok(x);
35            }
36            SeekFrom::End(x) => self.buf.len() as i64 + x,
37            SeekFrom::Current(x) => self.cursor as i64 + x,
38        };
39        if new_pos < 0 {
40            return Err(std::io::ErrorKind::InvalidInput.into());
41        }
42        self.cursor = new_pos.try_into().unwrap();
43        Ok(self.cursor as u64)
44    }
45}
46
47impl Read for SnapBufCursor {
48    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
49        let available = self.buf.read(self.cursor);
50        let read_len = buf.len().min(available.len());
51        buf[..read_len].copy_from_slice(&available[..read_len]);
52        self.cursor += read_len;
53        Ok(read_len)
54    }
55}
56
57impl Write for SnapBufCursor {
58    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
59        self.buf.write(self.cursor, buf);
60        self.cursor += buf.len();
61        Ok(buf.len())
62    }
63
64    fn flush(&mut self) -> std::io::Result<()> {
65        Ok(())
66    }
67}