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