swamp_script_core_extra/
extra.rs

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