diff --git a/gen/trie.ts b/gen/trie.ts index 7dc1e40..a07a339 100644 --- a/gen/trie.ts +++ b/gen/trie.ts @@ -139,14 +139,18 @@ export class TrieBuilder { // Generate the code for a node's variable name and value, and return the name. private generateNode (node: Node): string { - // Only generate elements up to the last non-undefined child to cut down on size of array. + // Only generate defined children to cut down on size of array, which would otherwise + // bog down compile time and binary size for large trees with lots of nodes. + // If array is empty, just use zero. + const firstIdx = node.children.length && node.children.findIndex(v => v); const children = Array.from( - {length: node.children.length}, - (_, i) => node.children[i] ? `Some(${this.generateNode(node.children[i])})` : 'None', + {length: node.children.length - firstIdx}, + (_, i) => node.children[i + firstIdx] ? `Some(${this.generateNode(node.children[i + firstIdx])})` : 'None', ).join(', '); const value = node.value === undefined ? 'None' : `Some(${node.value})`; const varValue = `&crate::pattern::TrieNode { + offset: ${firstIdx}, value: ${value}, children: &[${children}], }`; diff --git a/src/pattern.rs b/src/pattern.rs index e62910e..deac257 100644 --- a/src/pattern.rs +++ b/src/pattern.rs @@ -33,6 +33,10 @@ impl SinglePattern { // Can't use pub const fn constructor due to Copy trait, so allow directly creating struct publicly for now. pub struct TrieNode { + // Using a children array of size 256 would probably be fastest, but waste too much memory and cause slow compiles + // and large binaries. Instead, we only store the children between the first and last defined (see `gen/trie.ts`). + // When getting a child, use `index + offset`. + pub offset: usize, pub value: Option, pub children: &'static [Option<&'static TrieNode>], } @@ -58,7 +62,7 @@ impl TrieNode { let mut node: &TrieNode = self; let mut next_pos = from; while let Some(&c) = text.get(next_pos) { - match node.children.get(c as usize) { + match node.children.get(c as usize + node.offset) { Some(Some(child)) => node = child, None | Some(None) => return None, };