Skip to main content

oxihuman_core/
cursor_writer.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5/// A byte-buffer writer with a movable cursor position.
6#[allow(dead_code)]
7#[derive(Debug, Clone)]
8pub struct CursorWriter {
9    buffer: Vec<u8>,
10    position: usize,
11}
12
13impl Default for CursorWriter {
14    fn default() -> Self {
15        Self::new()
16    }
17}
18
19#[allow(dead_code)]
20impl CursorWriter {
21    pub fn new() -> Self {
22        Self {
23            buffer: Vec::new(),
24            position: 0,
25        }
26    }
27
28    pub fn with_capacity(cap: usize) -> Self {
29        Self {
30            buffer: Vec::with_capacity(cap),
31            position: 0,
32        }
33    }
34
35    pub fn write_u8(&mut self, v: u8) {
36        self.ensure_capacity(1);
37        self.buffer[self.position] = v;
38        self.position += 1;
39    }
40
41    pub fn write_u16_le(&mut self, v: u16) {
42        let bytes = v.to_le_bytes();
43        self.ensure_capacity(2);
44        self.buffer[self.position] = bytes[0];
45        self.buffer[self.position + 1] = bytes[1];
46        self.position += 2;
47    }
48
49    pub fn write_u32_le(&mut self, v: u32) {
50        let bytes = v.to_le_bytes();
51        self.ensure_capacity(4);
52        self.buffer[self.position..self.position + 4].copy_from_slice(&bytes);
53        self.position += 4;
54    }
55
56    pub fn write_f32_le(&mut self, v: f32) {
57        self.write_u32_le(v.to_bits());
58    }
59
60    pub fn write_bytes(&mut self, data: &[u8]) {
61        self.ensure_capacity(data.len());
62        self.buffer[self.position..self.position + data.len()].copy_from_slice(data);
63        self.position += data.len();
64    }
65
66    fn ensure_capacity(&mut self, additional: usize) {
67        let needed = self.position + additional;
68        if needed > self.buffer.len() {
69            self.buffer.resize(needed, 0);
70        }
71    }
72
73    pub fn position(&self) -> usize {
74        self.position
75    }
76
77    pub fn set_position(&mut self, pos: usize) {
78        self.position = pos;
79    }
80
81    pub fn seek_start(&mut self) {
82        self.position = 0;
83    }
84
85    pub fn seek_end(&mut self) {
86        self.position = self.buffer.len();
87    }
88
89    pub fn len(&self) -> usize {
90        self.buffer.len()
91    }
92
93    pub fn is_empty(&self) -> bool {
94        self.buffer.is_empty()
95    }
96
97    pub fn as_bytes(&self) -> &[u8] {
98        &self.buffer
99    }
100
101    pub fn into_bytes(self) -> Vec<u8> {
102        self.buffer
103    }
104
105    pub fn clear(&mut self) {
106        self.buffer.clear();
107        self.position = 0;
108    }
109
110    pub fn remaining(&self) -> usize {
111        self.buffer.len().saturating_sub(self.position)
112    }
113}
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118
119    #[test]
120    fn test_new_empty() {
121        let cw = CursorWriter::new();
122        assert!(cw.is_empty());
123        assert_eq!(cw.position(), 0);
124    }
125
126    #[test]
127    fn test_write_u8() {
128        let mut cw = CursorWriter::new();
129        cw.write_u8(0xAB);
130        assert_eq!(cw.as_bytes(), &[0xAB]);
131        assert_eq!(cw.position(), 1);
132    }
133
134    #[test]
135    fn test_write_u16_le() {
136        let mut cw = CursorWriter::new();
137        cw.write_u16_le(0x0102);
138        assert_eq!(cw.as_bytes(), &[0x02, 0x01]);
139    }
140
141    #[test]
142    fn test_write_u32_le() {
143        let mut cw = CursorWriter::new();
144        cw.write_u32_le(1);
145        assert_eq!(cw.as_bytes(), &[1, 0, 0, 0]);
146    }
147
148    #[test]
149    fn test_write_f32_le() {
150        let mut cw = CursorWriter::new();
151        let val: f32 = 1.0;
152        cw.write_f32_le(val);
153        let bits = u32::from_le_bytes([
154            cw.as_bytes()[0],
155            cw.as_bytes()[1],
156            cw.as_bytes()[2],
157            cw.as_bytes()[3],
158        ]);
159        assert!((f32::from_bits(bits) - val).abs() < f32::EPSILON);
160    }
161
162    #[test]
163    fn test_write_bytes() {
164        let mut cw = CursorWriter::new();
165        cw.write_bytes(&[1, 2, 3]);
166        assert_eq!(cw.as_bytes(), &[1, 2, 3]);
167    }
168
169    #[test]
170    fn test_seek() {
171        let mut cw = CursorWriter::new();
172        cw.write_bytes(&[1, 2, 3]);
173        cw.seek_start();
174        assert_eq!(cw.position(), 0);
175        cw.seek_end();
176        assert_eq!(cw.position(), 3);
177    }
178
179    #[test]
180    fn test_overwrite() {
181        let mut cw = CursorWriter::new();
182        cw.write_bytes(&[0, 0, 0]);
183        cw.set_position(1);
184        cw.write_u8(0xFF);
185        assert_eq!(cw.as_bytes(), &[0, 0xFF, 0]);
186    }
187
188    #[test]
189    fn test_clear() {
190        let mut cw = CursorWriter::new();
191        cw.write_u8(1);
192        cw.clear();
193        assert!(cw.is_empty());
194        assert_eq!(cw.position(), 0);
195    }
196
197    #[test]
198    fn test_remaining() {
199        let mut cw = CursorWriter::new();
200        cw.write_bytes(&[1, 2, 3, 4]);
201        cw.set_position(1);
202        assert_eq!(cw.remaining(), 3);
203    }
204}