1 use std::str::FromStr; 2 3 use { 4 Error, 5 Result, 6 Stream, 7 WriteBuffer, 8 WriteOptions, 9 }; 10 11 /// Representation of the [`<list-of-numbers>`] type. 12 /// 13 /// [`<list-of-numbers>`]: https://www.w3.org/TR/SVG11/types.html#DataTypeList 14 #[derive(Clone, PartialEq, Default)] 15 pub struct NumberList(pub Vec<f64>); 16 17 impl_from_vec!(NumberList, NumberList, f64); 18 impl_vec_defer!(NumberList, f64); 19 impl_display!(NumberList); 20 impl_debug_from_display!(NumberList); 21 22 /// A pull-based [`<list-of-numbers>`] parser. 23 /// 24 /// # Example 25 /// 26 /// ``` 27 /// use svgtypes::NumberListParser; 28 /// 29 /// let mut p = NumberListParser::from("10, 20 -50"); 30 /// assert_eq!(p.next().unwrap().unwrap(), 10.0); 31 /// assert_eq!(p.next().unwrap().unwrap(), 20.0); 32 /// assert_eq!(p.next().unwrap().unwrap(), -50.0); 33 /// assert_eq!(p.next().is_none(), true); 34 /// ``` 35 /// 36 /// [`<list-of-numbers>`]: https://www.w3.org/TR/SVG11/types.html#DataTypeList 37 #[derive(Clone, Copy, PartialEq, Debug)] 38 pub struct NumberListParser<'a>(Stream<'a>); 39 40 impl<'a> From<&'a str> for NumberListParser<'a> { from(v: &'a str) -> Self41 fn from(v: &'a str) -> Self { 42 NumberListParser(Stream::from(v)) 43 } 44 } 45 46 impl<'a> Iterator for NumberListParser<'a> { 47 type Item = Result<f64>; 48 next(&mut self) -> Option<Self::Item>49 fn next(&mut self) -> Option<Self::Item> { 50 if self.0.at_end() { 51 None 52 } else { 53 let v = self.0.parse_list_number(); 54 if v.is_err() { 55 self.0.jump_to_end(); 56 } 57 58 Some(v) 59 } 60 } 61 } 62 63 impl FromStr for NumberList { 64 type Err = Error; 65 from_str(text: &str) -> Result<Self>66 fn from_str(text: &str) -> Result<Self> { 67 let mut vec = Vec::new(); 68 for number in NumberListParser::from(text) { 69 vec.push(number?); 70 } 71 72 Ok(NumberList(vec)) 73 } 74 } 75 76 #[cfg(test)] 77 mod tests { 78 use super::*; 79 use ListSeparator; 80 81 #[test] write_1()82 fn write_1() { 83 let list = NumberList(vec![1.0, 2.0, 3.0]); 84 85 let mut opt = WriteOptions::default(); 86 opt.list_separator = ListSeparator::Space; 87 88 assert_eq!(list.with_write_opt(&opt).to_string(), "1 2 3"); 89 } 90 91 #[test] write_2()92 fn write_2() { 93 let list = NumberList(vec![1.0, 2.0, 3.0]); 94 95 let mut opt = WriteOptions::default(); 96 opt.list_separator = ListSeparator::Comma; 97 98 assert_eq!(list.with_write_opt(&opt).to_string(), "1,2,3"); 99 } 100 101 #[test] write_3()102 fn write_3() { 103 let list = NumberList(vec![1.0, 2.0, 3.0]); 104 105 let mut opt = WriteOptions::default(); 106 opt.list_separator = ListSeparator::CommaSpace; 107 108 assert_eq!(list.with_write_opt(&opt).to_string(), "1, 2, 3"); 109 } 110 } 111