silt_lua/
table.rs

1use hashbrown::HashMap;
2
3use crate::value::Value;
4
5pub struct Table {
6    data: HashMap<Value, Value>,
7    /** replicate standard lua behavior */
8    counter: i64,
9    id: usize,
10}
11
12impl Table {
13    pub fn new(id: usize) -> Self {
14        Table {
15            data: HashMap::new(),
16            counter: 0,
17            id,
18        }
19    }
20    pub fn insert(&mut self, key: Value, value: Value) {
21        self.data.insert(key, value);
22    }
23    pub fn get(&self, key: &Value) -> Option<&Value> {
24        self.data.get(key)
25    }
26    pub fn getn(&self, i: usize) -> Option<&Value> {
27        self.data.get(&Value::Integer(i as i64))
28    }
29    pub fn get_value(&self, key: &Value) -> Value {
30        match self.data.get(key) {
31            Some(v) => v.clone(),
32            None => Value::Nil,
33        }
34    }
35
36    pub fn len(&self) -> usize {
37        self.data.len()
38    }
39
40    /** push by counter's current index, if it aready exists keep incrementing until empty position is found */
41    pub fn push(&mut self, value: Value) {
42        // DEV this just feels clunky to replicate lua's behavior
43        self.counter += 1;
44        let mut key = Value::Integer(self.counter);
45        while self.data.contains_key(&key) {
46            self.counter += 1;
47            key.force_to_int(self.counter);
48        }
49        self.data.insert(key, value);
50    }
51}
52
53impl ToString for Table {
54    fn to_string(&self) -> String {
55        format!(
56            "table{}[{}]{{{}}}",
57            self.id,
58            self.data.len(),
59            self.data
60                .iter()
61                .map(|(k, v)| format!("{}: {}", k, v))
62                .collect::<Vec<String>>()
63                .join(", ")
64        )
65    }
66}