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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use crate::common;
use crate::Error;
use std::collections::HashSet;
use std::fs::File;
use std::io::Write;
use ucd_parse::Codepoints::{Range, Single};
use ucd_parse::{Codepoint, Codepoints};
pub fn generate_file_header(file: &mut File) -> Result<(), Error> {
let pkg_name = env!("CARGO_PKG_NAME");
let version = env!("CARGO_PKG_VERSION");
writeln!(
file,
"// File generated with {} version {}",
pkg_name, version
)?;
Ok(writeln!(file)?)
}
pub fn generate_codepoints_struct(file: &mut File) -> Result<(), Error> {
writeln!(
file,
"/// A representation of either a single codepoint or a range of codepoints."
)?;
writeln!(file, "pub enum Codepoints {{")?;
writeln!(file, "/// A single codepoint.")?;
writeln!(file, "\tSingle(u32),")?;
writeln!(file, "/// A range of codepoints.")?;
writeln!(file, "\tRange(std::ops::RangeInclusive<u32>),")?;
writeln!(file, "}}")?;
Ok(writeln!(file)?)
}
pub fn generate_codepoint_str(c: &Codepoints) -> String {
match c {
Single(cp) => format!("Codepoints::Single({:#06x})", cp.value()),
Range(r) => format!(
"Codepoints::Range(std::ops::RangeInclusive::new({:#06x}, {:#06x}))",
r.start.value(),
r.end.value()
),
}
}
fn vector_start(file: &mut File, t: &str, name: &str, len: usize) -> Result<(), Error> {
let const_name = name.to_uppercase();
Ok(writeln!(
file,
"static {}: [{}; {}] = [",
const_name, t, len
)?)
}
fn vector_codepoints(file: &mut File, vec: &[Codepoints]) -> Result<(), Error> {
for cps in vec.iter() {
writeln!(file, "\t{},", generate_codepoint_str(cps))?;
}
Ok(())
}
fn vector_end(file: &mut File) -> Result<(), Error> {
writeln!(file, "];")?;
Ok(writeln!(file)?)
}
pub fn generate_width_mapping_vector(
file: &mut File,
name: &str,
vec: &[(Codepoints, Codepoint)],
) -> Result<(), Error> {
vector_start(file, "(Codepoints, u32)", name, vec.len())?;
for (cps, cp) in vec.iter() {
writeln!(
file,
"\t({}, {:#06x}),",
generate_codepoint_str(cps),
cp.value()
)?;
}
vector_end(file)
}
pub fn generate_code_from_hashset(
file: &mut File,
name: &str,
codepoints: &HashSet<u32>,
) -> Result<(), Error> {
let vec = common::get_codepoints_vector(codepoints);
generate_code_from_vec(file, name, &vec)
}
pub fn generate_code_from_range(
file: &mut File,
name: &str,
range: &std::ops::Range<u32>,
) -> Result<(), Error> {
let mut codepoints = HashSet::new();
for cp in range.start..=range.end {
assert!(
codepoints.insert(cp),
"Codepoint {:#06x} repeated in {} range",
cp,
name
);
}
generate_code_from_hashset(file, name, &codepoints)
}
pub fn generate_code_from_vec(
file: &mut File,
name: &str,
vec: &[Codepoints],
) -> Result<(), Error> {
vector_start(file, "Codepoints", name, vec.len())?;
vector_codepoints(file, vec)?;
vector_end(file)
}