use alloc::sync::Arc;
use core::{fmt, hash::Hash};
use crate::addresses::{Rom, Vram};
use super::{
GeneratedBy, LabelMetadataNameDisplay, LabelType, OwnerSegmentKind, ReferrerInfo, Referrers,
};
#[derive(Clone)]
pub struct LabelMetadata {
generated_by: GeneratedBy,
vram: Vram,
owner_segment_kind: OwnerSegmentKind,
autodetected_type: LabelType,
rom: Option<Rom>,
user_declared_name: Option<Arc<str>>,
user_declared_type: Option<LabelType>,
is_defined: bool,
sym_creators: Referrers,
sym_referrers: Referrers,
visibility: Option<Arc<str>>,
}
impl LabelMetadata {
pub(crate) fn new(
vram: Vram,
owner_segment_kind: OwnerSegmentKind,
label_type: LabelType,
) -> Self {
Self {
generated_by: GeneratedBy::Autogenerated,
vram,
owner_segment_kind,
autodetected_type: label_type,
rom: None,
user_declared_name: None,
user_declared_type: None,
is_defined: false,
sym_creators: Referrers::new(),
sym_referrers: Referrers::new(),
visibility: None,
}
}
pub(crate) fn new_user(
vram: Vram,
owner_segment_kind: OwnerSegmentKind,
label_type: LabelType,
name: Arc<str>,
rom: Option<Rom>,
) -> Self {
Self {
generated_by: GeneratedBy::UserDeclared,
rom,
user_declared_name: Some(name),
user_declared_type: Some(label_type),
..Self::new(vram, owner_segment_kind, label_type)
}
}
pub fn generated_by(&self) -> GeneratedBy {
self.generated_by
}
pub const fn vram(&self) -> Vram {
self.vram
}
pub fn label_type(&self) -> LabelType {
self.user_declared_type.unwrap_or(self.autodetected_type)
}
pub(crate) fn set_autodetected_type(&mut self, new_type: LabelType) {
if self.autodetected_type.does_new_takes_precedence(new_type) {
self.autodetected_type = new_type;
}
}
pub fn owner_segment_kind(&self) -> &OwnerSegmentKind {
&self.owner_segment_kind
}
pub fn rom(&self) -> Option<Rom> {
self.rom
}
pub(crate) fn set_rom(&mut self, new_rom: Rom) {
self.rom = Some(new_rom);
}
pub fn display_name(&self) -> LabelMetadataNameDisplay<'_> {
LabelMetadataNameDisplay::new(self)
}
pub(crate) fn user_declared_name(&self) -> Option<Arc<str>> {
self.user_declared_name.clone()
}
#[cfg(feature = "pyo3")]
pub(crate) fn set_user_declared_name(&mut self, name: Arc<str>) {
self.user_declared_name = Some(name);
}
pub fn is_defined(&self) -> bool {
self.is_defined
}
pub(crate) fn set_defined(&mut self) {
self.is_defined = true;
}
pub(crate) fn add_creator(&mut self, creator: ReferrerInfo) {
self.sym_creators.add(creator);
}
pub fn reference_counter(&self) -> usize {
self.sym_referrers.reference_counter()
}
pub(crate) fn add_referenced_info(&mut self, referrer: ReferrerInfo) {
self.sym_referrers.add(referrer);
}
pub fn visibility(&self) -> Option<Arc<str>> {
self.visibility.clone()
}
pub(crate) fn set_visibility(&mut self, visibility: Arc<str>) {
self.visibility = Some(visibility)
}
}
impl PartialEq for LabelMetadata {
fn eq(&self, other: &Self) -> bool {
self.vram == other.vram && self.rom == other.rom
}
}
impl PartialOrd for LabelMetadata {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
match self.vram.partial_cmp(&other.vram) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
};
self.rom.partial_cmp(&other.rom)
}
}
impl Hash for LabelMetadata {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.vram.hash(state);
self.rom.hash(state);
}
}
impl fmt::Debug for LabelMetadata {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"LabelMetadata {{ vram: 0x{}, name: \"{}\" }}",
self.vram,
self.display_name()
)
}
}