use core::fmt;
use crate::symbol;
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct Index(pub IndexInt);
pub type IndexInt = u32;
pub trait IntoIndexInt {
fn into_index_int(self) -> IndexInt;
}
impl IntoIndexInt for u32 {
#[inline]
fn into_index_int(self) -> IndexInt {
self
}
}
impl IntoIndexInt for usize {
#[inline]
fn into_index_int(self) -> IndexInt {
self as IndexInt
}
}
impl IntoIndexInt for i32 {
#[inline]
fn into_index_int(self) -> IndexInt {
self as IndexInt
}
}
impl Index {
#[inline]
pub fn set(&mut self, val: IndexInt) {
self.0 = val;
}
#[inline]
pub const fn value(self) -> IndexInt {
self.0
}
#[inline]
pub const fn is_runtime(self) -> bool {
self.0 == Self::RUNTIME.0
}
pub const INVALID: Index = Index(IndexInt::MAX);
pub const RUNTIME: Index = Index(0);
pub const BAKE_SERVER_DATA: Index = Index(1);
pub const BAKE_CLIENT_DATA: Index = Index(2);
#[inline]
pub fn source(num: impl IntoIndexInt) -> Index {
Index(num.into_index_int())
}
#[inline]
pub fn part(num: impl IntoIndexInt) -> Index {
Index(num.into_index_int())
}
#[inline]
pub fn init<N>(num: N) -> Index
where
N: TryInto<IndexInt>,
N::Error: core::fmt::Debug,
{
Index(num.try_into().expect("Index::init: out of range"))
}
#[inline]
pub const fn is_valid(self) -> bool {
self.0 != Self::INVALID.0
}
#[inline]
pub const fn is_invalid(self) -> bool {
!self.is_valid()
}
#[inline]
pub const fn get(self) -> IndexInt {
self.0
}
}
impl Default for Index {
#[inline]
fn default() -> Self {
Self::INVALID
}
}
pub use crate::{Ref, RefInt, RefTag};
const _: () = assert!(Ref::NONE.is_empty());
pub trait SymbolTable {
fn get_symbol(&mut self, r: Ref) -> &mut symbol::Symbol;
}
impl SymbolTable for [symbol::Symbol] {
#[inline]
fn get_symbol(&mut self, r: Ref) -> &mut symbol::Symbol {
&mut self[r.inner_index() as usize]
}
}
impl SymbolTable for Vec<symbol::Symbol> {
#[inline]
fn get_symbol(&mut self, r: Ref) -> &mut symbol::Symbol {
&mut self[r.inner_index() as usize]
}
}
impl Ref {
#[inline]
pub fn get_symbol<T: SymbolTable + ?Sized>(self, symbol_table: &mut T) -> &mut symbol::Symbol {
symbol_table.get_symbol(self)
}
pub fn dump<T: SymbolTable + ?Sized>(self, symbol_table: &mut T) -> RefDump<'_> {
RefDump {
ref_: self,
symbol: symbol_table.get_symbol(self),
}
}
}
pub struct RefDump<'a> {
ref_: Ref,
symbol: &'a symbol::Symbol,
}
impl fmt::Display for RefDump<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = self.symbol.original_name.slice();
write!(
f,
"Ref[inner={}, src={}, .{}; original_name={}, uses={}]",
self.ref_.inner_index(),
self.ref_.source_index(),
<&'static str>::from(self.ref_.tag()),
bstr::BStr::new(name),
self.symbol.use_count_estimate,
)
}
}