use thiserror::Error;
use crate::block::Strtab;
use crate::block::{AttributeGroups, Attributes, TypeTable};
use crate::record::{Comdat, DataLayout, RecordStringError};
use crate::unroll::ConsistencyError;
#[derive(Debug, Error)]
pub enum MapError {
#[error("error while mapping block: {0}")]
BadBlockMap(String),
#[error("inconsistent block or record state")]
Inconsistent(#[from] ConsistencyError),
#[error("unsupported: {0}")]
Unsupported(String),
#[error("invalid: {0}")]
Invalid(String),
#[error("error while extracting string: {0}")]
RecordString(#[from] RecordStringError),
#[error("missing context for mapping")]
Context(#[from] MapCtxError),
}
#[derive(Debug, Error)]
pub enum MapCtxError {
#[error("mapping context requires a version for disambiguation, but none is available")]
NoVersion,
#[error("mapping context requires types, but none are available")]
NoTypeTable,
}
#[non_exhaustive]
#[derive(Debug, Default)]
pub(crate) struct PartialMapCtx {
pub(crate) version: Option<u64>,
pub(crate) datalayout: DataLayout,
pub(crate) section_table: Vec<String>,
pub(crate) gc_table: Vec<String>,
pub(crate) strtab: Strtab,
pub(crate) attribute_groups: AttributeGroups,
pub(crate) attributes: Attributes,
pub(crate) type_table: Option<TypeTable>,
pub(crate) comdats: Vec<Comdat>,
}
impl PartialMapCtx {
pub(crate) fn reify(&self) -> Result<MapCtx, MapCtxError> {
log::debug!("reifying {self:?}");
Ok(MapCtx {
version: self.version.ok_or(MapCtxError::NoVersion)?,
datalayout: &self.datalayout,
section_table: &self.section_table,
gc_table: &self.gc_table,
strtab: &self.strtab,
attribute_groups: &self.attribute_groups,
attributes: &self.attributes,
type_table: self.type_table.as_ref().ok_or(MapCtxError::NoTypeTable)?,
comdats: &self.comdats,
})
}
pub fn use_strtab(&self) -> Result<bool, MapCtxError> {
self.version.map(|v| v >= 2).ok_or(MapCtxError::NoVersion)
}
pub fn attribute_groups(&self) -> &AttributeGroups {
&self.attribute_groups
}
}
#[non_exhaustive]
#[derive(Debug)]
pub struct MapCtx<'ctx> {
pub version: u64,
pub datalayout: &'ctx DataLayout,
pub section_table: &'ctx [String],
pub gc_table: &'ctx [String],
pub strtab: &'ctx Strtab,
pub attribute_groups: &'ctx AttributeGroups,
pub attributes: &'ctx Attributes,
pub type_table: &'ctx TypeTable,
pub comdats: &'ctx [Comdat],
}
impl MapCtx<'_> {
pub fn use_strtab(&self) -> bool {
self.version >= 2
}
pub fn use_relative_ids(&self) -> bool {
self.version >= 1
}
}
pub(crate) trait PartialCtxMappable<T>: Sized {
type Error;
fn try_map(raw: &T, ctx: &mut PartialMapCtx) -> Result<Self, Self::Error>;
}
pub(crate) trait CtxMappable<'ctx, T>: Sized {
type Error;
fn try_map(raw: &T, ctx: &'ctx MapCtx) -> Result<Self, Self::Error>;
}