rocketsplash-rt 0.3.0

Runtime library for loading and rendering Rocketsplash assets (.rst, .rsf)
Documentation
// <FILE>crates/rocketsplash-rt/src/splash/fnc_load_splash.rs</FILE>
// <DESC>Splash deserialization and validation</DESC>
// <VERS>VERSION: 2.1.0</VERS>
// <WCTX>Foundation crates 0.3.0 (RELEASE_PLAN D3 hardening, F2 cycle-break)</WCTX>
// <CLOG>2.1.0: house Splash::load/from_bytes here beside the loader; direct sibling import (F2). 2.0.0: delegate decode/version/structural checks to rocketsplash_formats::read_splash. 1.0.1: align Splash construction with updated struct fields.</CLOG>

use std::path::Path;

use log::debug;
use rocketsplash_formats::{read_splash, CellStyle};

use crate::render::{RenderBuffer, RenderCell};
use crate::splash::cls_splash::Splash;
use crate::{Error, TextStyle};

impl Splash {
    pub fn load(path: impl AsRef<Path>) -> Result<Self, Error> {
        let bytes = std::fs::read(path)?;
        load_splash_from_bytes(&bytes)
    }

    pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
        load_splash_from_bytes(bytes)
    }
}

pub fn load_splash_from_bytes(bytes: &[u8]) -> Result<Splash, Error> {
    // read_splash enforces the size cap, version window, and cell-count
    // structure (RELEASE_PLAN D3).
    let splash = read_splash(bytes)?;

    let width = splash.width as usize;
    let height = splash.height as usize;
    let mut buffer = RenderBuffer::new(width, height);
    for (idx, cell) in splash.cells.iter().enumerate() {
        if idx >= buffer.cells.len() {
            break;
        }
        let mut render_cell = RenderCell::empty();
        render_cell.ch = cell.ch;
        render_cell.fg = cell.fg;
        render_cell.bg = cell.bg;
        render_cell.style = to_text_style(cell.style);
        render_cell.opacity = if cell.ch == ' ' { 0 } else { 255 };
        buffer.cells[idx] = render_cell;
    }

    debug!("Loaded splash {} ({}x{})", splash.meta.name, width, height);

    Ok(Splash {
        meta: splash.meta,
        buffer,
    })
}

fn to_text_style(style: CellStyle) -> TextStyle {
    let mut text_style = TextStyle::empty();
    if style.contains(CellStyle::BOLD) {
        text_style |= TextStyle::BOLD;
    }
    if style.contains(CellStyle::ITALIC) {
        text_style |= TextStyle::ITALIC;
    }
    if style.contains(CellStyle::UNDERLINE) {
        text_style |= TextStyle::UNDERLINE;
    }
    if style.contains(CellStyle::REVERSE) {
        text_style |= TextStyle::REVERSE;
    }
    text_style
}

// <FILE>crates/rocketsplash-rt/src/splash/fnc_load_splash.rs</FILE>
// <VERS>END OF VERSION: 2.0.0</VERS>