use crate::pixel::MAX_FORMATTED_PIXEL_SIZE_NEWLINE;
use crate::Pixel;
use std::io::Write;
use std::iter::FromIterator;
use std::sync::Arc;
pub static PIXEL_BUFFER_DEFAULT_CAPACITY: usize = 8 * 1024;
pub struct PixelBuffer {
buffer: Vec<u8>,
number_writer: NumberWriter,
}
impl PixelBuffer {
pub fn with_capacity(capacity: usize) -> PixelBuffer {
PixelBuffer {
buffer: Vec::with_capacity(capacity),
number_writer: NumberWriter::default(),
}
}
pub fn with_capacity_pixels(pixels: usize) -> PixelBuffer {
Self::with_capacity(pixels * MAX_FORMATTED_PIXEL_SIZE_NEWLINE)
}
pub fn new() -> PixelBuffer {
Self::with_capacity(PIXEL_BUFFER_DEFAULT_CAPACITY)
}
pub fn as_slice(&self) -> &[u8] {
self.as_ref()
}
pub fn is_empty(&self) -> bool {
self.buffer.is_empty()
}
pub fn is_capacity_reached(&self) -> bool {
self.buffer.capacity() < self.buffer.len() + MAX_FORMATTED_PIXEL_SIZE_NEWLINE
}
pub fn clear(&mut self) {
self.buffer.clear();
}
pub fn write_pixel(&mut self, pixel: &Pixel) {
let (x, y) = pixel.position.into();
let color = pixel.color;
self.buffer.write_all(b"PX ").unwrap();
self.number_writer
.write_decimal(&mut self.buffer, x as usize)
.unwrap();
self.buffer.write_all(b" ").unwrap();
self.number_writer
.write_decimal(&mut self.buffer, y as usize)
.unwrap();
self.buffer.write_all(b" ").unwrap();
self.number_writer
.write_hex02(&mut self.buffer, color.r)
.unwrap();
self.number_writer
.write_hex02(&mut self.buffer, color.g)
.unwrap();
self.number_writer
.write_hex02(&mut self.buffer, color.b)
.unwrap();
if let Some(a) = color.a {
self.number_writer.write_hex02(&mut self.buffer, a).unwrap();
}
self.buffer.write_all(b"\n").unwrap();
}
}
impl Default for PixelBuffer {
fn default() -> PixelBuffer {
PixelBuffer::new()
}
}
impl AsRef<[u8]> for PixelBuffer {
fn as_ref(&self) -> &[u8] {
self.buffer.as_slice()
}
}
impl<P: Into<Pixel>> FromIterator<P> for PixelBuffer {
fn from_iter<T: IntoIterator<Item = P>>(iter: T) -> Self {
let mut buffer = PixelBuffer::new();
for pixel in iter.into_iter() {
buffer.write_pixel(&pixel.into());
}
buffer
}
}
lazy_static! {
static ref NUMBER_WRITER: NumberWriter = NumberWriter::create();
}
static NUMBER_WRITER_DEFAULT_MAX_DECIMAL: usize = 4096;
#[derive(Clone)]
struct NumberWriter {
hex02: Arc<[[u8; 2]; 256]>,
decimal: Arc<Vec<String>>,
}
impl NumberWriter {
pub fn with_decimal_size(decimal_size: usize) -> NumberWriter {
let mut hex02 = [[0u8; 2]; 256];
for (i, item) in hex02.iter_mut().enumerate() {
let str = format!("{:02x}", i);
item[0] = str.as_bytes()[0];
item[1] = str.as_bytes()[1];
}
let mut decimal = Vec::new();
for i in 0..decimal_size {
decimal.push(format!("{}", i));
}
NumberWriter {
hex02: Arc::new(hex02),
decimal: Arc::new(decimal),
}
}
pub(crate) fn create() -> NumberWriter {
Self::with_decimal_size(NUMBER_WRITER_DEFAULT_MAX_DECIMAL)
}
pub fn write_hex02(&self, mut writer: impl Write, value: u8) -> std::io::Result<()> {
writer.write_all(&self.hex02[value as usize][..])
}
pub fn write_decimal(&self, mut writer: impl Write, value: usize) -> std::io::Result<()> {
if value < self.decimal.len() {
writer.write_all(self.decimal[value].as_bytes())
} else {
panic!("value is to large");
}
}
}
impl Default for NumberWriter {
fn default() -> Self {
NUMBER_WRITER.clone()
}
}
#[cfg(test)]
mod test {
use crate::{Pixel, PixelBuffer};
#[test]
fn pixelbuffer_from_iter() {
let v = vec![
Pixel::from(((12, 34), (255, 0, 10))),
Pixel::from(((12, 35), (0, 255, 10))),
];
let buffer: PixelBuffer = v.into_iter().collect();
assert_eq!(buffer.as_slice(), b"PX 12 34 ff000a\nPX 12 35 00ff0a\n");
}
}