unicode_locale_parser/extensions/
pu.rs

1use crate::constants::SEP;
2use crate::errors::ParserError;
3use crate::extensions::ExtensionKind;
4
5use std::fmt::{self, Write};
6use std::iter::Peekable;
7
8#[derive(Debug)]
9pub struct PuExtensions {
10    pub values: Vec<String>,
11}
12
13impl fmt::Display for PuExtensions {
14    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
15        write!(f, "{}", ExtensionKind::Pu)?;
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_pu_extensions<'a>(
25    iter: &mut Peekable<impl Iterator<Item = &'a str>>,
26) -> Result<PuExtensions, ParserError> {
27    // pu_extensions
28    // https://www.unicode.org/reports/tr35/tr35-71/tr35.html#pu_extensions
29    let mut values = vec![];
30
31    for subtag in iter {
32        values.push(String::from(parse_value(subtag)?));
33    }
34
35    Ok(PuExtensions { values })
36}
37
38fn is_pu_value_subtag(subtag: &[u8]) -> bool {
39    (1..=8).contains(&subtag.len()) && subtag.iter().all(|c| c.is_ascii_alphanumeric())
40}
41
42fn parse_value(subtag: &str) -> Result<&str, ParserError> {
43    if !is_pu_value_subtag(subtag.as_bytes()) {
44        Err(ParserError::InvalidSubtag)
45    } else {
46        Ok(subtag)
47    }
48}
49
50/**
51 * Unit tests
52 */
53
54#[allow(unused_imports)] // for unit tests
55use crate::shared::split_str;
56
57#[test]
58fn success_pu_extensions() {
59    // full case
60    let mut iter = split_str("abc-123").peekable();
61    assert_eq!(
62        vec!["abc", "123"],
63        parse_pu_extensions(&mut iter).unwrap().values
64    );
65
66    // Display trait implementation
67    let mut iter = split_str("abc-123").peekable();
68    assert_eq!(
69        "x-abc-123",
70        format!("{}", parse_pu_extensions(&mut iter).unwrap())
71    );
72}
73
74#[test]
75fn fail_pu_extensions() {
76    // invalid subtag
77    let mut iter = split_str("abc-123456789").peekable();
78    assert_eq!(
79        ParserError::InvalidSubtag,
80        parse_pu_extensions(&mut iter).unwrap_err()
81    );
82}