ucd_util/property.rs
1/// The type of a property name table.
2///
3/// A property name table is a sequence of sorted tuples, where the first
4/// value in each tuple is a normalized property name and the second value of
5/// each tuple is the corresponding canonical property name.
6pub type PropertyTable = &'static [(&'static str, &'static str)];
7
8/// Find the canonical property name for the given normalized property name.
9///
10/// If no such property exists, then `None` is returned.
11///
12/// The normalized property name must have been normalized according to
13/// UAX44 LM3, which can be done using `symbolic_name_normalize`.
14pub fn canonical_property_name(
15 property_table: PropertyTable,
16 normalized_property_name: &str,
17) -> Option<&'static str> {
18 property_table
19 .binary_search_by_key(&normalized_property_name, |&(n, _)| n)
20 .ok()
21 .map(|i| property_table[i].1)
22}
23
24/// Type of a property value table.
25///
26/// A property value table maps property names to a mapping of property values,
27/// where the mapping of property values is represented by a sequence of
28/// tuples. The first element of each tuple is a normalized property value
29/// while the second element of each tuple is the corresponding canonical
30/// property value.
31///
32/// Note that a property value table only includes values for properties that
33/// are catalogs, enumerations or binary properties. Properties that have
34/// string values (such as case or decomposition mappings), numeric values
35/// or are miscellaneous are not represented in this table.
36pub type PropertyValueTable = &'static [(&'static str, PropertyValues)];
37
38/// A mapping of property values for a specific property.
39///
40/// The first element of each tuple is a normalized property value while the
41/// second element of each tuple is the corresponding canonical property
42/// value.
43pub type PropertyValues = &'static [(&'static str, &'static str)];
44
45/// Find the set of possible property values for a given property.
46///
47/// The set returned is a mapping expressed as a sorted list of tuples.
48/// The first element of each tuple is a normalized property value while the
49/// second element of each tuple is the corresponding canonical property
50/// value.
51///
52/// If no such property exists, then `None` is returned.
53///
54/// The given property name must be in its canonical form, which can be
55/// found using `canonical_property_name`.
56pub fn property_values(
57 property_value_table: PropertyValueTable,
58 canonical_property_name: &str,
59) -> Option<PropertyValues> {
60 property_value_table
61 .binary_search_by_key(&canonical_property_name, |&(n, _)| n)
62 .ok()
63 .map(|i| property_value_table[i].1)
64}
65
66/// Find the canonical property value for the given normalized property
67/// value.
68///
69/// The given property values should correspond to the values for the property
70/// under question, which can be found using `property_values`.
71///
72/// If no such property value exists, then `None` is returned.
73///
74/// The normalized property value must have been normalized according to
75/// UAX44 LM3, which can be done using `symbolic_name_normalize`.
76pub fn canonical_property_value(
77 property_values: PropertyValues,
78 normalized_property_value: &str,
79) -> Option<&'static str> {
80 // This is cute. The types line up, so why not?
81 canonical_property_name(property_values, normalized_property_value)
82}
83
84#[cfg(test)]
85mod tests {
86 use crate::unicode_tables::property_names::PROPERTY_NAMES;
87 use crate::unicode_tables::property_values::PROPERTY_VALUES;
88
89 use super::{
90 canonical_property_name, canonical_property_value, property_values,
91 };
92
93 #[test]
94 fn canonical_property_name_1() {
95 assert_eq!(
96 canonical_property_name(PROPERTY_NAMES, "gc"),
97 Some("General_Category")
98 );
99 assert_eq!(
100 canonical_property_name(PROPERTY_NAMES, "generalcategory"),
101 Some("General_Category")
102 );
103 assert_eq!(canonical_property_name(PROPERTY_NAMES, "g c"), None);
104 }
105
106 #[test]
107 fn property_values_1() {
108 assert_eq!(
109 property_values(PROPERTY_VALUES, "White_Space"),
110 Some(
111 &[
112 ("f", "No"),
113 ("false", "No"),
114 ("n", "No"),
115 ("no", "No"),
116 ("t", "Yes"),
117 ("true", "Yes"),
118 ("y", "Yes"),
119 ("yes", "Yes"),
120 ][..]
121 )
122 );
123 }
124
125 #[test]
126 fn canonical_property_value_1() {
127 let values = property_values(PROPERTY_VALUES, "White_Space").unwrap();
128 assert_eq!(canonical_property_value(values, "false"), Some("No"));
129 assert_eq!(canonical_property_value(values, "t"), Some("Yes"));
130 assert_eq!(canonical_property_value(values, "F"), None);
131 }
132}