1use super::ast;
6use super::scope;
7use std::marker::PhantomData;
8use std::ops::Index;
9use std::ops::IndexMut;
10
11#[cfg(feature = "serde_borsh")]
12use borsh::{maybestd::io::Result, maybestd::io::Write, BorshDeserialize, BorshSerialize};
13
14pub trait PiggyVecKey {
15 fn as_usize(&self) -> usize;
16}
17
18#[derive(Debug)]
21pub struct PiggyVec<K, V>
22where
23 K: PiggyVecKey + From<usize>,
24{
25 vec: Vec<V>,
26 phantom: PhantomData<K>,
27}
28
29impl<K, V> PiggyVec<K, V>
30where
31 K: PiggyVecKey + From<usize>,
32{
33 pub fn with_capacity(capacity: usize) -> Self {
34 Self {
35 vec: Vec::with_capacity(capacity),
36 phantom: PhantomData {},
37 }
38 }
39
40 #[inline]
41 pub fn insert(&mut self, v: V) -> K {
42 self.vec.push(v);
43 (self.vec.len() - 1).into()
44 }
45
46 #[inline]
47 pub fn vec(&self) -> &Vec<V> {
48 &self.vec
49 }
50
51 pub fn iter<'a>(&'a self) -> PiggyVecIter<'a, K, V> {
52 PiggyVecIter {
53 vec_iter: self.vec.iter(),
54 phantom: PhantomData {},
55 }
56 }
57}
58
59impl<K, V> Index<K> for PiggyVec<K, V>
60where
61 K: PiggyVecKey + From<usize>,
62{
63 type Output = V;
64
65 #[inline]
66 fn index(&self, index: K) -> &Self::Output {
67 &self.vec[index.as_usize()]
68 }
69}
70
71impl<K, V> IndexMut<K> for PiggyVec<K, V>
72where
73 K: PiggyVecKey + From<usize>,
74{
75 #[inline]
76 fn index_mut(&mut self, index: K) -> &mut Self::Output {
77 &mut self.vec[index.as_usize()]
78 }
79}
80
81impl<K, V> From<Vec<V>> for PiggyVec<K, V>
82where
83 K: PiggyVecKey + From<usize>,
84{
85 #[inline]
86 fn from(vec: Vec<V>) -> Self {
87 PiggyVec {
88 vec,
89 phantom: PhantomData {},
90 }
91 }
92}
93
94#[cfg(feature = "serde_borsh")]
95impl<K, V> BorshSerialize for PiggyVec<K, V>
96where
97 K: PiggyVecKey + From<usize>,
98 V: BorshSerialize,
99{
100 fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
101 self.vec().serialize(writer)
102 }
103}
104
105#[cfg(feature = "serde_borsh")]
106impl<K, V> BorshDeserialize for PiggyVec<K, V>
107where
108 K: PiggyVecKey + From<usize>,
109 V: BorshDeserialize,
110{
111 fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> Result<Self> {
112 Ok(Vec::<V>::deserialize_reader(reader)?.into())
113 }
114}
115
116pub struct PiggyVecIter<'a, K, V>
117where
118 K: PiggyVecKey + From<usize>,
119{
120 vec_iter: std::slice::Iter<'a, V>,
121 phantom: PhantomData<K>,
122}
123
124impl<'a, K, V> Iterator for PiggyVecIter<'a, K, V>
125where
126 K: PiggyVecKey + From<usize>,
127{
128 type Item = &'a V;
129
130 fn next(&mut self) -> Option<Self::Item> {
131 self.vec_iter.next()
132 }
133}
134
135#[macro_export]
136macro_rules! piggy_key_type {
137 ( $(#[$outer:meta])* $vis:vis struct $name:ident; $($rest:tt)* ) => {
138 $(#[$outer])*
139 #[derive(Copy, Clone, Default,
140 Eq, PartialEq, Ord, PartialOrd,
141 Hash, Debug)]
142 #[repr(transparent)]
143 $vis struct $name(usize);
144
145 impl $name {
146 #[inline]
147 pub fn null() -> Self {
148 $name(std::usize::MAX)
149 }
150 }
151
152 impl From<usize> for $name {
153 #[inline]
154 fn from(k: usize) -> Self {
155 $name(k)
156 }
157 }
158
159 impl $crate::PiggyVecKey for $name {
160 #[inline]
161 fn as_usize(&self) -> usize {
162 self.0
163 }
164 }
165
166 piggy_key_type!($($rest)*);
167 };
168
169 () => {}
170}
171
172piggy_key_type! {
173 pub struct LabeledStmtKey;
174 pub struct AssignStmtKey;
175 pub struct SpecKey;
176 pub struct FuncDeclKey;
177 pub struct FuncTypeKey;
178 pub struct IdentKey;
179 pub struct FieldKey;
180 pub struct EntityKey;
181 pub struct ScopeKey;
182}
183
184pub type LabeledStmts = PiggyVec<LabeledStmtKey, ast::LabeledStmt>;
185pub type AssignStmts = PiggyVec<AssignStmtKey, ast::AssignStmt>;
186pub type Specs = PiggyVec<SpecKey, ast::Spec>;
187pub type FuncDecls = PiggyVec<FuncDeclKey, ast::FuncDecl>;
188pub type FuncTypes = PiggyVec<FuncTypeKey, ast::FuncType>;
189pub type Idents = PiggyVec<IdentKey, ast::Ident>;
190pub type Fields = PiggyVec<FieldKey, ast::Field>;
191pub type Entitys = PiggyVec<EntityKey, scope::Entity>;
192pub type Scopes = PiggyVec<ScopeKey, scope::Scope>;
193
194pub struct AstObjects {
195 pub l_stmts: LabeledStmts,
196 pub a_stmts: AssignStmts,
197 pub specs: Specs,
198 pub fdecls: FuncDecls,
199 pub ftypes: FuncTypes,
200 pub idents: Idents,
201 pub fields: Fields,
202 pub entities: Entitys,
203 pub scopes: Scopes,
204}
205
206impl AstObjects {
207 pub fn new() -> AstObjects {
208 const CAP: usize = 16;
209 AstObjects {
210 l_stmts: PiggyVec::with_capacity(CAP),
211 a_stmts: PiggyVec::with_capacity(CAP),
212 specs: PiggyVec::with_capacity(CAP),
213 fdecls: PiggyVec::with_capacity(CAP),
214 ftypes: PiggyVec::with_capacity(CAP),
215 idents: PiggyVec::with_capacity(CAP),
216 fields: PiggyVec::with_capacity(CAP),
217 entities: PiggyVec::with_capacity(CAP),
218 scopes: PiggyVec::with_capacity(CAP),
219 }
220 }
221}