media-core 0.9.0

Define media types and provide basic media utilities
Documentation
use crate::{Error, Result};

pub struct CircularBuffer<T = u8> {
    buffer: Vec<T>,
    read_pos: usize,
    write_pos: usize,
    len: usize,
}

impl<T: Default + Copy> CircularBuffer<T> {
    pub fn new(capacity: usize) -> Self {
        Self {
            buffer: vec![T::default(); capacity],
            read_pos: 0,
            write_pos: 0,
            len: 0,
        }
    }

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

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

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

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

    pub fn grow(&mut self, capacity: usize) -> Result<()> {
        if self.capacity() >= capacity {
            return Ok(());
        }

        let new_capacity = capacity.max(self.capacity() * 2);

        if self.read_pos + self.len <= self.capacity() {
            if self.write_pos == 0 && self.len > 0 {
                let pos = self.capacity();
                self.buffer.resize(new_capacity, T::default());
                self.write_pos = pos;
            } else {
                self.buffer.resize(new_capacity, T::default());
            }
        } else {
            let mut new_buffer = vec![T::default(); new_capacity];
            let len = self.len;

            if len > 0 {
                self.read_to_slice(&mut new_buffer[..len]);
            }

            self.buffer = new_buffer;
            self.read_pos = 0;
            self.write_pos = len;
            self.len = len;
        }

        Ok(())
    }

    pub fn write(&mut self, buf: &[T]) -> Result<usize> {
        if buf.is_empty() {
            return Err(Error::WriteFailed("input buffer is empty".into()));
        }

        if self.available() < buf.len() {
            self.grow(self.len + buf.len())?;
        }

        let write_len = buf.len().min(self.available());
        let end_pos = self.write_pos + write_len;

        if end_pos <= self.capacity() {
            self.buffer[self.write_pos..end_pos].copy_from_slice(&buf[..write_len]);
            self.write_pos = end_pos % self.capacity();
        } else {
            let chunk_len = self.capacity() - self.write_pos;
            self.buffer[self.write_pos..].copy_from_slice(&buf[..chunk_len]);
            self.buffer[..write_len - chunk_len].copy_from_slice(&buf[chunk_len..write_len]);
            self.write_pos = (write_len - chunk_len) % self.capacity();
        }

        self.len += write_len;

        Ok(write_len)
    }

    pub fn read(&mut self, buf: &mut [T]) -> Result<usize> {
        if buf.is_empty() {
            return Err(Error::ReadFailed("output buffer is empty".into()));
        }

        let read_len = buf.len().min(self.len);
        if read_len == 0 {
            return Ok(0);
        }

        self.read_to_slice(&mut buf[..read_len]);
        Ok(read_len)
    }

    fn read_to_slice(&mut self, buf: &mut [T]) {
        let read_len = buf.len();
        let end_pos = self.read_pos + read_len;

        if end_pos <= self.capacity() {
            buf.copy_from_slice(&self.buffer[self.read_pos..end_pos]);
            self.read_pos = end_pos % self.capacity();
        } else {
            let chunk_len = self.capacity() - self.read_pos;
            buf[..chunk_len].copy_from_slice(&self.buffer[self.read_pos..]);
            buf[chunk_len..].copy_from_slice(&self.buffer[..read_len - chunk_len]);
            self.read_pos = (read_len - chunk_len) % self.capacity();
        }

        self.len -= read_len;
    }

    pub fn peek(&self, buf: &mut [T]) -> Result<usize> {
        if buf.is_empty() {
            return Err(Error::ReadFailed("output buffer is empty".into()));
        }

        let peek_len = buf.len().min(self.len);
        if peek_len == 0 {
            return Ok(0);
        }

        let end_pos = self.read_pos + peek_len;

        if end_pos <= self.capacity() {
            buf.copy_from_slice(&self.buffer[self.read_pos..end_pos]);
        } else {
            let chunk_len = self.capacity() - self.read_pos;
            buf[..chunk_len].copy_from_slice(&self.buffer[self.read_pos..]);
            buf[chunk_len..].copy_from_slice(&self.buffer[..peek_len - chunk_len]);
        }

        Ok(peek_len)
    }

    pub fn consume(&mut self, len: usize) -> usize {
        let consume_len = len.min(self.len);
        self.read_pos = (self.read_pos + consume_len) % self.capacity();
        self.len -= consume_len;
        consume_len
    }

    pub fn clear(&mut self) {
        self.read_pos = 0;
        self.write_pos = 0;
        self.len = 0;
    }
}