unicode_locale_parser/
measure.rs1use crate::constants::SEP;
2use crate::errors::ParserError;
3use crate::shared::split_str;
4
5use std::fmt::{self};
6use std::iter::Peekable;
7use std::str::FromStr;
8
9#[derive(Debug, PartialEq)]
10pub struct UnicodeMeasureUnit {
11 pub values: Vec<String>,
12}
13
14impl fmt::Display for UnicodeMeasureUnit {
15 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16 let mut messages = vec![];
17 for value in &self.values {
18 messages.push(value.to_string());
19 }
20 write!(f, "{}", messages.join(&SEP.to_string()))?;
21 Ok(())
22 }
23}
24
25impl FromStr for UnicodeMeasureUnit {
26 type Err = ParserError;
27
28 fn from_str(source: &str) -> Result<Self, Self::Err> {
29 parse_unicode_measure_unit(source)
30 }
31}
32
33pub fn parse_unicode_measure_unit(measure_unit: &str) -> Result<UnicodeMeasureUnit, ParserError> {
53 if measure_unit.is_empty() {
54 return Err(ParserError::Missing);
55 }
56
57 parse_unicode_measure_unit_from_iter(&mut split_str(measure_unit).peekable())
58}
59
60fn parse_unicode_measure_unit_from_iter<'a>(
61 iter: &mut Peekable<impl Iterator<Item = &'a str>>,
62) -> Result<UnicodeMeasureUnit, ParserError> {
63 let mut values = vec![];
66
67 while let Some(subtag) = iter.peek() {
68 let subtag_bytes = subtag.as_bytes();
69
70 if !(3..=8).contains(&subtag_bytes.len())
71 || !subtag_bytes.iter().all(|b: &u8| b.is_ascii_alphanumeric())
72 {
73 return Err(ParserError::InvalidSubtag);
74 }
75
76 values.push(subtag.to_string());
77 iter.next();
78 }
79
80 let values = if values.is_empty() {
81 return Err(ParserError::Missing);
82 } else {
83 values
84 };
85
86 Ok(UnicodeMeasureUnit { values })
87}
88
89#[test]
94fn success_parse_unicode_measure_unit() {
95 let measure = parse_unicode_measure_unit("area-hectare").unwrap();
97 assert_eq!(vec!["area", "hectare"], measure.values);
98
99 assert_eq!(
101 "area-hectare",
102 format!("{}", parse_unicode_measure_unit("area-hectare").unwrap())
103 );
104
105 assert_eq!(
107 parse_unicode_measure_unit("area-hectare").unwrap(),
108 parse_unicode_measure_unit("area-hectare").unwrap()
109 );
110
111 let measure: UnicodeMeasureUnit = "area-hectare".parse().unwrap();
113 assert_eq!(vec!["area", "hectare"], measure.values);
114}
115
116#[test]
117fn fail_parse_unicode_measure_unit() {
118 assert_eq!(
120 ParserError::Missing,
121 parse_unicode_measure_unit("").unwrap_err()
122 );
123
124 assert_eq!(
126 ParserError::InvalidSubtag,
127 parse_unicode_measure_unit("acceleration-g-force").unwrap_err()
128 );
129}