rune/core/object/
chartab.rs

1use super::{CloneIn, Gc, IntoObject, NIL, Object, WithLifetime};
2use crate::{
3    core::gc::{Block, GcHeap, Slot},
4    derive_GcMoveable,
5};
6use rune_core::hashmap::HashMap;
7use rune_macros::Trace;
8use std::{cell::RefCell, fmt};
9
10#[derive(Debug, Eq, Trace)]
11pub struct CharTableInner<'ob> {
12    parent: RefCell<Option<Slot<&'ob CharTable>>>,
13    data: RefCell<HashMap<usize, Slot<Object<'ob>>>>,
14    init: Slot<Object<'ob>>,
15}
16
17impl<'ob> CharTableInner<'ob> {
18    pub fn new(init: Option<Object<'ob>>) -> Self {
19        CharTableInner {
20            parent: RefCell::new(None),
21            data: RefCell::new(HashMap::default()),
22            init: Slot::new(init.unwrap_or(NIL)),
23        }
24    }
25}
26
27#[derive(PartialEq, Eq, Trace, Debug)]
28pub(crate) struct CharTable(GcHeap<CharTableInner<'static>>);
29
30derive_GcMoveable!(CharTable);
31
32impl PartialEq for CharTableInner<'_> {
33    fn eq(&self, other: &Self) -> bool {
34        std::ptr::eq(self, other)
35    }
36}
37
38impl<'new> CloneIn<'new, &'new Self> for CharTable {
39    fn clone_in<const C: bool>(&self, bk: &'new Block<C>) -> Gc<&'new Self> {
40        let parent_clone =
41            self.0.parent.borrow().as_ref().map(|p| Slot::new(p.clone_in(bk).untag()));
42        let parent = RefCell::new(parent_clone);
43
44        let mut data = HashMap::default();
45        for (key, value) in self.0.data.borrow().iter() {
46            let new_value = Slot::new(value.clone_in(bk));
47            data.insert(*key, new_value);
48        }
49        let data = RefCell::new(data);
50        let init = Slot::new(self.0.init.clone_in(bk));
51        CharTableInner { parent, data, init }.into_obj(bk)
52    }
53}
54
55impl CharTable {
56    pub(in crate::core) unsafe fn new(table: CharTableInner<'_>, constant: bool) -> Self {
57        // transmute lifetime to static
58        let table =
59            unsafe { std::mem::transmute::<CharTableInner<'_>, CharTableInner<'static>>(table) };
60        Self(GcHeap::new(table, constant))
61    }
62
63    pub fn get(&self, idx: usize) -> Object {
64        match self.0.data.borrow().get(&idx) {
65            Some(x) => **x,
66            None => *self.0.init,
67        }
68    }
69
70    pub fn set(&self, idx: usize, item: Object) {
71        unsafe { self.0.data.borrow_mut().insert(idx, Slot::new(item.with_lifetime())) };
72    }
73
74    pub fn set_parent(&self, new: Option<&Self>) {
75        let new_ptr = new.map(|n| unsafe { Slot::new(n.with_lifetime()) });
76        *self.0.parent.borrow_mut() = new_ptr;
77    }
78}
79
80impl fmt::Display for CharTable {
81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        write!(f, "[")?;
83        let data = self.0.data.borrow();
84
85        let mut entries: Vec<_> = data.iter().collect();
86        entries.sort_by_key(|&(key, _)| key);
87
88        let mut iter = entries.into_iter();
89        if let Some((_, first)) = iter.next() {
90            write!(f, "{}", first)?;
91            for (_, value) in iter {
92                write!(f, " {}", value)?;
93            }
94        }
95        write!(f, "]")
96    }
97}