use core::{error, fmt};
use std::{collections::BTreeMap, sync::Arc};
#[cfg(feature = "pyo3")]
use pyo3::prelude::*;
use crate::{
addresses::Rom,
relocation::{RelocReferencedSym, RelocationInfo, RelocationType},
};
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "pyo3", pyclass(module = "spimdisasm", name = "UserRelocs"))]
pub struct PyUserRelocs {
inner: BTreeMap<Rom, RelocationInfo>,
}
impl PyUserRelocs {
pub fn inner(&self) -> &BTreeMap<Rom, RelocationInfo> {
&self.inner
}
}
#[pymethods]
impl PyUserRelocs {
#[new]
pub fn py_new() -> Self {
Self {
inner: BTreeMap::new(),
}
}
pub fn add_reloc(
&mut self,
rom: Rom,
reloc_type: RelocationType,
sym_name: String,
addend: i64,
) -> Result<(), UserRelocAddError> {
let reloc =
reloc_type.new_reloc_info(RelocReferencedSym::SymName(Arc::from(sym_name), addend));
if self.inner.insert(rom, reloc).is_some() {
Err(UserRelocAddError { rom })
} else {
Ok(())
}
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "pyo3", pyclass(module = "spimdisasm"))]
pub struct UserRelocAddError {
rom: Rom,
}
impl fmt::Display for UserRelocAddError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Duplicated rom address {:?} while adding relocs",
self.rom
)
}
}
impl error::Error for UserRelocAddError {}
use pyo3::exceptions::PyRuntimeError;
pyo3::create_exception!(spimdisasm, PyUserRelocAddError, PyRuntimeError);
impl std::convert::From<UserRelocAddError> for PyErr {
fn from(err: UserRelocAddError) -> PyErr {
PyUserRelocAddError::new_err(err.to_string())
}
}