unicode_locale_parser/extensions/
other.rs

1use crate::constants::SEP;
2use crate::errors::ParserError;
3
4use std::fmt::{self, Write};
5use std::iter::Peekable;
6
7#[derive(Debug, PartialEq)]
8pub struct OtherExtensions {
9    pub values: Vec<String>,
10    pub extension: char,
11}
12
13impl fmt::Display for OtherExtensions {
14    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
15        f.write_char(self.extension)?;
16        for value in &self.values {
17            f.write_char(SEP)?;
18            f.write_str(value)?;
19        }
20        Ok(())
21    }
22}
23
24pub fn parse_other_extensions<'a>(
25    iter: &mut Peekable<impl Iterator<Item = &'a str>>,
26    extension: char,
27) -> Result<OtherExtensions, ParserError> {
28    // other_extensions
29    // https://www.unicode.org/reports/tr35/tr35-71/tr35.html#other_extensions
30    let mut values = vec![];
31
32    while let Some(subtag) = iter.peek() {
33        if subtag.len() == 1 {
34            break;
35        } else {
36            values.push(String::from(parse_value(subtag)?));
37            iter.next();
38        }
39    }
40
41    Ok(OtherExtensions { values, extension })
42}
43
44fn is_other_value_subtag(subtag: &[u8]) -> bool {
45    (2..=8).contains(&subtag.len()) && subtag.iter().all(|c| c.is_ascii_alphanumeric())
46}
47
48fn parse_value(subtag: &str) -> Result<&str, ParserError> {
49    if !is_other_value_subtag(subtag.as_bytes()) {
50        Err(ParserError::InvalidSubtag)
51    } else {
52        Ok(subtag)
53    }
54}
55
56/**
57 * Unit tests
58 */
59
60#[allow(unused_imports)] // for unit tests
61use crate::shared::split_str;
62
63#[test]
64fn success_other_extensions() {
65    // full case
66    let mut iter = split_str("abc-123").peekable();
67    assert_eq!(
68        vec!["abc", "123"],
69        parse_other_extensions(&mut iter, 'a').unwrap().values
70    );
71
72    // Display trait implementation
73    let mut iter = split_str("abc-123").peekable();
74    assert_eq!(
75        "b-abc-123",
76        format!("{}", parse_other_extensions(&mut iter, 'b').unwrap())
77    );
78}
79
80#[test]
81fn fail_pu_extensions() {
82    // invalid subtag
83    let mut iter = split_str("abc-123456789").peekable();
84    assert_eq!(
85        ParserError::InvalidSubtag,
86        parse_other_extensions(&mut iter, '1').unwrap_err()
87    );
88}