character_set/dump/
mod.rs

1use 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}