use std::ops::Index;
use crate::types::value::MarshalValue;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ObjectIdx(usize);
impl ObjectIdx {
pub fn inner(&self) -> usize {
self.0
}
pub fn new(idx: usize) -> Self {
Self(idx)
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct ObjectRefIdx(usize);
impl ObjectRefIdx {
pub fn inner(&self) -> usize {
self.0
}
pub fn new(idx: usize) -> Self {
Self(idx)
}
}
#[derive(Debug, Clone, Default)]
pub struct ObjectTable<'a> {
objects: Vec<MarshalValue<'a>>,
object_refs: Vec<ObjectIdx>,
}
impl<'a> ObjectTable<'a> {
pub fn new() -> Self {
Self::default()
}
pub fn push_object(&mut self, value: MarshalValue<'a>) -> ObjectIdx {
let idx = ObjectIdx::new(self.objects.len());
self.objects.push(value);
idx
}
pub fn push_object_ref(&mut self, idx: ObjectIdx) {
self.object_refs.push(idx);
}
pub fn object_ref_count(&self) -> usize {
self.object_refs.len()
}
pub fn replace_last_object_ref(&mut self, idx: ObjectIdx) {
*self
.object_refs
.last_mut()
.expect("no object ref to replace") = idx;
}
pub fn get_by_ref(&self, ref_idx: usize) -> Option<ObjectIdx> {
self.object_refs.get(ref_idx).copied()
}
pub fn resolve_ref(&self, ref_idx: ObjectRefIdx) -> Option<&MarshalValue<'a>> {
let obj_idx = self.object_refs.get(ref_idx.inner())?;
self.objects.get(obj_idx.inner())
}
}
impl<'a> Index<usize> for ObjectTable<'a> {
type Output = MarshalValue<'a>;
fn index(&self, index: usize) -> &Self::Output {
self.objects.index(index)
}
}
impl<'a> Index<ObjectIdx> for ObjectTable<'a> {
type Output = MarshalValue<'a>;
fn index(&self, index: ObjectIdx) -> &Self::Output {
self.objects.index(index.inner())
}
}
impl<'a> Index<ObjectRefIdx> for ObjectTable<'a> {
type Output = MarshalValue<'a>;
fn index(&self, index: ObjectRefIdx) -> &Self::Output {
self.index(*self.object_refs.index(index.inner()))
}
}