xo65 0.1.0

Library for parsing cc65 object files (xo65 format)
Documentation
use xo65::{file::File, Xo65};

use crate::util::fmt_maybe_string;

pub trait Xo65Query<'data> {
    fn get_file(&self, idx: u32) -> Option<&File>;
    fn fmt_file(&self, idx: u32) -> FmtXo65File<'_, 'data>;

    #[allow(dead_code)]
    fn get_string(&self, idx: u32) -> Option<&'data [u8]>;
    fn fmt_string(&self, idx: u32) -> FmtXo65String<'_, 'data>;
}

impl<'data> Xo65Query<'data> for Xo65<'data> {
    fn get_file(&self, idx: u32) -> Option<&File> {
        self.file_table().get(idx as usize)
    }

    fn fmt_file(&self, idx: u32) -> FmtXo65File<'_, 'data> {
        FmtXo65File { obj: self, idx }
    }

    fn get_string(&self, idx: u32) -> Option<&'data [u8]> {
        self.string_table().get(idx as usize)
    }

    fn fmt_string(&self, idx: u32) -> FmtXo65String<'_, 'data> {
        FmtXo65String { obj: self, idx }
    }
}

#[derive(Debug)]
pub struct FmtXo65File<'a, 'data> {
    obj: &'a Xo65<'data>,
    idx: u32,
}

impl std::fmt::Display for FmtXo65File<'_, '_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if let Some(file) = self.obj.get_file(self.idx) {
            self.obj.fmt_string(file.name()).fmt(f)
        } else {
            write!(f, "{} (file index OUT OF RANGE)", self.idx)
        }
    }
}

#[derive(Debug)]
pub struct FmtXo65String<'a, 'data> {
    obj: &'a Xo65<'data>,
    idx: u32,
}

impl std::fmt::Display for FmtXo65String<'_, '_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if self.idx == 0 {
            // 文字列インデックス 0 は None として扱われる。
            write!(f, "<None>")
        } else if let Some(s) = self.obj.string_table().get(self.idx as usize) {
            fmt_maybe_string(s).fmt(f)
        } else {
            write!(f, "{} (string index OUT OF RANGE)", self.idx)
        }
    }
}