#![warn( clippy::correctness, clippy::nursery, clippy::unnecessary_cast, clippy::all, clippy::suspicious, clippy::perf, rustdoc::missing_errors_doc, rustdoc::missing_panics_doc )] use std::fs::File; use std::io::{Read, Seek, SeekFrom}; use proc_macro::TokenStream; use quote::quote; use syn::{LitStr, parse_macro_input}; extern crate proc_macro; #[proc_macro] pub fn include_font(item: TokenStream) -> TokenStream { let filename = parse_macro_input!(item as LitStr); let file_path = filename.value(); println!("Loading font: [{}]", file_path); let font_bytes = match load_file(file_path) { Ok(bytes) => bytes, Err(why) => panic!("{}", why), }; let font_data = match Font::new(font_bytes) { Ok(font) => font.0, Err(why) => panic!("{}", why), }; quote!( [ #( [#(#font_data),*] ),* ] ) .into() } struct Font([[u8; 16]; 512]); impl Font { const MAGIC: u16 = 0x3604; pub fn new(data: [u8; (32 + 2) * 512 + 4]) -> Result { let magic: u16 = (data[0] as u16) << 8 | data[1] as u16; let mode = data[2]; let size = data[3]; if magic != Self::MAGIC { return Err("Magic value is invalid!"); } let has_512_glyphs = (mode & 0x01) != 0; let mut glyphs = [[0; 16]; 512]; let glyph_count = if has_512_glyphs { 512 } else { 256 }; for i in 0..(glyph_count as usize) { let mut buff: [u8; 16] = [0; 16]; for j in 0..(size as usize) { buff[j] = data[4 + i * (size as usize) + j]; } glyphs[i] = buff; } Ok(Self(glyphs)) } } type FileContents = [u8; (32 + 2) * 512 + 4]; fn load_file(filename: String) -> Result { let mut buf = [0; (32 + 2) * 512 + 4]; let mut f = File::open(filename).unwrap(); f.seek(SeekFrom::Start(0)).unwrap(); loop { match f.read(&mut buf) { Ok(read) => { if read == 0 { break; } } Err(why) => { eprintln!("Failed to read PS1 font file: {}", why); return Err(why); } } } Ok(buf) }