irox-bits 0.5.0

Bits & Bobs. No-std/No-alloc bit/byte manipulation of streams
Documentation
// SPDX-License-Identifier: MIT
// Copyright 2025 IROX Contributors
//

use crate::mutbits::MutBits;
use crate::{Bits, BitsWrapper, Error, Seek, SeekFrom};
use std::io::{Read, Write};

impl Bits for std::fs::File {
    fn next_u8(&mut self) -> Result<Option<u8>, Error> {
        use std::io::Read;
        let mut buf: [u8; 1] = [0];
        let read = self.read(&mut buf)?;
        if read == 1 {
            return Ok(Some(buf[0]));
        }
        Ok(None)
    }
}

impl MutBits for std::fs::File {
    fn write_u8(&mut self, val: u8) -> Result<(), Error> {
        Ok(self.write_all(&[val])?)
    }

    fn flush(&mut self) -> Result<(), Error> {
        Write::flush(self)?;
        Ok(())
    }
}
impl Seek for std::fs::File {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64, Error> {
        std::io::Seek::seek(self, pos.into())?;
        Ok(std::io::Seek::stream_position(self)?)
    }
}
impl<T: Read> Bits for std::io::BufReader<T> {
    fn next_u8(&mut self) -> Result<Option<u8>, Error> {
        BitsWrapper::Borrowed(self).next_u8()
    }
}
impl<T: Write> MutBits for std::io::BufWriter<T> {
    fn write_u8(&mut self, val: u8) -> Result<(), Error> {
        BitsWrapper::Borrowed(self).write_u8(val)
    }
    fn flush(&mut self) -> Result<(), Error> {
        Write::flush(self)?;
        Ok(())
    }
}

impl Bits for std::net::TcpStream {
    fn next_u8(&mut self) -> Result<Option<u8>, Error> {
        BitsWrapper::Borrowed(self).next_u8()
    }

    fn read_some_into<T: MutBits>(&mut self, buf: &mut T) -> Result<usize, Error> {
        let mut b = [0u8; 4096];
        let read_stream = self.peek(&mut b)?;
        let (stream, _) = b.split_at_mut(read_stream);
        let consumed = buf.write_some_bytes(stream);
        let (stream, _) = stream.split_at_mut(consumed);
        std::io::Read::read_exact(self, stream)?;
        Ok(consumed)
    }
}
impl Bits for &mut std::net::TcpStream {
    fn next_u8(&mut self) -> Result<Option<u8>, Error> {
        BitsWrapper::Borrowed(self).next_u8()
    }

    fn read_some_into<T: MutBits>(&mut self, buf: &mut T) -> Result<usize, Error> {
        let mut b = [0u8; 4096];
        let read_stream = self.peek(&mut b)?;
        let (stream, _) = b.split_at_mut(read_stream);
        let consumed = buf.write_some_bytes(stream);
        let (stream, _) = stream.split_at_mut(consumed);
        std::io::Read::read_exact(self, stream)?;
        Ok(consumed)
    }
}
impl MutBits for std::net::TcpStream {
    fn write_u8(&mut self, val: u8) -> Result<(), Error> {
        BitsWrapper::Borrowed(self).write_u8(val)
    }
    fn flush(&mut self) -> Result<(), Error> {
        std::io::Write::flush(self)?;
        Ok(())
    }
}
impl MutBits for &mut std::net::TcpStream {
    fn write_u8(&mut self, val: u8) -> Result<(), Error> {
        BitsWrapper::Borrowed(self).write_u8(val)
    }
    fn flush(&mut self) -> Result<(), Error> {
        std::io::Write::flush(self)?;
        Ok(())
    }
}

#[cfg(windows)]
impl crate::SeekRead for std::fs::File {
    fn seek_read(&mut self, out: &mut [u8], offset: u64) -> Result<usize, Error> {
        Ok(std::os::windows::fs::FileExt::seek_read(self, out, offset)?)
    }
}
#[cfg(windows)]
impl crate::SeekWrite for std::fs::File {
    fn seek_write(&mut self, input: &[u8], offset: u64) -> Result<usize, Error> {
        Ok(std::os::windows::fs::FileExt::seek_write(
            self, input, offset,
        )?)
    }
}

#[cfg(unix)]
impl crate::SeekRead for std::fs::File {
    fn seek_read(&mut self, out: &mut [u8], offset: u64) -> Result<usize, Error> {
        Ok(std::os::unix::fs::FileExt::read_at(self, out, offset)?)
    }
}
#[cfg(unix)]
impl crate::SeekWrite for std::fs::File {
    fn seek_write(&mut self, input: &[u8], offset: u64) -> Result<usize, Error> {
        Ok(std::os::unix::fs::FileExt::write_at(self, input, offset)?)
    }
}