unicode_locale_parser/extensions/
pu.rs1use 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 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#[allow(unused_imports)] use crate::shared::split_str;
56
57#[test]
58fn success_pu_extensions() {
59 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 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 let mut iter = split_str("abc-123456789").peekable();
78 assert_eq!(
79 ParserError::InvalidSubtag,
80 parse_pu_extensions(&mut iter).unwrap_err()
81 );
82}