use alloc::string::String;
use crate::{Data, DecodeResult, FormatIns, FormatOptions, LocatedIns};
struct Formatter<'a, 'b> {
options: &'a FormatOptions,
formatter: &'a mut core::fmt::Formatter<'b>,
}
impl core::fmt::Write for Formatter<'_, '_> {
fn write_str(&mut self, value: &str) -> core::fmt::Result {
self.formatter.write_str(value)
}
}
impl FormatIns for Formatter<'_, '_> {
fn options(&self) -> &FormatOptions {
self.options
}
}
#[must_use = "display adapters must be formatted to produce output"]
pub struct DisplayIns<'a> {
located: LocatedIns<'a>,
options: &'a FormatOptions,
}
impl<'a> LocatedIns<'a> {
pub const fn display(self, options: &'a FormatOptions) -> DisplayIns<'a> {
DisplayIns { located: self, options }
}
}
impl core::fmt::Display for DisplayIns<'_> {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut out = Formatter { options: self.options, formatter };
out.write_ins(self.located.instruction(), self.located.address())
}
}
#[must_use = "display adapters must be formatted to produce output"]
pub struct DisplayDecode<'a> {
result: &'a DecodeResult,
address: u32,
options: &'a FormatOptions,
}
impl DecodeResult {
pub const fn display_at<'a>(
&'a self,
address: u32,
options: &'a FormatOptions,
) -> DisplayDecode<'a> {
DisplayDecode { result: self, address, options }
}
pub fn write_at<W: FormatIns + ?Sized>(&self, out: &mut W, address: u32) -> core::fmt::Result {
match self {
Self::Instruction(instruction) => out.write_ins(instruction, address),
Self::Unknown(word) => write!(out, ".word 0x{word:04x}"),
}
}
}
impl core::fmt::Display for DisplayDecode<'_> {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut out = Formatter { options: self.options, formatter };
self.result.write_at(&mut out, self.address)
}
}
#[must_use = "display adapters must be formatted to produce output"]
pub struct DisplayData<'a> {
data: &'a Data,
}
impl Data {
pub const fn display(&self) -> DisplayData<'_> {
DisplayData { data: self }
}
}
impl core::fmt::Display for DisplayData<'_> {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self.data {
Data::Byte(value) => write!(formatter, ".byte 0x{value:02x}"),
Data::Word(value) => write!(formatter, ".word 0x{value:04x}"),
Data::Long(value) => write!(formatter, ".long 0x{value:08x}"),
}
}
}
#[must_use = "formatters must be written to and consumed to produce output"]
pub struct StringFormatter {
options: FormatOptions,
string: String,
}
impl StringFormatter {
pub const fn new(options: FormatOptions) -> Self {
Self { options, string: String::new() }
}
pub fn clear(&mut self) {
self.string.clear();
}
pub fn as_str(&self) -> &str {
&self.string
}
pub fn into_string(self) -> String {
self.string
}
}
impl core::fmt::Write for StringFormatter {
fn write_str(&mut self, value: &str) -> core::fmt::Result {
self.string.push_str(value);
Ok(())
}
}
impl FormatIns for StringFormatter {
fn options(&self) -> &FormatOptions {
&self.options
}
}