irox_bits/seek.rs
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
// SPDX-License-Identifier: MIT
// Copyright 2024 IROX Contributors
//
use crate::Error;
/// Enum to indicate how to move a read/write pointer.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum SeekFrom {
Start(u64),
End(i64),
Current(i64),
}
cfg_feature_std! {
impl From<SeekFrom> for std::io::SeekFrom {
fn from(fr: SeekFrom) -> Self {
match fr {
SeekFrom::Start(n) => std::io::SeekFrom::Start(n),
SeekFrom::End(n) => std::io::SeekFrom::End(n),
SeekFrom::Current(n) => std::io::SeekFrom::Current(n),
}
}
}
}
///
/// Trait to move the current read/write position of a stream.
///
/// There's no reason this trait should have been in std and not core.
pub trait Seek {
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Error>;
}
///
/// Trait to permit an atomic Seek+Read operation
pub trait SeekRead {
/// Seek to the offset, relative to the start of the stream, and read some bytes into the
/// provided buffer. The number of bytes read is returned.
fn seek_read(&mut self, out: &mut [u8], offset: u64) -> Result<usize, Error>;
/// Reads all data from the offset into the provided buffer. May require multiple file ops &
/// seeks if the calls do not read all the data.
fn seek_read_all(&mut self, mut out: &mut [u8], mut offset: u64) -> Result<(), Error> {
while !out.is_empty() {
let split = self.seek_read(out, offset)?;
let (_, newo) = out.split_at_mut(split);
out = newo;
offset += split as u64;
}
Ok(())
}
}
///
/// Trait to permit an atomic Seek+Write operation
pub trait SeekWrite {
/// Seek to the provided offset, relative to the start of the stream, and write some bytes
/// from the provided buffer. The number of bytes written is returned.
fn seek_write(&mut self, input: &[u8], offset: u64) -> Result<usize, Error>;
/// Writes all the data to the provided offset. May require multiple file ops & seeks
/// if the calls do not write all the data.
fn seek_write_all(&mut self, mut input: &[u8], mut offset: u64) -> Result<(), Error> {
while !input.is_empty() {
let split = self.seek_write(input, offset)?;
let (_, nxt) = input.split_at(split);
offset += split as u64;
input = nxt;
}
Ok(())
}
}