Skip to main content

oxihuman_core/
byte_pool.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5/// A pool of reusable byte buffers to reduce allocation overhead.
6#[allow(dead_code)]
7#[derive(Debug, Clone)]
8pub struct BytePool {
9    free: Vec<Vec<u8>>,
10    buffer_size: usize,
11    total_allocated: usize,
12}
13
14#[allow(dead_code)]
15impl BytePool {
16    pub fn new(buffer_size: usize) -> Self {
17        Self {
18            free: Vec::new(),
19            buffer_size,
20            total_allocated: 0,
21        }
22    }
23
24    pub fn acquire(&mut self) -> Vec<u8> {
25        if let Some(mut buf) = self.free.pop() {
26            buf.clear();
27            buf
28        } else {
29            self.total_allocated += 1;
30            Vec::with_capacity(self.buffer_size)
31        }
32    }
33
34    pub fn release(&mut self, buf: Vec<u8>) {
35        self.free.push(buf);
36    }
37
38    pub fn free_count(&self) -> usize {
39        self.free.len()
40    }
41
42    pub fn total_allocated(&self) -> usize {
43        self.total_allocated
44    }
45
46    pub fn buffer_size(&self) -> usize {
47        self.buffer_size
48    }
49
50    pub fn shrink(&mut self, max_free: usize) {
51        while self.free.len() > max_free {
52            self.free.pop();
53        }
54    }
55
56    pub fn clear(&mut self) {
57        self.free.clear();
58    }
59
60    pub fn is_empty(&self) -> bool {
61        self.free.is_empty()
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn test_new() {
71        let pool = BytePool::new(1024);
72        assert_eq!(pool.buffer_size(), 1024);
73        assert_eq!(pool.free_count(), 0);
74    }
75
76    #[test]
77    fn test_acquire() {
78        let mut pool = BytePool::new(256);
79        let buf = pool.acquire();
80        assert!(buf.is_empty());
81        assert_eq!(pool.total_allocated(), 1);
82    }
83
84    #[test]
85    fn test_release_and_reuse() {
86        let mut pool = BytePool::new(256);
87        let buf = pool.acquire();
88        pool.release(buf);
89        assert_eq!(pool.free_count(), 1);
90        let _buf2 = pool.acquire();
91        assert_eq!(pool.free_count(), 0);
92        assert_eq!(pool.total_allocated(), 1);
93    }
94
95    #[test]
96    fn test_shrink() {
97        let mut pool = BytePool::new(64);
98        let mut bufs = Vec::new();
99        for _ in 0..5 {
100            bufs.push(pool.acquire());
101        }
102        for buf in bufs {
103            pool.release(buf);
104        }
105        pool.shrink(2);
106        assert_eq!(pool.free_count(), 2);
107    }
108
109    #[test]
110    fn test_clear() {
111        let mut pool = BytePool::new(64);
112        let buf = pool.acquire();
113        pool.release(buf);
114        pool.clear();
115        assert!(pool.is_empty());
116    }
117
118    #[test]
119    fn test_multiple_acquire() {
120        let mut pool = BytePool::new(64);
121        let _a = pool.acquire();
122        let _b = pool.acquire();
123        assert_eq!(pool.total_allocated(), 2);
124    }
125
126    #[test]
127    fn test_released_buffer_cleared() {
128        let mut pool = BytePool::new(64);
129        let mut buf = pool.acquire();
130        buf.extend_from_slice(&[1, 2, 3]);
131        pool.release(buf);
132        let reused = pool.acquire();
133        assert!(reused.is_empty());
134    }
135
136    #[test]
137    fn test_is_empty() {
138        let pool = BytePool::new(64);
139        assert!(pool.is_empty());
140    }
141
142    #[test]
143    fn test_shrink_to_zero() {
144        let mut pool = BytePool::new(64);
145        let buf = pool.acquire();
146        pool.release(buf);
147        pool.shrink(0);
148        assert!(pool.is_empty());
149    }
150
151    #[test]
152    fn test_acquire_capacity() {
153        let mut pool = BytePool::new(512);
154        let buf = pool.acquire();
155        assert!(buf.capacity() >= 512);
156    }
157}