//! PeekReader implementation.

use std::io::Read;

/// A reader that caches the first `buf_size` bytes for peeking.
pub struct PeekReader<R> {
    reader: R,
    buffer: Vec<u8>,
    pos: usize,
}

impl<R: Read> PeekReader<R> {
    /// Creates a new PeekReader that caches the first `buf_size` bytes.
    pub fn new(mut reader: R, buf_size: usize) -> Self {
        let mut buffer = Vec::with_capacity(buf_size);
        reader
            .by_ref()
            .take(buf_size as u64)
            .read_to_end(&mut buffer)
            .unwrap();

        Self {
            reader,
            buffer,
            pos: 0,
        }
    }

    /// Returns the buffered header bytes.
    pub fn header(&mut self) -> &[u8] {
        &self.buffer
    }
}

impl<R: std::io::Read> std::io::Read for PeekReader<R> {
    fn read(&mut self, out: &mut [u8]) -> std::io::Result<usize> {
        if self.pos < self.buffer.len() {
            let avail = &self.buffer[self.pos..];
            let to_copy = out.len().min(avail.len());
            out[..to_copy].copy_from_slice(&avail[..to_copy]);
            self.pos += to_copy;
            Ok(to_copy)
        } else {
            self.reader.read(out)
        }
    }
}
