1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use syn::Ident;
use quote::{quote, ToTokens};
use proc_macro2::{TokenStream, Literal};
use crate::util::ToIdent;
pub struct TableStack {
tables: Vec<(Ident, [u8; 256])>,
shift: u8,
}
pub struct TableView<'a> {
ident: &'a Ident,
table: &'a mut [u8; 256],
mask: u8,
}
impl TableStack {
pub fn new() -> Self {
TableStack {
tables: vec![("COMPACT_TABLE_0".to_ident(), [0; 256])],
shift: 0,
}
}
pub fn view(&mut self) -> TableView {
let mask = if self.shift < 8 {
let mask = 1u8 << self.shift;
self.shift += 1;
mask
} else {
let ident = format!("COMPACT_TABLE_{}", self.tables.len()).to_ident();
self.tables.push((ident, [0; 256]));
self.shift = 1;
1
};
let (ref ident, ref mut table) = self.tables.last_mut().unwrap();
TableView {
ident,
table,
mask,
}
}
}
impl<'a> TableView<'a> {
pub fn ident(&self) -> &'a Ident {
self.ident
}
pub fn flag(&mut self, byte: u8) {
self.table[byte as usize] |= self.mask;
}
pub fn mask(&self) -> Literal {
Literal::u8_unsuffixed(self.mask)
}
}
impl ToTokens for TableStack {
fn to_tokens(&self, out: &mut TokenStream) {
if self.shift == 0 {
return;
}
for (ident, table) in self.tables.iter() {
let bytes = table.iter().copied().map(Literal::u8_unsuffixed);
out.extend(quote! {
static #ident: [u8; 256] = [#(#bytes),*];
});
}
}
}