ruby_marshal/
value_arena.rs

1mod value;
2mod value_handle;
3
4pub use self::value::ArrayValue;
5pub use self::value::BoolValue;
6pub use self::value::FixnumValue;
7pub use self::value::HashValue;
8pub use self::value::NilValue;
9pub use self::value::ObjectValue;
10pub use self::value::StringValue;
11pub use self::value::SymbolValue;
12pub use self::value::UserDefinedValue;
13pub use self::value::Value;
14pub use self::value::ValueKind;
15pub use self::value_handle::TypedValueHandle;
16pub use self::value_handle::ValueHandle;
17use slotmap::SlotMap;
18use std::collections::HashMap;
19
20/// An arena of Ruby values.
21#[derive(Debug)]
22pub struct ValueArena {
23    arena: SlotMap<slotmap::DefaultKey, Value>,
24    symbols: HashMap<Vec<u8>, TypedValueHandle<SymbolValue>>,
25    root: ValueHandle,
26}
27
28impl ValueArena {
29    /// Make a new empty [`ValueArena`].
30    ///
31    /// The root node is nil.
32    pub fn new() -> Self {
33        let mut arena = SlotMap::new();
34        let symbols = HashMap::new();
35        let root = ValueHandle::new(arena.insert(Value::Nil(NilValue)));
36
37        Self {
38            arena,
39            symbols,
40            root,
41        }
42    }
43
44    /// Get the root [`ValueHandle`].
45    pub fn root(&self) -> ValueHandle {
46        self.root
47    }
48
49    /// Replace the current root, returning the old root.
50    pub fn replace_root<H>(&mut self, new_root: H) -> ValueHandle
51    where
52        H: Into<ValueHandle>,
53    {
54        let mut new_root = new_root.into();
55
56        std::mem::swap(&mut self.root, &mut new_root);
57        new_root
58    }
59
60    /// Get a reference to the [`Value`] denoted by the given [`ValueHandle`].
61    pub fn get<H>(&self, handle: H) -> Option<&Value>
62    where
63        H: Into<ValueHandle>,
64    {
65        self.arena.get(handle.into().index)
66    }
67
68    /// Get a mutable reference to the [`Value`] denoted by the given [`ValueHandle`].
69    pub(crate) fn get_mut<H>(&mut self, handle: H) -> Option<&mut Value>
70    where
71        H: Into<ValueHandle>,
72    {
73        self.arena.get_mut(handle.into().index)
74    }
75
76    /// Get a reference to the [`SymbolValue`] denoted by the given [`TypedValueHandle`].
77    ///
78    /// # Panics
79    /// Panics if the value is not a SymbolValue.
80    pub fn get_symbol(&self, handle: TypedValueHandle<SymbolValue>) -> Option<&SymbolValue> {
81        Some(self.get(handle)?.as_symbol().expect("not a symbol"))
82    }
83
84    /// Create an orphan `Nil` value and return the handle.
85    pub fn create_nil(&mut self) -> TypedValueHandle<NilValue> {
86        let index = self.arena.insert(Value::Nil(NilValue));
87        let handle = ValueHandle::new(index);
88
89        TypedValueHandle::new_unchecked(handle)
90    }
91
92    /// Create an orphan `Bool` value and return the handle.
93    pub fn create_bool(&mut self, value: bool) -> TypedValueHandle<BoolValue> {
94        let index = self.arena.insert(Value::Bool(BoolValue::new(value)));
95        let handle = ValueHandle::new(index);
96
97        TypedValueHandle::new_unchecked(handle)
98    }
99
100    /// Create an orphan `Fixnum` value and return the handle.
101    pub fn create_fixnum(&mut self, value: i32) -> TypedValueHandle<FixnumValue> {
102        let index = self.arena.insert(Value::Fixnum(FixnumValue::new(value)));
103        let handle = ValueHandle::new(index);
104
105        TypedValueHandle::new_unchecked(handle)
106    }
107
108    /// Create an orphan `Symbol` value and return the handle.
109    ///
110    /// If a symbol with this name already exists in this arena, it is returned instead of creating a new symbol.
111    pub fn create_symbol(&mut self, value: Vec<u8>) -> TypedValueHandle<SymbolValue> {
112        if let Some(handle) = self.symbols.get(&value) {
113            return *handle;
114        }
115
116        self.create_new_symbol(value)
117    }
118
119    /// Create a new orphan `Symbol` value and return the handle.
120    pub fn create_new_symbol(&mut self, value: Vec<u8>) -> TypedValueHandle<SymbolValue> {
121        let index = self
122            .arena
123            .insert(Value::Symbol(SymbolValue::new(value.clone())));
124        let handle = ValueHandle::new(index);
125        let handle = TypedValueHandle::new_unchecked(handle);
126
127        self.symbols.entry(value).or_insert(handle);
128
129        handle
130    }
131
132    /// Create an orphan `Array` value and return the handle.
133    pub fn create_array(&mut self, value: Vec<ValueHandle>) -> TypedValueHandle<ArrayValue> {
134        let index = self.arena.insert(Value::Array(ArrayValue::new(value)));
135        let handle = ValueHandle::new(index);
136
137        TypedValueHandle::new_unchecked(handle)
138    }
139
140    /// Create an orphan `Hash` value and return the handle.
141    pub fn create_hash(
142        &mut self,
143        value: Vec<(ValueHandle, ValueHandle)>,
144        default_value: Option<ValueHandle>,
145    ) -> TypedValueHandle<HashValue> {
146        let index = self
147            .arena
148            .insert(Value::Hash(HashValue::new(value, default_value)));
149        let handle = ValueHandle::new(index);
150
151        TypedValueHandle::new_unchecked(handle)
152    }
153
154    /// Create an orphan `Object` value and return the handle.
155    pub fn create_object(
156        &mut self,
157        name: TypedValueHandle<SymbolValue>,
158        instance_variables: Vec<(TypedValueHandle<SymbolValue>, ValueHandle)>,
159    ) -> TypedValueHandle<ObjectValue> {
160        let index = self
161            .arena
162            .insert(Value::Object(ObjectValue::new(name, instance_variables)));
163        let handle = ValueHandle::new(index);
164
165        TypedValueHandle::new_unchecked(handle)
166    }
167
168    /// Create an orphan `String` value and return the handle.
169    pub fn create_string(&mut self, value: Vec<u8>) -> TypedValueHandle<StringValue> {
170        let index = self.arena.insert(Value::String(StringValue::new(value)));
171        let handle = ValueHandle::new(index);
172
173        TypedValueHandle::new_unchecked(handle)
174    }
175
176    /// Create an orphan `UserDefined` value and return the handle.
177    pub fn create_user_defined(
178        &mut self,
179        name: TypedValueHandle<SymbolValue>,
180        value: Vec<u8>,
181    ) -> TypedValueHandle<UserDefinedValue> {
182        let index = self
183            .arena
184            .insert(Value::UserDefined(UserDefinedValue::new(name, value)));
185        let handle = ValueHandle::new(index);
186
187        TypedValueHandle::new_unchecked(handle)
188    }
189}
190
191impl Default for ValueArena {
192    fn default() -> Self {
193        Self::new()
194    }
195}
196
197impl std::ops::Index<ValueHandle> for ValueArena {
198    type Output = Value;
199
200    fn index(&self, index: ValueHandle) -> &Self::Output {
201        self.get(index).expect("missing value")
202    }
203}