找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 75|回复: 0

【Rust】分享一个模块:CopiableBuffer。自己造轮子实现简易的栈上缓冲区。

[复制链接]
发表于 2025-4-14 21:02:14 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
这玩意儿可以 Debug,Clone,Copy,push(),len(),set_len(),last(),iter(),iter_mut(),into_iter(),clear(),capacity(),is_full(),is_empty(),以及带边界检查的索引和可变索引。如果不想它进行边界检查,你就自己读写它的 buffer 就好了。
拉珠元素拉满。
一个定长数组和一个变量存储了你往里面写入了多少数据。
在需要简短的像 Vec<T> 一样的东西,却也不希望失去 Copy 的时候,可以使用这个。

use std::{io, ops::{Index, IndexMut}, iter::FromIterator, fmt::Debug};

pub trait CopiableItem: Default + Clone + Copy + Debug + Sized {}
impl<T> CopiableItem for T where T: Default + Clone + Copy + Debug + Sized {}

#[derive(Clone, Copy)]
pub struct CopiableBuffer<T, const N: usize>
where T: CopiableItem {
    buffer: [T; N],
    buf_used: usize,
}

#[derive(Debug)]
pub struct CopiableBufferIter<'a, T, const N: usize>
where T: CopiableItem {
    refbuf: &'a CopiableBuffer<T, N>,
    iter_index: usize,
}

#[derive(Debug)]
pub struct CopiableBufferIterMut<'a, T, const N: usize>
where T: CopiableItem {
    refbuf: &'a mut CopiableBuffer<T, N>,
    iter_index: usize,
}

#[derive(Clone, Copy)]
pub struct CopiableBufferIntoIter<T, const N: usize>
where T: CopiableItem {
    buffer: [T; N],
    buf_used: usize,
    iter_index: usize,
}

impl<T, const N: usize> CopiableBuffer<T, N>
where T: CopiableItem {
    pub fn new() -> Self {
        Self {
            buffer: [T::default(); N],
            buf_used: 0,
        }
    }

    pub fn len(&self) -> usize {
        self.buf_used
    }

    pub fn set_len(&mut self, new_len: usize) {
        self.buf_used = new_len;
    }

    #[track_caller]
    pub fn last(&mut self) -> &mut T {
        if self.buf_used == 0 {
            panic!("CopiableBuffer<{}, {N}> is empty.", std::any::type_name::<T>());
        }
        &mut self.buffer[self.buf_used - 1]
    }

    #[track_caller]
    pub fn push(&mut self, data: T) {
        if self.buf_used >= self.buffer.len() {
            panic!("CopiableBuffer<{}, {N}> is full.", std::any::type_name::<T>());
        } else {
            self.buffer[self.buf_used] = data;
            self.buf_used += 1;
        }
    }

    pub fn iter(&self) -> impl Iterator<Item = &T> {
        CopiableBufferIter::<T, N> {
            refbuf: &self,
            iter_index: 0,
        }
    }

    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
        CopiableBufferIterMut::<T, N> {
            refbuf: self,
            iter_index: 0,
        }
    }

    pub fn clear(&mut self) {
        self.set_len(0)
    }

    pub fn capacity(&self) -> usize {
        N
    }

    pub fn is_full(&self) -> bool {
        self.len() == self.capacity()
    }
    
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

impl<T, const N: usize> Index<usize> for CopiableBuffer<T, N>
where T: CopiableItem {
    type Output = T;

    #[track_caller]
    fn index(&self, index: usize) -> &Self::Output {
        if index >= self.buf_used {
            panic!(
                "Index out of bounds: {} >= {}",
                index, self.buf_used
            );
        }
        &self.buffer[index]
    }
}

impl<T, const N: usize> IndexMut<usize> for CopiableBuffer<T, N>
where T: CopiableItem {

    #[track_caller]
    fn index_mut<'a>(&mut self, index: usize) -> &mut T {
        if index >= self.buf_used {
            panic!(
                "Index out of bounds: {} >= {}",
                index, self.buf_used
            );
        }
        &mut self.buffer[index]
    }
}

impl<T, const N: usize> FromIterator<T> for CopiableBuffer<T, N>
where T: CopiableItem {
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        let mut iter = iter.into_iter();
        let mut ret = Self::new();
        while let Some(data) = iter.next() {
            ret.push(data);
        }
        ret
    }
}

impl<'a, T, const N: usize> Iterator for CopiableBufferIter<'a, T, N>
where T: CopiableItem {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        if self.iter_index < self.refbuf.len() {
            let r = &self.refbuf.buffer[self.iter_index];
            self.iter_index += 1;
            Some(r)
        } else {
            None
        }
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        self.iter_index += n;
        self.next()
    }
}

impl<'a, T, const N: usize> Iterator for CopiableBufferIterMut<'a, T, N>
where T: CopiableItem {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<Self::Item> {
        if self.iter_index < self.refbuf.len() {
            unsafe {
                let item_ptr = self.refbuf.buffer.as_mut_ptr().add(self.iter_index);
                self.iter_index += 1;
                Some(&mut *item_ptr)
            }
        } else {
            None
        }
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        self.iter_index += n;
        self.next()
    }
}

impl<T, const N: usize> Iterator for CopiableBufferIntoIter<T, N>
where T: CopiableItem {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        if self.iter_index < self.buf_used {
            let ret = Some(self.buffer[self.iter_index]);
            self.iter_index += 1;
            ret
        } else {
            None
        }
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        self.iter_index += n;
        self.next()
    }
}

impl<T, const N: usize> IntoIterator for CopiableBuffer<T, N>
where T: CopiableItem {
    type Item = T;
    type IntoIter = CopiableBufferIntoIter<T, N>;

    fn into_iter(self) -> Self::IntoIter {
        Self::IntoIter {
            buffer: self.buffer,
            buf_used: self.buf_used,
            iter_index: 0,
        }
    }
}

impl<T, const N: usize> Debug for CopiableBuffer<T, N>
where T: CopiableItem {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        fmt.debug_struct(&format!("CopiableBuffer<{}, {N}>", std::any::type_name::<T>()))
            .field("buffer", &&self.buffer[..self.buf_used])
            .field("buf_used", &self.buf_used)
            .finish()
    }
}

impl<T, const N: usize> Debug for CopiableBufferIntoIter<T, N>
where T: CopiableItem {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        fmt.debug_struct(&format!("CopiableBufferIntoIter<{}, {N}>", std::any::type_name::<T>()))
            .field("buffer", &&self.buffer[..self.buf_used])
            .field("buf_used", &self.buf_used)
            .field("iter_index", &self.iter_index)
            .finish()
    }
}
回复

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2025-4-23 01:29 , Processed in 0.031192 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表