character_set/dump/
mod.rs1use std::{fmt::Write, mem::take};
2
3use ucd_trie::TrieSetSlice;
4
5use crate::CharacterSet;
6
7#[derive(Debug, Clone)]
8pub struct DumpAction {
9 pub name: String,
10 pub public: String,
11 pub skip_fmt: bool,
12 pub dump_tree: bool,
13 pub dump_check: bool,
14 pub dump_range: bool,
15 pub trie_set: String,
16}
17
18impl Default for DumpAction {
19 fn default() -> Self {
20 Self {
21 name: "".to_string(),
22 public: "pub".to_string(),
23 skip_fmt: true,
24 dump_tree: true,
25 dump_check: true,
26 dump_range: true,
27 trie_set: "ucd_trie::TrieSet".to_string(),
28 }
29 }
30}
31
32impl DumpAction {
33 pub fn dump(&self, set: &CharacterSet) -> Result<String, std::fmt::Error> {
34 let mut out = String::new();
35 if self.dump_range {
36 self.write_range(set, &mut out)?;
37 return Ok(out);
38 }
39 if self.dump_tree {
40 let tree = set.compress();
41 self.write_tree(tree.as_slice(), &mut out)?;
42 if self.dump_check {
43 out.push_str("\n\n");
44 self.write_check(&mut out)?
45 }
46 return Ok(out);
47 }
48 return Ok(out);
49 }
50
51 fn write_range(&self, set: &CharacterSet, w: &mut impl Write) -> Result<(), std::fmt::Error> {
52 let ranges = set.to_ranges();
53 self.write_skip_fmt(w)?;
54 self.write_public(w)?;
55 writeln!(w, "const {name}: &'static [RangeInclusive<char>] = &[", name = self.name)?;
56 const MAX: usize = 144;
57 let mut buffer = String::with_capacity(2 * MAX);
58 for range in ranges {
59 if buffer.len() <= MAX {
60 write!(buffer, "{:?}..={:?},", range.start(), range.end())?;
61 }
62 else {
63 writeln!(w, " {}", take(&mut buffer))?;
64 }
65 }
66 writeln!(w, " {}", take(&mut buffer))?;
67 write!(w, "];")?;
68 Ok(())
69 }
70
71 fn write_tree(&self, tree: TrieSetSlice, w: &mut impl Write) -> Result<(), std::fmt::Error> {
72 self.write_skip_fmt(w)?;
73 self.write_public(w)?;
74 writeln!(w, "const {name}: {trie_set} = {trie_set} {{", name = self.name, trie_set = self.trie_set)?;
75 writeln!(w, " tree1_level1: &{:?},", tree.tree1_level1)?;
76 writeln!(w, " tree2_level1: &{:?},", tree.tree2_level1)?;
77 writeln!(w, " tree2_level2: &{:?},", tree.tree2_level2)?;
78 writeln!(w, " tree3_level1: &{:?},", tree.tree3_level1)?;
79 writeln!(w, " tree3_level2: &{:?},", tree.tree3_level2)?;
80 writeln!(w, " tree3_level3: &{:?},", tree.tree3_level3)?;
81 write!(w, "}};")?;
82 Ok(())
83 }
84 fn write_check(&self, w: &mut impl Write) -> Result<(), std::fmt::Error> {
85 self.write_public(w)?;
86 writeln!(w, "fn is_{name}(c: char) -> bool {{", name = self.name.to_ascii_lowercase())?;
87 writeln!(w, " {name}.contains_char(c)", name = self.name)?;
88 write!(w, "}};")?;
89 Ok(())
90 }
91 fn write_skip_fmt(&self, writer: &mut impl Write) -> Result<(), std::fmt::Error> {
92 if self.skip_fmt {
93 writer.write_str("#[rustfmt::skip]")?;
94 writer.write_char('\n')?;
95 }
96 Ok(())
97 }
98 fn write_public(&self, writer: &mut impl Write) -> Result<(), std::fmt::Error> {
99 if !self.public.is_empty() {
100 writer.write_str(&self.public)?;
101 writer.write_char(' ')?;
102 }
103 Ok(())
104 }
105}