@@ -5,15 +5,21 @@ use std::path::Path;
5
5
type StrResult < T > = Result < T , String > ;
6
6
7
7
/// A module of definitions.
8
- struct Module < ' a > ( Vec < ( & ' a str , Def < ' a > ) > ) ;
8
+ struct Module < ' a > ( Vec < ( & ' a str , Binding < ' a > ) > ) ;
9
9
10
10
impl < ' a > Module < ' a > {
11
- fn new ( mut list : Vec < ( & ' a str , Def < ' a > ) > ) -> Self {
11
+ fn new ( mut list : Vec < ( & ' a str , Binding < ' a > ) > ) -> Self {
12
12
list. sort_by_key ( |& ( name, _) | name) ;
13
13
Self ( list)
14
14
}
15
15
}
16
16
17
+ /// A definition bound in a module, with metadata.
18
+ struct Binding < ' a > {
19
+ def : Def < ' a > ,
20
+ deprecation : Option < & ' a str > ,
21
+ }
22
+
17
23
/// A definition in a module.
18
24
enum Def < ' a > {
19
25
Symbol ( Symbol < ' a > ) ,
@@ -30,6 +36,7 @@ enum Symbol<'a> {
30
36
#[ derive( Debug , Copy , Clone ) ]
31
37
enum Line < ' a > {
32
38
Blank ,
39
+ Deprecated ( & ' a str ) ,
33
40
ModuleStart ( & ' a str ) ,
34
41
ModuleEnd ,
35
42
Symbol ( & ' a str , Option < char > ) ,
@@ -91,7 +98,9 @@ fn tokenize(line: &str) -> StrResult<Line> {
91
98
None => ( line, None ) ,
92
99
} ;
93
100
94
- Ok ( if tail == Some ( "{" ) {
101
+ Ok ( if head == "@deprecated:" {
102
+ Line :: Deprecated ( tail. ok_or ( "missing deprecation message" ) ?. trim ( ) )
103
+ } else if tail == Some ( "{" ) {
95
104
validate_ident ( head) ?;
96
105
Line :: ModuleStart ( head)
97
106
} else if head == "}" && tail. is_none ( ) {
@@ -137,11 +146,18 @@ fn decode_char(text: &str) -> StrResult<char> {
137
146
/// Turns a stream of lines into a list of definitions.
138
147
fn parse < ' a > (
139
148
p : & mut Peekable < impl Iterator < Item = StrResult < Line < ' a > > > > ,
140
- ) -> StrResult < Vec < ( & ' a str , Def < ' a > ) > > {
149
+ ) -> StrResult < Vec < ( & ' a str , Binding < ' a > ) > > {
141
150
let mut defs = vec ! [ ] ;
151
+ let mut deprecation = None ;
142
152
loop {
143
153
match p. next ( ) . transpose ( ) ? {
144
- None | Some ( Line :: ModuleEnd ) => break ,
154
+ None | Some ( Line :: ModuleEnd ) => {
155
+ if let Some ( message) = deprecation {
156
+ return Err ( format ! ( "dangling `@deprecated: {}`" , message) ) ;
157
+ }
158
+ break ;
159
+ }
160
+ Some ( Line :: Deprecated ( message) ) => deprecation = Some ( message) ,
145
161
Some ( Line :: Symbol ( name, c) ) => {
146
162
let mut variants = vec ! [ ] ;
147
163
while let Some ( Line :: Variant ( name, c) ) = p. peek ( ) . cloned ( ) . transpose ( ) ? {
@@ -159,11 +175,19 @@ fn parse<'a>(
159
175
Symbol :: Single ( c)
160
176
} ;
161
177
162
- defs. push ( ( name, Def :: Symbol ( symbol) ) ) ;
178
+ defs. push ( ( name, Binding { def : Def :: Symbol ( symbol) , deprecation } ) ) ;
179
+ deprecation = None ;
163
180
}
164
181
Some ( Line :: ModuleStart ( name) ) => {
165
182
let module_defs = parse ( p) ?;
166
- defs. push ( ( name, Def :: Module ( Module :: new ( module_defs) ) ) ) ;
183
+ defs. push ( (
184
+ name,
185
+ Binding {
186
+ def : Def :: Module ( Module :: new ( module_defs) ) ,
187
+ deprecation,
188
+ } ,
189
+ ) ) ;
190
+ deprecation = None ;
167
191
}
168
192
other => return Err ( format ! ( "expected definition, found {other:?}" ) ) ,
169
193
}
@@ -174,9 +198,9 @@ fn parse<'a>(
174
198
/// Encodes a `Module` into Rust code.
175
199
fn encode ( buf : & mut String , module : & Module ) {
176
200
buf. push_str ( "Module(&[" ) ;
177
- for ( name, def ) in & module. 0 {
178
- write ! ( buf, "({name:?}," ) . unwrap ( ) ;
179
- match def {
201
+ for ( name, entry ) in & module. 0 {
202
+ write ! ( buf, "({name:?}, Binding {{ def: " ) . unwrap ( ) ;
203
+ match & entry . def {
180
204
Def :: Module ( module) => {
181
205
buf. push_str ( "Def::Module(" ) ;
182
206
encode ( buf, module) ;
@@ -191,7 +215,7 @@ fn encode(buf: &mut String, module: &Module) {
191
215
buf. push_str ( ")" ) ;
192
216
}
193
217
}
194
- buf . push_str ( " ),") ;
218
+ write ! ( buf , ", deprecation: {:?} }} ),", entry . deprecation ) . unwrap ( ) ;
195
219
}
196
220
buf. push_str ( "])" ) ;
197
221
}
0 commit comments