token_read/
to_tokens.rs

1use std::str::SplitWhitespace;
2
3use crate::FromTokens;
4
5/// A trait for types that can be used to create an iterator of tokens.
6///
7/// It can be used to easily parse strings.
8pub trait ToTokens<'a> {
9    type Iter: Iterator<Item = &'a str>;
10
11    /// Creates an iterator of tokens contained in the type.
12    fn to_tokens(&'a self) -> Self::Iter;
13
14    /// Parses all tokens into an (usually inferred) type.
15    ///
16    /// # Example
17    ///
18    /// ```
19    /// # use token_read::ToTokens;
20    /// # use anyhow::Result;
21    /// #
22    /// # fn main() -> Result<()> {
23    /// let (a, b): (u64, char) = "15 B".parse_tokens()?;
24    ///
25    /// assert_eq!(a, 15);
26    /// assert_eq!(b, 'B');
27    /// #
28    /// #   Ok(())
29    /// # }
30    /// ```
31    fn parse_tokens<T>(&'a self) -> Result<T, T::Error>
32    where
33        T: FromTokens,
34    {
35        T::from_tokens(self.to_tokens())
36    }
37}
38
39impl<'a> ToTokens<'a> for str {
40    type Iter = SplitWhitespace<'a>;
41
42    /// Splits the string by any whitespace (including newlines).
43    fn to_tokens(&'a self) -> Self::Iter {
44        self.split_whitespace()
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use crate::ToTokens;
51
52    #[test]
53    fn splits_string_at_whitespace() {
54        let tokens = "0 1".to_tokens();
55        let tokens: Vec<&str> = tokens.collect();
56        assert_eq!(tokens, vec!["0", "1"]);
57    }
58
59    #[test]
60    fn parse_tokens_parses_tokens() {
61        let numbers: Vec<u8> = "1 2".parse_tokens().unwrap();
62        assert_eq!(numbers, vec![1, 2]);
63    }
64}