use alloc::sync::Arc;
use core::{error, fmt};
#[cfg(feature = "pyo3")]
use pyo3::prelude::*;
use crate::{
addresses::{Rom, Size, Vram},
context::OwnedSegmentNotFoundError,
metadata::{segment_metadata::AddSymbolError, AddLabelError},
section_type::SectionType,
symbols::SymbolCreationError,
};
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
#[cfg_attr(feature = "pyo3", pyclass(module = "spimdisasm"))]
pub enum SectionCreationError {
OwnedSegmentNotFound(OwnedSegmentNotFoundError),
AddSymbol(AddSymbolError),
AddLabel(AddLabelError),
EmptySection(EmptySectionError),
BadBytesSize(BadBytesSizeError),
UnalignedVram(UnalignedVramError),
UnalignedRom(UnalignedRomError),
RomVramAlignmentMismatch(RomVramAlignmentMismatchError),
AlreadyCreated(SectionAlreadyCreatedError),
NotPrehated(SectionNotPreheatedError),
BadUserSymbolSize(BadUserSymbolSizeError),
}
impl fmt::Display for SectionCreationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SectionCreationError::OwnedSegmentNotFound(x) => {
write!(f, "{x}")
}
SectionCreationError::AddSymbol(x) => write!(f, "{x}"),
SectionCreationError::AddLabel(x) => write!(f, "{x}"),
SectionCreationError::EmptySection(x) => write!(f, "{x}"),
SectionCreationError::BadBytesSize(x) => write!(f, "{x}"),
SectionCreationError::UnalignedVram(x) => write!(f, "{x}"),
SectionCreationError::UnalignedRom(x) => write!(f, "{x}"),
SectionCreationError::RomVramAlignmentMismatch(x) => write!(f, "{x}"),
SectionCreationError::AlreadyCreated(x) => write!(f, "{x}"),
SectionCreationError::NotPrehated(x) => write!(f, "{x}"),
SectionCreationError::BadUserSymbolSize(x) => write!(f, "{x}"),
}
}
}
impl error::Error for SectionCreationError {}
impl From<SymbolCreationError> for SectionCreationError {
fn from(value: SymbolCreationError) -> Self {
match value {
SymbolCreationError::OwnedSegmentNotFound(x) => {
SectionCreationError::OwnedSegmentNotFound(x)
}
SymbolCreationError::AddSymbol(x) => SectionCreationError::AddSymbol(x),
SymbolCreationError::AddLabel(x) => SectionCreationError::AddLabel(x),
}
}
}
impl From<OwnedSegmentNotFoundError> for SectionCreationError {
fn from(value: OwnedSegmentNotFoundError) -> Self {
SectionCreationError::OwnedSegmentNotFound(value)
}
}
impl From<AddSymbolError> for SectionCreationError {
fn from(value: AddSymbolError) -> Self {
SectionCreationError::AddSymbol(value)
}
}
impl From<EmptySectionError> for SectionCreationError {
fn from(value: EmptySectionError) -> Self {
SectionCreationError::EmptySection(value)
}
}
impl From<BadBytesSizeError> for SectionCreationError {
fn from(value: BadBytesSizeError) -> Self {
SectionCreationError::BadBytesSize(value)
}
}
impl From<UnalignedVramError> for SectionCreationError {
fn from(value: UnalignedVramError) -> Self {
SectionCreationError::UnalignedVram(value)
}
}
impl From<UnalignedRomError> for SectionCreationError {
fn from(value: UnalignedRomError) -> Self {
SectionCreationError::UnalignedRom(value)
}
}
impl From<RomVramAlignmentMismatchError> for SectionCreationError {
fn from(value: RomVramAlignmentMismatchError) -> Self {
SectionCreationError::RomVramAlignmentMismatch(value)
}
}
impl From<SectionAlreadyCreatedError> for SectionCreationError {
fn from(value: SectionAlreadyCreatedError) -> Self {
SectionCreationError::AlreadyCreated(value)
}
}
impl From<SectionNotPreheatedError> for SectionCreationError {
fn from(value: SectionNotPreheatedError) -> Self {
SectionCreationError::NotPrehated(value)
}
}
impl From<BadUserSymbolSizeError> for SectionCreationError {
fn from(value: BadUserSymbolSizeError) -> Self {
SectionCreationError::BadUserSymbolSize(value)
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
#[cfg_attr(feature = "pyo3", pyclass(module = "spimdisasm"))]
pub struct EmptySectionError {
name: Arc<str>,
vram: Vram,
}
impl EmptySectionError {
pub(crate) fn new(name: Arc<str>, vram: Vram) -> Self {
Self { name, vram }
}
}
impl fmt::Display for EmptySectionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Can't initialize section '{}' ({:?}) with empty bytes.",
self.name, self.vram
)
}
}
impl error::Error for EmptySectionError {}
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
#[cfg_attr(feature = "pyo3", pyclass(module = "spimdisasm"))]
pub struct BadBytesSizeError {
name: Arc<str>,
size: usize,
multiple_of: usize,
}
impl BadBytesSizeError {
pub(crate) fn new(name: Arc<str>, size: usize, multiple_of: usize) -> Self {
Self {
name,
size,
multiple_of,
}
}
}
impl fmt::Display for BadBytesSizeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Can't create section {} because the bytes length (0x{:X}) is not a multiple of 0x{:X}.", self.name, self.size, self.multiple_of)
}
}
impl error::Error for BadBytesSizeError {}
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
#[cfg_attr(feature = "pyo3", pyclass(module = "spimdisasm"))]
pub struct UnalignedVramError {
name: Arc<str>,
vram: Vram,
multiple_of: usize,
}
impl UnalignedVramError {
pub(crate) fn new(name: Arc<str>, vram: Vram, multiple_of: usize) -> Self {
Self {
name,
vram,
multiple_of,
}
}
}
impl fmt::Display for UnalignedVramError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Can't create section {} because the vram ({:?}) is not aligned to 0x{:X}.",
self.name, self.vram, self.multiple_of
)
}
}
impl error::Error for UnalignedVramError {}
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
#[cfg_attr(feature = "pyo3", pyclass(module = "spimdisasm"))]
pub struct UnalignedRomError {
name: Arc<str>,
rom: Rom,
multiple_of: usize,
}
impl UnalignedRomError {
pub(crate) fn new(name: Arc<str>, rom: Rom, multiple_of: usize) -> Self {
Self {
name,
rom,
multiple_of,
}
}
}
impl fmt::Display for UnalignedRomError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Can't create section {} because the rom (0x{:X}) is not aligned to 0x{:X}.",
self.name,
self.rom.inner(),
self.multiple_of
)
}
}
impl error::Error for UnalignedRomError {}
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
#[cfg_attr(feature = "pyo3", pyclass(module = "spimdisasm"))]
pub struct RomVramAlignmentMismatchError {
name: Arc<str>,
rom: Rom,
vram: Vram,
multiple_of: usize,
}
impl RomVramAlignmentMismatchError {
pub(crate) fn new(name: Arc<str>, rom: Rom, vram: Vram, multiple_of: usize) -> Self {
Self {
name,
rom,
vram,
multiple_of,
}
}
}
impl fmt::Display for RomVramAlignmentMismatchError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Can't create section {} because the alignment of its rom ({:?}) and vram ({:?}) mod {} does not match.", self.name, self.rom, self.vram, self.multiple_of)
}
}
impl error::Error for RomVramAlignmentMismatchError {}
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
#[cfg_attr(feature = "pyo3", pyclass(module = "spimdisasm"))]
pub struct SectionAlreadyCreatedError {
name: Arc<str>,
rom: Option<Rom>,
vram: Vram,
}
impl SectionAlreadyCreatedError {
pub(crate) fn new(name: Arc<str>, rom: Option<Rom>, vram: Vram) -> Self {
Self { name, rom, vram }
}
}
impl fmt::Display for SectionAlreadyCreatedError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Can't create section {} ({:?} / {:?}) because it has been created already.",
self.name, self.rom, self.vram
)
}
}
impl error::Error for SectionAlreadyCreatedError {}
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
#[cfg_attr(feature = "pyo3", pyclass(module = "spimdisasm"))]
pub struct SectionNotPreheatedError {
name: Arc<str>,
rom: Rom,
vram: Vram,
}
impl SectionNotPreheatedError {
pub(crate) fn new(name: Arc<str>, rom: Rom, vram: Vram) -> Self {
Self { name, rom, vram }
}
}
impl fmt::Display for SectionNotPreheatedError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Can't create section {} ({:?} / {:?}) because it wasn't preheated.",
self.name, self.rom, self.vram
)
}
}
impl error::Error for SectionNotPreheatedError {}
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
#[cfg_attr(feature = "pyo3", pyclass(module = "spimdisasm"))]
pub struct BadUserSymbolSizeError {
name: Arc<str>,
vram: Vram,
size: Size,
section_type: SectionType,
multiple_of: u32,
}
impl BadUserSymbolSizeError {
pub(crate) fn new(
name: Arc<str>,
vram: Vram,
size: Size,
section_type: SectionType,
multiple_of: u32,
) -> Self {
Self {
name,
vram,
size,
section_type,
multiple_of,
}
}
}
impl fmt::Display for BadUserSymbolSizeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(
f,
"User-declared symbol '{}' (Vram {}) has an invalid user size ({}).",
self.name, self.vram, self.size
)?;
write!(
f,
" This symbol is was found in a '{}' section which requires all symbols to have a size multiple of '{}'", self.section_type, self.multiple_of
)
}
}
impl error::Error for BadUserSymbolSizeError {}
#[cfg(feature = "pyo3")]
pub(crate) mod python_bindings {
use pyo3::exceptions::PyRuntimeError;
use pyo3::prelude::*;
pyo3::create_exception!(spimdisasm, SectionCreationError, PyRuntimeError);
impl std::convert::From<super::SectionCreationError> for PyErr {
fn from(err: super::SectionCreationError) -> PyErr {
SectionCreationError::new_err(err.to_string())
}
}
}