1use std::fmt;
2use std::sync::Arc;
3
4use crate::Variable;
5
6const BLOCK_SIZE: usize = 124;
8
9const EMPTY: u64 = 0x0;
10const BOOL: u64 = 0x1;
11const F64: u64 = 0x2;
12const STR: u64 = 0x3;
13
14pub struct Block {
16 data: [u64; BLOCK_SIZE],
17 tys: [u64; 4],
18}
19
20impl Block {
21 fn new() -> Block {
22 Block {
23 data: [0; BLOCK_SIZE],
24 tys: [0; 4],
25 }
26 }
27
28 pub(crate) fn var(&self, ind: u8) -> Variable {
29 use std::mem::transmute;
30
31 let k = ind as usize;
32 assert!(k < BLOCK_SIZE);
33 let i = k / 32;
34 let j = k - i * 32;
35 match self.tys[i] >> (j * 2) & 0x3 {
36 EMPTY => panic!("Reading beyond end"),
37 BOOL => Variable::bool(self.data[k] != 0),
38 F64 => Variable::f64(f64::from_bits(self.data[k])),
39 STR => Variable::Str(unsafe { transmute::<&u64, &Arc<String>>(&self.data[k]) }.clone()),
40 _ => panic!("Invalid type"),
41 }
42 }
43
44 fn push(&mut self, var: &Variable, pos: usize) {
45 use std::mem::transmute;
46
47 let k = pos;
48 assert!(k < BLOCK_SIZE);
49
50 let i = k / 32;
51 let j = k - i * 32;
52 match *var {
53 Variable::Bool(val, _) => {
54 self.tys[i] &= !(0x3 << (j * 2));
56 self.tys[i] |= BOOL << (j * 2);
58 self.data[k] = val as u64;
59 }
60 Variable::F64(val, _) => {
61 self.tys[i] &= !(0x3 << (j * 2));
63 self.tys[i] |= F64 << (j * 2);
65 self.data[k] = val.to_bits();
66 }
67 Variable::Str(ref s) => {
68 self.tys[i] &= !(0x3 << (j * 2));
70 self.tys[i] |= STR << (j * 2);
72 self.data[k] = unsafe { transmute::<Arc<String>, usize>(s.clone()) as u64 };
73 }
74 _ => panic!("Expected `str`, `f64`, `bool`"),
75 }
76 }
77}
78
79impl Clone for Block {
80 fn clone(&self) -> Block {
81 use std::mem::transmute;
82
83 let mut data = self.data;
84 for k in 0..BLOCK_SIZE {
85 let i = k / 32;
86 let j = k - i * 32;
87 match self.tys[i] >> (j * 2) & 0x3 {
88 EMPTY => break,
89 STR => {
90 unsafe {
92 data[k] = transmute::<Arc<String>, usize>(
93 transmute::<&usize, &Arc<String>>(&(self.data[k] as usize)).clone(),
94 ) as u64;
95 }
96 }
97 _ => {}
98 }
99 }
100 Block {
101 data,
102 tys: self.tys,
103 }
104 }
105}
106
107impl Drop for Block {
108 fn drop(&mut self) {
109 use std::mem::transmute;
110
111 for k in 0..BLOCK_SIZE {
112 let i = k / 32;
113 let j = k - i * 32;
114 match self.tys[i] >> (j * 2) & 0x3 {
115 EMPTY => break,
116 STR => {
117 unsafe { drop(transmute::<usize, Arc<String>>(self.data[k] as usize)) }
119 }
120 _ => {}
121 }
122 }
123 }
124}
125
126impl fmt::Debug for Block {
127 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
128 write!(f, "Block")
129 }
130}
131
132#[derive(Debug, Clone)]
133pub(crate) struct Slice {
134 pub(crate) block: Arc<Block>,
135 pub(crate) start: u8,
136 pub(crate) end: u8,
137}
138
139impl Slice {
140 fn new() -> Slice {
141 Slice {
142 block: Arc::new(Block::new()),
143 start: 0,
144 end: 0,
145 }
146 }
147}
148
149#[derive(Debug, Clone)]
151pub struct Link {
152 pub(crate) slices: Vec<Slice>,
153}
154
155impl Default for Link {
156 fn default() -> Link {
157 Link::new()
158 }
159}
160
161impl Link {
162 pub fn new() -> Link {
164 Link { slices: vec![] }
165 }
166
167 pub fn head(&self) -> Option<Box<Variable>> {
169 if self.slices.is_empty() {
170 None
171 } else {
172 let first = &self.slices[0];
173 if first.start < first.end {
174 Some(Box::new(first.block.var(first.start)))
175 } else {
176 None
177 }
178 }
179 }
180
181 pub fn tip(&self) -> Option<Box<Variable>> {
183 if let Some(last) = self.slices.last() {
184 if last.start < last.end {
185 Some(Box::new(last.block.var(last.end - 1)))
186 } else {
187 None
188 }
189 } else {
190 None
191 }
192 }
193
194 pub fn tail(&self) -> Link {
198 if self.slices.is_empty() {
199 Link::new()
200 } else {
201 let first = &self.slices[0];
202 let mut l = Link::new();
203 if first.start + 1 < first.end {
205 l.slices.push(first.clone());
206 l.slices[0].start += 1;
207 }
208 for slice in self.slices.iter().skip(1) {
209 l.slices.push(slice.clone())
210 }
211 l
212 }
213 }
214
215 pub fn neck(&self) -> Link {
219 if let Some(last) = self.slices.last() {
220 let mut l = Link::new();
221 for slice in self.slices.iter().take(self.slices.len() - 1) {
222 l.slices.push(slice.clone())
223 }
224 if last.start + 1 < last.end {
226 l.slices.push(Slice {
227 block: last.block.clone(),
228 start: last.start,
229 end: last.end - 1,
230 })
231 }
232 l
233 } else {
234 Link::new()
235 }
236 }
237
238 pub fn is_empty(&self) -> bool {
240 self.slices.len() == 0
241 }
242
243 pub fn add(&self, other: &Link) -> Link {
245 let mut slices = Vec::with_capacity(self.slices.len() + other.slices.len());
246 slices.extend_from_slice(&self.slices);
247 slices.extend_from_slice(&other.slices);
248 Link { slices }
249 }
250
251 pub fn push(&mut self, v: &Variable) -> Result<(), String> {
253 use crate::Variable::*;
254
255 match *v {
256 Bool(_, _) | F64(_, _) | Str(_) => {
257 if !self.slices.is_empty() {
258 let last = self.slices.last_mut().unwrap();
259 if (last.end as usize) < BLOCK_SIZE {
260 Arc::make_mut(&mut last.block).push(v, last.end as usize);
261 last.end += 1;
262 return Ok(());
263 }
264 }
265
266 self.slices.push(Slice::new());
267 let last = self.slices.last_mut().unwrap();
268 Arc::make_mut(&mut last.block).push(v, 0);
269 last.end = 1;
270 Ok(())
271 }
272 Link(ref link) => {
273 for slice in &link.slices {
274 for i in slice.start..slice.end {
275 self.push(&slice.block.var(i))?
276 }
277 }
278 Ok(())
279 }
280 _ => Err("Expected `bool`, `f64` or `str`".into()),
281 }
282 }
283}