read_fonts/tables/
ltag.rs

1//! The [language tag](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ltag.html) table.
2
3include!("../../generated/generated_ltag.rs");
4
5impl<'a> Ltag<'a> {
6    /// Returns an iterator yielding the index and string value of each
7    /// tag in the table.
8    pub fn tag_indices(&self) -> impl Iterator<Item = (u32, &'a str)> {
9        let table_data = self.offset_data().as_bytes();
10        self.tag_ranges()
11            .iter()
12            .enumerate()
13            .filter_map(move |(index, range)| {
14                let start = range.offset() as usize;
15                // These are u16 so can't overflow even in 32-bit
16                let range = start..start + range.length() as usize;
17                let string_bytes = table_data.get(range)?;
18                let s = core::str::from_utf8(string_bytes).ok()?;
19                Some((index as u32, s))
20            })
21    }
22
23    /// Returns the index of the given language tag.
24    pub fn index_for_tag(&self, tag: &str) -> Option<u32> {
25        self.tag_indices().find(|x| x.1 == tag).map(|x| x.0)
26    }
27}
28
29#[cfg(test)]
30mod tests {
31    use font_test_data::bebuffer::BeBuffer;
32
33    use super::*;
34
35    #[test]
36    fn tags() {
37        // Second sample at <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ltag.html>
38        let mut buf = BeBuffer::new();
39        // header
40        buf = buf.extend([1u32, 0, 3]);
41        // tag records
42        buf = buf.extend([24u16, 2, 26, 2, 28, 2]);
43        // string data
44        buf = buf.extend("enspsr".as_bytes().iter().copied());
45        let expected_tags = [(0, "en"), (1, "sp"), (2, "sr")];
46        let ltag = Ltag::read(buf.data().into()).unwrap();
47        let tags = ltag.tag_indices().collect::<Vec<_>>();
48        assert_eq!(tags, expected_tags);
49        assert_eq!(ltag.index_for_tag("en"), Some(0));
50        assert_eq!(ltag.index_for_tag("sp"), Some(1));
51        assert_eq!(ltag.index_for_tag("sr"), Some(2));
52        assert_eq!(ltag.index_for_tag("ar"), None);
53        assert_eq!(ltag.index_for_tag("hi"), None);
54    }
55}