• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use proc_macro::{TokenStream, TokenTree};
15 
16 /// Convert [`TokenStream`] to [`TupleParser`]
tuple_parser(input: TokenStream) -> TupleParser17 pub(crate) fn tuple_parser(input: TokenStream) -> TupleParser {
18     let buf = input.into_iter().collect::<Vec<_>>();
19 
20     let mut flag_with = false;
21     let mut flag_except = false;
22     let mut flag_at = false;
23 
24     let mut len = 0;
25     let mut default = TokenStream::new();
26     let mut except = TokenStream::new();
27     let mut except_index = 0;
28 
29     let mut idx = 0;
30     while idx < buf.len() {
31         match &buf[idx] {
32             TokenTree::Ident(ident) => {
33                 // Get Separator "with/except/at"
34                 match ident.to_string().as_str() {
35                     "with" => {
36                         flag_with = true;
37                         idx += 1;
38                         continue;
39                     }
40                     "except" => {
41                         flag_except = true;
42                         idx += 1;
43                         continue;
44                     }
45                     "at" => {
46                         flag_at = true;
47                         idx += 1;
48                         continue;
49                     }
50                     _ => {}
51                 }
52             }
53             TokenTree::Group(group) => {
54                 if !flag_with && !flag_except && !flag_at {
55                     // The tuple length is obtained by calculating the number of parenthesis layers
56                     // of ((0 + 1) + 1). Actually the '0' also has a parenthesis wrapped around it,
57                     // So here have to -1.
58                     len = group_num(group.stream()) - 1;
59                     idx += 1;
60                     continue;
61                 }
62                 if flag_with && flag_except && flag_at {
63                     // Get the except_index.
64                     except_index = group.stream().into_iter().count();
65                     idx += 1;
66                     continue;
67                 }
68             }
69             _ => {}
70         }
71 
72         // Get TupleParser's 'default' or 'except'
73         if flag_with && !flag_at {
74             let default_or_except = TokenStream::from((buf[idx]).to_owned());
75             if flag_except {
76                 except.extend(default_or_except);
77             } else {
78                 default.extend(default_or_except);
79             }
80         }
81 
82         idx += 1;
83     }
84     TupleParser {
85         len,
86         default,
87         except,
88         except_index,
89     }
90 }
91 
92 /// Recursively queried how many layers of [`TokenTree::Group`]
group_num(inner: TokenStream) -> usize93 fn group_num(inner: TokenStream) -> usize {
94     match inner.into_iter().next() {
95         Some(TokenTree::Group(group)) => group_num(group.stream()) + 1,
96         _ => 0,
97     }
98 }
99 
100 /// Necessary data for building tuples
101 pub(crate) struct TupleParser {
102     /// Length of Tuple
103     pub(crate) len: usize,
104     /// Default value of Tuple
105     pub(crate) default: TokenStream,
106     /// Except value of Tuple
107     pub(crate) except: TokenStream,
108     /// Index of the default value in the tuple
109     pub(crate) except_index: usize,
110 }
111