irox_bits/
seek.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2024 IROX Contributors
3//
4use crate::Error;
5
6/// Enum to indicate how to move a read/write pointer.
7#[derive(Debug, Copy, Clone, Eq, PartialEq)]
8pub enum SeekFrom {
9    Start(u64),
10    End(i64),
11    Current(i64),
12}
13
14cfg_feature_std! {
15    impl From<SeekFrom> for std::io::SeekFrom {
16        fn from(fr: SeekFrom) -> Self {
17            match fr {
18                SeekFrom::Start(n) => std::io::SeekFrom::Start(n),
19                SeekFrom::End(n) => std::io::SeekFrom::End(n),
20                SeekFrom::Current(n) => std::io::SeekFrom::Current(n),
21            }
22        }
23    }
24}
25
26///
27/// Trait to move the current read/write position of a stream.  
28///
29/// There's no reason this trait should have been in std and not core.  
30pub trait Seek {
31    fn seek(&mut self, pos: SeekFrom) -> Result<u64, Error>;
32}
33
34///
35/// Trait to permit an atomic Seek+Read operation
36pub trait SeekRead {
37    /// Seek to the offset, relative to the start of the stream, and read some bytes into the
38    /// provided buffer.  The number of bytes read is returned.
39    fn seek_read(&mut self, out: &mut [u8], offset: u64) -> Result<usize, Error>;
40
41    /// Reads all data from the offset into the provided buffer.  May require multiple file ops &
42    /// seeks if the calls do not read all the data.
43    fn seek_read_all(&mut self, mut out: &mut [u8], mut offset: u64) -> Result<(), Error> {
44        while !out.is_empty() {
45            let split = self.seek_read(out, offset)?;
46            let (_, newo) = out.split_at_mut(split);
47            out = newo;
48            offset += split as u64;
49        }
50        Ok(())
51    }
52}
53
54///
55/// Trait to permit an atomic Seek+Write operation
56pub trait SeekWrite {
57    /// Seek to the provided offset, relative to the start of the stream, and write some bytes
58    /// from the provided buffer.  The number of bytes written is returned.
59    fn seek_write(&mut self, input: &[u8], offset: u64) -> Result<usize, Error>;
60
61    /// Writes all the data to the provided offset.  May require multiple file ops & seeks
62    /// if the calls do not write all the data.
63    fn seek_write_all(&mut self, mut input: &[u8], mut offset: u64) -> Result<(), Error> {
64        while !input.is_empty() {
65            let split = self.seek_write(input, offset)?;
66            let (_, nxt) = input.split_at(split);
67            offset += split as u64;
68            input = nxt;
69        }
70        Ok(())
71    }
72}