swamp_core_extra/
extra.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use crate::idx_gen::IndexAllocator;
6use crate::qck_des::quick_deserialize;
7use crate::value::{QuickDeserialize, Value, to_rust_value};
8use crate::value::{QuickSerialize, ValueRef};
9use sparse_slot::{Id, SparseSlot};
10use std::cell::RefCell;
11use std::fmt::{Debug, Display, Formatter};
12use std::rc::Rc;
13use swamp_types::ExternalType;
14use swamp_types::Type;
15
16#[derive(Debug, PartialEq, Eq)]
17pub struct SparseValueId(pub Id);
18
19impl Display for SparseValueId {
20    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
21        write!(f, "id:{}:{}", self.0.index, self.0.generation)
22    }
23}
24
25impl QuickDeserialize for SparseValueId {
26    fn quick_deserialize(octets: &[u8]) -> (Self, usize) {
27        let mut offset = 0;
28
29        // Deserialize the index
30        let index = u16::from_le_bytes(octets[offset..offset + 2].try_into().unwrap());
31        offset += 2;
32
33        // Deserialize the generation
34        let generation = u8::from_le_bytes(octets[offset..=offset].try_into().unwrap());
35        offset += 1;
36
37        let id = Id::new(index.into(), generation);
38
39        (SparseValueId(id), offset)
40    }
41}
42
43impl QuickSerialize for SparseValueId {
44    fn quick_serialize(&self, octets: &mut [u8]) -> usize {
45        let mut offset = 0;
46
47        // Serialize the index
48        let index_octets = (self.0.index as u16).to_le_bytes();
49        octets[offset..offset + index_octets.len()].copy_from_slice(&index_octets);
50        offset += index_octets.len();
51
52        // Serialize the generation
53        let generation_octets = self.0.generation.to_le_bytes();
54        octets[offset..offset + generation_octets.len()].copy_from_slice(&generation_octets);
55        offset += generation_octets.len();
56
57        offset
58    }
59}
60
61#[derive()]
62pub struct SparseValueMap {
63    pub sparse_slot: SparseSlot<Rc<RefCell<Value>>>,
64    pub id_generator: IndexAllocator,
65    pub value_item_type: Type,
66    pub rust_type_ref_for_id: ExternalType,
67}
68
69impl Debug for SparseValueMap {
70    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
71        writeln!(f, "SparseValueMap")?;
72
73        for (id, val) in self.sparse_slot.iter() {
74            writeln!(f, "  {id}: {}", val.borrow())?;
75        }
76
77        Ok(())
78    }
79}
80
81impl QuickSerialize for SparseValueMap {
82    fn quick_serialize(&self, octets: &mut [u8]) -> usize {
83        let mut offset = 0;
84
85        let count = self.sparse_slot.len() as u16;
86        let count_octets = count.to_le_bytes();
87        octets[offset..offset + count_octets.len()].copy_from_slice(&count_octets);
88        offset += count_octets.len();
89
90        for (id, value) in self.sparse_slot.iter() {
91            let short_index = id.index as u16;
92            let key_index_octets = short_index.to_le_bytes();
93            octets[offset..offset + key_index_octets.len()].copy_from_slice(&key_index_octets);
94            offset += key_index_octets.len();
95
96            let key_generation_octets = id.generation.to_le_bytes();
97            octets[offset..offset + key_generation_octets.len()]
98                .copy_from_slice(&key_generation_octets);
99            offset += key_generation_octets.len();
100
101            let value_size = value.borrow().quick_serialize(&mut octets[offset..], 0);
102            offset += value_size;
103        }
104
105        offset
106    }
107}
108
109impl SparseValueMap {
110    /// # Panics
111    ///
112    #[must_use]
113    pub fn quick_deserialize(
114        key_type: ExternalType,
115        value_item_type: &Type,
116        octets: &[u8],
117    ) -> (Self, usize) {
118        let mut sparse = Self::new(key_type, value_item_type.clone());
119        let mut offset = 0;
120        let count = u16::from_le_bytes(
121            octets[offset..offset + 2]
122                .try_into()
123                .expect("could not convert to u16 count"),
124        );
125        offset += 2;
126
127        for _i in 0..count {
128            let index = u16::from_le_bytes(
129                octets[offset..offset + 2]
130                    .try_into()
131                    .expect("could not convert to u16 index"),
132            );
133            offset += 2;
134
135            let generation = u8::from_le_bytes(
136                octets[offset..=offset]
137                    .try_into()
138                    .expect("could not convert to u16 generation"),
139            );
140            offset += 1;
141
142            let (value, octet_size) =
143                quick_deserialize(&value_item_type.clone(), &octets[offset..], 0);
144            offset += octet_size;
145
146            let id = Id::new(index as usize, generation);
147            let deserialized_value_ref = Rc::new(RefCell::new(value));
148            sparse
149                .sparse_slot
150                .try_set(id, deserialized_value_ref)
151                .expect("could not insert into SparseValueMap");
152
153            sparse.id_generator.reserve(index as usize, generation);
154        }
155
156        (sparse, offset)
157    }
158}
159
160impl Display for SparseValueMap {
161    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
162        write!(
163            f,
164            "Sparse<{:?}> len:{}",
165            self.value_item_type,
166            self.sparse_slot.len()
167        )
168    }
169}
170
171impl SparseValueMap {
172    #[must_use]
173    pub fn new(rust_type_ref_for_id: ExternalType, value_item_type: Type) -> Self {
174        /* let type_parameter = match &resolved_type {
175            Type::Generic(_, parameters) => parameters[0].clone(),
176            _ => panic!("illegal sparse type. not generic"),
177        }; */
178
179        Self {
180            sparse_slot: SparseSlot::<Rc<RefCell<Value>>>::new(2048),
181            id_generator: IndexAllocator::new(),
182            value_item_type,
183            rust_type_ref_for_id,
184        }
185    }
186
187    /// # Panics
188    ///
189    pub fn add(&mut self, v: Value) -> Value {
190        // TODO: Check that value is of correct type parameter
191        let (index, generation) = self.id_generator.create();
192
193        let id = Id { index, generation };
194
195        // Always store mutable references
196        let mutable_reference = Rc::new(RefCell::new(v));
197
198        self.sparse_slot
199            .try_set(id, mutable_reference)
200            .expect("sparse should work");
201
202        let script_id = SparseValueId(id);
203
204        to_rust_value(self.rust_type_ref_for_id.clone(), script_id)
205    }
206
207    pub fn remove(&mut self, id: &SparseValueId) {
208        self.id_generator.remove((id.0.index, id.0.generation));
209        self.sparse_slot.remove(id.0);
210    }
211
212    #[must_use]
213    pub fn get(&self, id: &SparseValueId) -> Option<&ValueRef> {
214        self.sparse_slot.get(id.0)
215    }
216
217    #[allow(unused)]
218    #[must_use]
219    pub fn iter(&self) -> sparse_slot::Iter<'_, Rc<RefCell<Value>>> {
220        self.sparse_slot.iter()
221    }
222
223    pub fn iter_mut(&mut self) -> sparse_slot::IterMut<'_, Rc<RefCell<Value>>> {
224        self.sparse_slot.iter_mut()
225    }
226
227    #[must_use]
228    pub fn values(&self) -> Vec<Rc<RefCell<Value>>> {
229        self.sparse_slot.iter().map(|(_id, v)| v.clone()).collect()
230    }
231}