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
82
83
84
85
86
87
88
89
90
use std::fmt::Write;

use ucd_trie::TrieSetSlice;

use crate::CharacterSet;

#[derive(Debug, Clone)]
pub struct DumpAction {
    pub name: String,
    pub public: String,
    pub skip_fmt: bool,
    pub dump_tree: bool,
    pub dump_check: bool,
    pub trie_set: String,
}

impl Default for DumpAction {
    fn default() -> Self {
        Self {
            name: "".to_string(),
            public: "pub".to_string(),
            skip_fmt: true,
            dump_tree: true,
            dump_check: true,
            trie_set: "ucd_trie::TrieSet".to_string(),
        }
    }
}

impl DumpAction {
    pub fn dump(&self, set: &CharacterSet) -> String {
        let mut out = String::new();
        if self.dump_tree {
            let tree = set.compress();
            self.write_tree(tree.as_slice(), &mut out).unwrap_or_default();
            if self.dump_check {
                out.push_str("\n\n");
                self.write_check(&mut out).unwrap_or_default()
            }
        }
        return out;
    }

    // fn write_range(&self) -> Result<String, std::fmt::Error> {
    //     let ranges = self.to_ranges();
    //     let mut w = String::new();
    //     let public = if public { "pub " } else { "" };
    //     writeln!(w, "const {}: &'static [(char, char); {}] = &[", public, name, ranges.len())?;
    //     for range in ranges {
    //         writeln!(w, "    ({:?}, {:?}),", range.start, range.end)?;
    //     }
    //     write!(w, "];")?;
    //     Ok(w)
    // }

    fn write_tree(&self, tree: TrieSetSlice, w: &mut impl Write) -> Result<(), std::fmt::Error> {
        self.write_skip_fmt(w)?;
        self.write_public(w)?;
        writeln!(w, "const {name}: {trie_set} = {trie_set} {{", name = self.name, trie_set = self.trie_set)?;
        writeln!(w, "    tree1_level1: &{:?},", tree.tree1_level1)?;
        writeln!(w, "    tree2_level1: &{:?},", tree.tree2_level1)?;
        writeln!(w, "    tree2_level2: &{:?},", tree.tree2_level2)?;
        writeln!(w, "    tree3_level1: &{:?},", tree.tree3_level1)?;
        writeln!(w, "    tree3_level2: &{:?},", tree.tree3_level2)?;
        writeln!(w, "    tree3_level3: &{:?},", tree.tree3_level3)?;
        write!(w, "}};")?;
        Ok(())
    }
    fn write_check(&self, w: &mut impl Write) -> Result<(), std::fmt::Error> {
        self.write_public(w)?;
        writeln!(w, "fn is_{name}(c: char) -> bool {{", name = self.name.to_ascii_lowercase())?;
        writeln!(w, "    {name}.contains_char(c)", name = self.name)?;
        write!(w, "}};")?;
        Ok(())
    }
    fn write_skip_fmt(&self, writer: &mut impl Write) -> Result<(), std::fmt::Error> {
        if self.skip_fmt {
            writer.write_str("#[rustfmt::skip]")?;
            writer.write_char('\n')?;
        }
        Ok(())
    }
    fn write_public(&self, writer: &mut impl Write) -> Result<(), std::fmt::Error> {
        if !self.public.is_empty() {
            writer.write_str(&self.public)?;
            writer.write_char(' ')?;
        }
        Ok(())
    }
}