character-set 0.4.0

High performance `set.contains(char)`
Documentation
use std::{fmt::Write, mem::take};

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 dump_range: 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,
            dump_range: true,
            trie_set: "ucd_trie::TrieSet".to_string(),
        }
    }
}

impl DumpAction {
    pub fn dump(&self, set: &CharacterSet) -> Result<String, std::fmt::Error> {
        let mut out = String::new();
        if self.dump_range {
            self.write_range(set, &mut out)?;
            return Ok(out);
        }
        if self.dump_tree {
            let tree = set.compress();
            self.write_tree(tree.as_slice(), &mut out)?;
            if self.dump_check {
                out.push_str("\n\n");
                self.write_check(&mut out)?
            }
            return Ok(out);
        }
        return Ok(out);
    }

    fn write_range(&self, set: &CharacterSet, w: &mut impl Write) -> Result<(), std::fmt::Error> {
        let ranges = set.to_ranges();
        self.write_skip_fmt(w)?;
        self.write_public(w)?;
        writeln!(w, "const {name}: &'static [RangeInclusive<char>] = &[", name = self.name)?;
        const MAX: usize = 144;
        let mut buffer = String::with_capacity(2 * MAX);
        for range in ranges {
            if buffer.len() <= MAX {
                write!(buffer, "{:?}..={:?},", range.start(), range.end())?;
            }
            else {
                writeln!(w, "    {}", take(&mut buffer))?;
            }
        }
        writeln!(w, "    {}", take(&mut buffer))?;
        write!(w, "];")?;
        Ok(())
    }

    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(())
    }
}