Skip to main content

oxihuman_core/
output_buffer.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5/// A growable output buffer for accumulating byte data.
6#[allow(dead_code)]
7pub struct OutputBuffer {
8    data: Vec<u8>,
9    flush_count: u32,
10}
11
12#[allow(dead_code)]
13impl OutputBuffer {
14    pub fn new() -> Self {
15        Self {
16            data: Vec::new(),
17            flush_count: 0,
18        }
19    }
20    pub fn with_capacity(cap: usize) -> Self {
21        Self {
22            data: Vec::with_capacity(cap),
23            flush_count: 0,
24        }
25    }
26    pub fn write_bytes(&mut self, bytes: &[u8]) {
27        self.data.extend_from_slice(bytes);
28    }
29    pub fn write_str(&mut self, s: &str) {
30        self.data.extend_from_slice(s.as_bytes());
31    }
32    pub fn write_u8(&mut self, v: u8) {
33        self.data.push(v);
34    }
35    pub fn write_u32_le(&mut self, v: u32) {
36        self.data.extend_from_slice(&v.to_le_bytes());
37    }
38    pub fn flush(&mut self) -> Vec<u8> {
39        self.flush_count += 1;
40        std::mem::take(&mut self.data)
41    }
42    pub fn peek(&self) -> &[u8] {
43        &self.data
44    }
45    pub fn len(&self) -> usize {
46        self.data.len()
47    }
48    pub fn is_empty(&self) -> bool {
49        self.data.is_empty()
50    }
51    pub fn flush_count(&self) -> u32 {
52        self.flush_count
53    }
54    pub fn clear(&mut self) {
55        self.data.clear();
56    }
57    pub fn capacity(&self) -> usize {
58        self.data.capacity()
59    }
60    pub fn as_str_lossy(&self) -> std::borrow::Cow<'_, str> {
61        String::from_utf8_lossy(&self.data)
62    }
63}
64
65impl Default for OutputBuffer {
66    fn default() -> Self {
67        Self::new()
68    }
69}
70
71#[allow(dead_code)]
72pub fn new_output_buffer() -> OutputBuffer {
73    OutputBuffer::new()
74}
75#[allow(dead_code)]
76pub fn ob_write_bytes(b: &mut OutputBuffer, bytes: &[u8]) {
77    b.write_bytes(bytes);
78}
79#[allow(dead_code)]
80pub fn ob_write_str(b: &mut OutputBuffer, s: &str) {
81    b.write_str(s);
82}
83#[allow(dead_code)]
84pub fn ob_write_u8(b: &mut OutputBuffer, v: u8) {
85    b.write_u8(v);
86}
87#[allow(dead_code)]
88pub fn ob_flush(b: &mut OutputBuffer) -> Vec<u8> {
89    b.flush()
90}
91#[allow(dead_code)]
92pub fn ob_peek(b: &OutputBuffer) -> &[u8] {
93    b.peek()
94}
95#[allow(dead_code)]
96pub fn ob_len(b: &OutputBuffer) -> usize {
97    b.len()
98}
99#[allow(dead_code)]
100pub fn ob_is_empty(b: &OutputBuffer) -> bool {
101    b.is_empty()
102}
103#[allow(dead_code)]
104pub fn ob_clear(b: &mut OutputBuffer) {
105    b.clear();
106}
107#[allow(dead_code)]
108pub fn ob_flush_count(b: &OutputBuffer) -> u32 {
109    b.flush_count()
110}
111
112#[cfg(test)]
113mod tests {
114    use super::*;
115    #[test]
116    fn test_write_str_peek() {
117        let mut b = new_output_buffer();
118        ob_write_str(&mut b, "hello");
119        assert_eq!(ob_peek(&b), b"hello");
120    }
121    #[test]
122    fn test_write_bytes() {
123        let mut b = new_output_buffer();
124        ob_write_bytes(&mut b, &[1, 2, 3]);
125        assert_eq!(ob_len(&b), 3);
126    }
127    #[test]
128    fn test_flush_clears() {
129        let mut b = new_output_buffer();
130        ob_write_str(&mut b, "abc");
131        let out = ob_flush(&mut b);
132        assert_eq!(out, b"abc");
133        assert!(ob_is_empty(&b));
134    }
135    #[test]
136    fn test_flush_count() {
137        let mut b = new_output_buffer();
138        ob_flush(&mut b);
139        ob_flush(&mut b);
140        assert_eq!(ob_flush_count(&b), 2);
141    }
142    #[test]
143    fn test_write_u8() {
144        let mut b = new_output_buffer();
145        ob_write_u8(&mut b, 42);
146        assert_eq!(ob_peek(&b), &[42u8]);
147    }
148    #[test]
149    fn test_write_u32_le() {
150        let mut b = new_output_buffer();
151        b.write_u32_le(0x01020304);
152        assert_eq!(b.len(), 4);
153        assert_eq!(b.peek()[0], 0x04);
154    }
155    #[test]
156    fn test_clear() {
157        let mut b = new_output_buffer();
158        ob_write_str(&mut b, "data");
159        ob_clear(&mut b);
160        assert!(ob_is_empty(&b));
161    }
162    #[test]
163    fn test_is_empty_initially() {
164        let b = new_output_buffer();
165        assert!(ob_is_empty(&b));
166    }
167    #[test]
168    fn test_len_accumulates() {
169        let mut b = new_output_buffer();
170        ob_write_str(&mut b, "abc");
171        ob_write_str(&mut b, "de");
172        assert_eq!(ob_len(&b), 5);
173    }
174    #[test]
175    fn test_as_str_lossy() {
176        let mut b = new_output_buffer();
177        ob_write_str(&mut b, "rust");
178        let s = b.as_str_lossy();
179        assert_eq!(s.as_ref(), "rust");
180    }
181}