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}