use std::fmt;
use crate::{sanitize_variable_name, Flags};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct RustVariables {
name: String,
width: u32,
height: u32,
flags: Flags,
data: Vec<u8>,
}
impl RustVariables {
pub fn new(
name: impl Into<String>,
width: u32,
height: u32,
flags: Flags,
data: Vec<u8>,
) -> Self {
Self {
name: name.into(),
width,
height,
flags,
data,
}
}
pub fn name(&self) -> &str {
self.name.as_ref()
}
pub fn width(&self) -> u32 {
self.width
}
pub fn height(&self) -> u32 {
self.height
}
pub fn flags(&self) -> Flags {
self.flags
}
pub fn data(&self) -> &[u8] {
self.data.as_ref()
}
}
impl fmt::Display for RustVariables {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let name = sanitize_variable_name(&self.name);
writeln!(f, "const {}_WIDTH: u32 = {};", name, self.width)?;
writeln!(f, "const {}_HEIGHT: u32 = {};", name, self.height)?;
write!(f, "const {}_FLAGS: u32 = {};", name, self.flags.value())?;
writeln!(f, " // {}", self.flags.human_readable_value())?;
write!(f, "const {}: [u8; {}] = [", name, self.data.len())?;
if let Some(byte) = self.data.first() {
if f.alternate() {
write!(f, "{:#010b}", byte)?;
} else {
write!(f, "{:#04x}", byte)?;
}
}
for byte in self.data.iter().skip(1) {
if f.alternate() {
write!(f, ", {:#010b}", byte)?;
} else {
write!(f, ", {:#04x}", byte)?;
}
}
writeln!(f, "];")?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Flags;
#[test]
fn to_string() {
let rust_variables = RustVariables::new(
"some_name",
10,
12,
Flags::OneBitPerPixel,
vec![0x01, 0x02, 0x04, 0x1f],
);
let rust_code = rust_variables.to_string();
let expected = "const SOME_NAME_WIDTH: u32 = 10;
const SOME_NAME_HEIGHT: u32 = 12;
const SOME_NAME_FLAGS: u32 = 0; // BLIT_1BPP
const SOME_NAME: [u8; 4] = [0x01, 0x02, 0x04, 0x1f];\n";
assert_eq!(rust_code, expected);
}
#[test]
fn to_string_two_bits_per_pixel() {
let rust_variables = RustVariables::new(
"some_name",
10,
12,
Flags::TwoBitsPerPixel,
vec![0x01, 0x02, 0x04, 0x1f],
);
let rust_code = rust_variables.to_string();
let expected = "const SOME_NAME_WIDTH: u32 = 10;
const SOME_NAME_HEIGHT: u32 = 12;
const SOME_NAME_FLAGS: u32 = 1; // BLIT_2BPP
const SOME_NAME: [u8; 4] = [0x01, 0x02, 0x04, 0x1f];\n";
assert_eq!(rust_code, expected);
}
#[test]
fn format() {
let rust_variables = RustVariables::new(
"some_name",
10,
12,
Flags::OneBitPerPixel,
vec![0x01, 0x02, 0x04, 0x1f],
);
let rust_code = format!("{}", rust_variables);
let expected = "const SOME_NAME_WIDTH: u32 = 10;
const SOME_NAME_HEIGHT: u32 = 12;
const SOME_NAME_FLAGS: u32 = 0; // BLIT_1BPP
const SOME_NAME: [u8; 4] = [0x01, 0x02, 0x04, 0x1f];\n";
assert_eq!(rust_code, expected);
}
#[test]
fn format_alternate() {
let rust_variables = RustVariables::new(
"some_name",
10,
12,
Flags::OneBitPerPixel,
vec![0x01, 0x02, 0x04, 0x1f],
);
let rust_code = format!("{:#}", rust_variables);
let expected = "const SOME_NAME_WIDTH: u32 = 10;
const SOME_NAME_HEIGHT: u32 = 12;
const SOME_NAME_FLAGS: u32 = 0; // BLIT_1BPP
const SOME_NAME: [u8; 4] = [0b00000001, 0b00000010, 0b00000100, 0b00011111];\n";
assert_eq!(rust_code, expected);
}
}