serser/
into.rs

1use crate::token::*;
2use crate::TokenSink;
3
4/// Provides a way to associate appropriate sources with Rust data types.
5pub trait IntoTokens {
6    /// Yields tokens to the sink, one by one. If
7    /// [TokenSink::yield_token] returns false while there are more
8    /// tokens, this function should fail with `invalid_token`.
9    fn into_tokens<S: TokenSink>(&self, sink: &mut S) -> Result<(), S::Error>;
10}
11
12macro_rules! basic_into_tokens [
13    ($($id:ident => $ty:ty),*$(,)?) => {
14        $(impl IntoTokens for $ty {
15            fn into_tokens<S: TokenSink>(&self, sink: &mut S) -> Result<(), S::Error> {
16                sink.yield_token(Token::$id(*self)).map(|_| ())
17            }
18        })*
19    };
20];
21
22basic_into_tokens![
23    Bool => bool,
24
25    U8 => u8,
26    U16 => u16,
27    U32 => u32,
28    U64 => u64,
29    U128 => u128,
30    Usize => usize,
31
32    I8 => i8,
33    I16 => i16,
34    I32 => i32,
35    I64 => i64,
36    I128 => i128,
37    Isize => isize,
38
39    F32 => f32,
40    F64 => f64,
41    Char => char,
42    Bytes => &'_ [u8],
43    Str => &'_ str,
44];
45
46impl IntoTokens for () {
47    fn into_tokens<S: TokenSink>(&self, sink: &mut S) -> Result<(), S::Error> {
48        sink.yield_token(Token::Unit).map(|_| ())
49    }
50}
51
52impl<'a, K, V> IntoTokens for (K, V)
53where
54    K: IntoTokens,
55    V: IntoTokens,
56{
57    fn into_tokens<S: TokenSink>(&self, sink: &mut S) -> Result<(), S::Error> {
58        sink.yield_token(Token::Tuple(TupleMeta { size_hint: Some(2) }))?;
59        self.0.into_tokens(sink)?;
60        self.1.into_tokens(sink)?;
61        sink.yield_token(Token::EndTuple).map(|_| ())
62    }
63}
64
65impl<T> IntoTokens for [T]
66where
67    T: IntoTokens,
68{
69    fn into_tokens<S: TokenSink>(&self, sink: &mut S) -> Result<(), S::Error> {
70        iter_into_tokens(self.iter(), sink).map(|_| ())
71    }
72}
73
74impl<T> IntoTokens for Vec<T>
75where
76    T: IntoTokens,
77{
78    fn into_tokens<S: TokenSink>(&self, sink: &mut S) -> Result<(), S::Error> {
79        iter_into_tokens(self.iter(), sink).map(|_| ())
80    }
81}
82
83/// Yields the contents of an iterator as a [Token::Seq].
84pub fn iter_into_tokens<'a, I: Iterator<Item = &'a T>, S: TokenSink, T>(
85    it: I,
86    sink: &mut S,
87) -> Result<(), S::Error>
88where
89    T: 'a + IntoTokens,
90{
91    let (_, size_hint) = it.size_hint();
92    sink.yield_token(Token::Seq(SeqMeta { size_hint }))?;
93
94    for elem in it {
95        elem.into_tokens(sink)?;
96    }
97
98    sink.yield_token(Token::EndSeq).map(|_| ())
99}
100
101impl<'a> IntoTokens for Token<'a> {
102    fn into_tokens<S: TokenSink>(&self, sink: &mut S) -> Result<(), S::Error> {
103        sink.yield_token(self.clone())?;
104        Ok(())
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    use super::*;
111    use crate::vec::*;
112
113    #[test]
114    fn test_bool_into() {
115        let mut got = TokenVec::new();
116        true.into_tokens(&mut got).unwrap();
117        assert_eq!(got.into_vec(), vec![OwningToken::Bool(true)]);
118    }
119
120    #[test]
121    fn test_u32_into() {
122        let mut got = TokenVec::new();
123        42u32.into_tokens(&mut got).unwrap();
124        assert_eq!(got.into_vec(), vec![OwningToken::U32(42)]);
125    }
126
127    #[test]
128    fn test_tuple_into() {
129        let mut got = TokenVec::new();
130        (42u32, true).into_tokens(&mut got).unwrap();
131        assert_eq!(
132            got.into_vec(),
133            vec![
134                OwningToken::Tuple(TupleMeta { size_hint: Some(2) }),
135                OwningToken::U32(42),
136                OwningToken::Bool(true),
137                OwningToken::EndTuple,
138            ]
139        );
140    }
141
142    #[test]
143    fn test_vec_u32_into() {
144        let mut got = TokenVec::new();
145        vec![42u32].into_tokens(&mut got).unwrap();
146        assert_eq!(
147            got.into_vec(),
148            vec![
149                OwningToken::Seq(SeqMeta { size_hint: Some(1) }),
150                OwningToken::U32(42),
151                OwningToken::EndSeq,
152            ],
153        );
154    }
155}