//! An encapsulation of `BufReader`'s buffer management logic.
//!
//! This module factors out the basic functionality of `BufReader` in order to protect two core
//! invariants:
//! * `filled` bytes of `buf` are always initialized
//! * `pos` is always <= `filled`
//! Since this module encapsulates the buffer management logic, we can ensure that the range
//! `pos..filled` is always a valid index into the initialized region of the buffer. This means
//! that user code which wants to do reads from a `BufReader` via `buffer` + `consume` can do so
//! without encountering any runtime bounds checks.

use core::cmp;
use core::mem::MaybeUninit;

use crate::boxed::Box;
use crate::io::{self, BorrowedBuf, ErrorKind, Read};

pub(super) struct Buffer {
    // The buffer.
    buf: Box<[MaybeUninit<u8>]>,
    // The current seek offset into `buf`, must always be <= `filled`.
    pos: usize,
    // Each call to `fill_buf` sets `filled` to indicate how many bytes at the start of `buf` are
    // initialized with bytes from a read.
    filled: usize,
    // Whether `buf` has been fully initialized. We track this so that we can accurately tell
    // `read_buf` how many bytes of buf are initialized, to bypass as much of its defensive
    // initialization as possible. Calls to `fill_buf` are not required to actually fill the buffer,
    // and omitting this is a huge perf regression for `Read` impls that do not.
    initialized: bool,
}

impl Buffer {
    #[cfg(not(no_global_oom_handling))]
    #[inline]
    pub(super) fn with_capacity(capacity: usize) -> Self {
        let buf = Box::new_uninit_slice(capacity);
        Self { buf, pos: 0, filled: 0, initialized: false }
    }

    #[inline]
    pub(super) fn try_with_capacity(capacity: usize) -> io::Result<Self> {
        match Box::try_new_uninit_slice(capacity) {
            Ok(buf) => Ok(Self { buf, pos: 0, filled: 0, initialized: false }),
            Err(_) => {
                Err(io::const_error!(ErrorKind::OutOfMemory, "failed to allocate read buffer"))
            }
        }
    }

    #[inline]
    pub(super) fn buffer(&self) -> &[u8] {
        // SAFETY: self.pos and self.filled are valid, and self.filled >= self.pos, and
        // that region is initialized because those are all invariants of this type.
        unsafe { self.buf.get_unchecked(self.pos..self.filled).assume_init_ref() }
    }

    #[inline]
    pub(super) fn capacity(&self) -> usize {
        self.buf.len()
    }

    #[inline]
    pub(super) fn filled(&self) -> usize {
        self.filled
    }

    #[inline]
    pub(super) fn pos(&self) -> usize {
        self.pos
    }

    // This is only used by a test which asserts that the initialization-tracking is correct.
    pub(super) fn initialized(&self) -> bool {
        self.initialized
    }

    #[inline]
    pub(super) fn discard_buffer(&mut self) {
        self.pos = 0;
        self.filled = 0;
    }

    #[inline]
    pub(super) fn consume(&mut self, amt: usize) {
        self.pos = cmp::min(self.pos + amt, self.filled);
    }

    /// If there are `amt` bytes available in the buffer, pass a slice containing those bytes to
    /// `visitor` and return true. If there are not enough bytes available, return false.
    #[inline]
    pub(super) fn consume_with<V>(&mut self, amt: usize, mut visitor: V) -> bool
    where
        V: FnMut(&[u8]),
    {
        if let Some(claimed) = self.buffer().get(..amt) {
            visitor(claimed);
            // If the indexing into self.buffer() succeeds, amt must be a valid increment.
            self.pos += amt;
            true
        } else {
            false
        }
    }

    #[inline]
    pub(super) fn unconsume(&mut self, amt: usize) {
        self.pos = self.pos.saturating_sub(amt);
    }

    /// Read more bytes into the buffer without discarding any of its contents
    pub(super) fn read_more(&mut self, mut reader: impl Read) -> io::Result<usize> {
        let mut buf = BorrowedBuf::from(&mut self.buf[self.filled..]);

        if self.initialized {
            // SAFETY: `self.initialized` is only set after `self.buf` was
            // fully initialized, and once `self.buf` is fully initialized
            // no part will become uninitialized.
            unsafe { buf.set_init() };
        }

        reader.read_buf(buf.unfilled())?;
        self.filled += buf.len();
        self.initialized = buf.is_init();
        Ok(buf.len())
    }

    /// Remove bytes that have already been read from the buffer.
    pub(super) fn backshift(&mut self) {
        self.buf.copy_within(self.pos..self.filled, 0);
        self.filled -= self.pos;
        self.pos = 0;
    }

    #[inline]
    pub(super) fn fill_buf(&mut self, mut reader: impl Read) -> io::Result<&[u8]> {
        // If we've reached the end of our internal buffer then we need to fetch
        // some more data from the reader.
        // Branch using `>=` instead of the more correct `==`
        // to tell the compiler that the pos..cap slice is always valid.
        if self.pos >= self.filled {
            debug_assert!(self.pos == self.filled);

            let mut buf = BorrowedBuf::from(&mut *self.buf);

            if self.initialized {
                // SAFETY: `self.initialized` is only set after `self.buf` was
                // fully initialized, and once `self.buf` is fully initialized
                // no part will become uninitialized.
                unsafe { buf.set_init() };
            }

            let result = reader.read_buf(buf.unfilled());

            self.pos = 0;
            self.filled = buf.len();
            self.initialized = buf.is_init();

            result?;
        }
        Ok(self.buffer())
    }
}
