xchecker_runner/
ring_buffer.rs1use std::collections::VecDeque;
4use std::fmt;
5
6#[derive(Debug, Clone)]
8pub struct RingBuffer {
9 buffer: VecDeque<u8>,
10 max_bytes: usize,
11 total_bytes_written: usize,
12}
13
14impl RingBuffer {
15 #[must_use]
17 pub fn new(max_bytes: usize) -> Self {
18 Self {
19 buffer: VecDeque::with_capacity(max_bytes.min(8192)),
20 max_bytes,
21 total_bytes_written: 0,
22 }
23 }
24
25 pub fn write(&mut self, data: &[u8]) {
29 self.total_bytes_written += data.len();
30
31 for &byte in data {
32 if self.buffer.len() >= self.max_bytes {
33 self.buffer.pop_front();
35 }
36 self.buffer.push_back(byte);
37 }
38 }
39
40 #[must_use]
42 #[allow(dead_code)] pub fn len(&self) -> usize {
44 self.buffer.len()
45 }
46
47 #[must_use]
49 #[allow(dead_code)] pub fn is_empty(&self) -> bool {
51 self.buffer.is_empty()
52 }
53
54 #[must_use]
56 pub const fn total_bytes_written(&self) -> usize {
57 self.total_bytes_written
58 }
59
60 #[must_use]
62 pub const fn was_truncated(&self) -> bool {
63 self.total_bytes_written > self.max_bytes
64 }
65}
66
67impl fmt::Display for RingBuffer {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 let bytes: Vec<u8> = self.buffer.iter().copied().collect();
70 write!(f, "{}", String::from_utf8_lossy(&bytes))
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn test_ring_buffer_basic() {
80 let mut buffer = RingBuffer::new(10);
81 buffer.write(b"hello");
82 assert_eq!(buffer.to_string(), "hello");
83 assert_eq!(buffer.len(), 5);
84 assert!(!buffer.is_empty());
85 }
86
87 #[test]
88 fn test_ring_buffer_truncation() {
89 let mut buffer = RingBuffer::new(10);
90 buffer.write(b"hello");
91 buffer.write(b"world");
92 buffer.write(b"!");
93
94 assert_eq!(buffer.len(), 10);
96 assert_eq!(buffer.to_string(), "elloworld!");
97 assert_eq!(buffer.total_bytes_written(), 11);
98 assert!(buffer.was_truncated());
99 }
100
101 #[test]
102 fn test_ring_buffer_large_write() {
103 let mut buffer = RingBuffer::new(5);
104 buffer.write(b"hello world");
105
106 assert_eq!(buffer.len(), 5);
108 assert_eq!(buffer.to_string(), "world");
109 assert_eq!(buffer.total_bytes_written(), 11);
110 assert!(buffer.was_truncated());
111 }
112
113 #[test]
114 fn test_ring_buffer_exact_capacity() {
115 let mut buffer = RingBuffer::new(10);
116 buffer.write(b"1234567890");
117
118 assert_eq!(buffer.len(), 10);
119 assert_eq!(buffer.to_string(), "1234567890");
120 assert!(!buffer.was_truncated());
121 }
122
123 #[test]
124 fn test_ring_buffer_multiple_writes() {
125 let mut buffer = RingBuffer::new(10);
126 buffer.write(b"12345");
127 buffer.write(b"67890");
128 buffer.write(b"ABCDE");
129
130 assert_eq!(buffer.len(), 10);
132 assert_eq!(buffer.to_string(), "67890ABCDE");
133 assert_eq!(buffer.total_bytes_written(), 15);
134 assert!(buffer.was_truncated());
135 }
136
137 #[test]
138 fn test_ring_buffer_empty() {
139 let buffer = RingBuffer::new(10);
140 assert!(buffer.is_empty());
141 assert_eq!(buffer.len(), 0);
142 assert_eq!(buffer.to_string(), "");
143 assert!(!buffer.was_truncated());
144 }
145
146 #[test]
147 fn test_ring_buffer_utf8_handling() {
148 let mut buffer = RingBuffer::new(20);
149 buffer.write("Hello 世界".as_bytes());
150 assert_eq!(buffer.to_string(), "Hello 世界");
151 }
152
153 #[test]
154 fn test_ring_buffer_invalid_utf8() {
155 let mut buffer = RingBuffer::new(10);
156 buffer.write(&[0xFF, 0xFE, 0xFD]);
158 let result = buffer.to_string();
160 assert!(!result.is_empty());
161 }
162}