#![no_std]
#![cfg_attr(feature = "const_fn", feature(const_fn))]
#[derive(Debug)]
pub struct LogBuffer<T: AsRef<[u8]> + AsMut<[u8]>> {
buffer: T,
position: usize
}
impl<T: AsRef<[u8]> + AsMut<[u8]>> LogBuffer<T> {
pub fn new(storage: T) -> LogBuffer<T> {
let mut buffer = LogBuffer { buffer: storage, position: 0 };
buffer.clear();
buffer
}
#[cfg(feature = "const_fn")]
pub const fn uninitialized(storage: T) -> LogBuffer<T> {
LogBuffer { buffer: storage, position: 0 }
}
pub fn clear(&mut self) {
self.position = 0;
for b in self.buffer.as_mut().iter_mut() {
*b = 0xff;
}
}
pub fn is_empty(&self) -> bool {
let buffer = self.buffer.as_ref();
self.position == 0 &&
(buffer.len() == 0 || buffer[buffer.len() - 1] == 0xff)
}
fn rotate(&mut self) {
self.buffer.as_mut().rotate_left(self.position);
self.position = 0;
}
pub fn extract(&mut self) -> &str {
self.rotate();
fn is_utf8_leader(byte: u8) -> bool {
byte & 0b10000000 == 0b00000000 ||
byte & 0b11100000 == 0b11000000 ||
byte & 0b11110000 == 0b11100000 ||
byte & 0b11111000 == 0b11110000
}
let buffer = self.buffer.as_mut();
for i in 0..buffer.len() {
if is_utf8_leader(buffer[i]) {
return core::str::from_utf8(&buffer[i..]).unwrap()
}
}
return ""
}
pub fn extract_lines(&mut self) -> core::str::Lines {
self.rotate();
let buffer = self.buffer.as_mut();
for i in 0..buffer.len() {
if i > 0 && buffer[i - 1] == b'\n' {
let slice = core::str::from_utf8(&buffer[i..]).unwrap();
return slice.lines()
}
}
return "".lines()
}
}
impl<T: AsRef<[u8]> + AsMut<[u8]>> core::fmt::Write for LogBuffer<T> {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
for &b in s.as_bytes() {
self.buffer.as_mut()[self.position] = b;
self.position = (self.position + 1) % self.buffer.as_mut().len()
}
Ok(())
}
}