@@ -15,11 +15,12 @@ use crate::protofile::MessageDescription;
15
15
use crate :: protofile:: SequenceType ;
16
16
use alloc:: borrow:: Cow ;
17
17
use alloc:: boxed:: Box ;
18
+ use alloc:: collections:: VecDeque ;
18
19
use alloc:: format;
19
20
use alloc:: string:: String ;
20
21
use alloc:: vec:: Vec ;
21
22
use heck:: ToUpperCamelCase ;
22
- use std:: collections:: HashSet ;
23
+ use std:: collections:: HashMap ;
23
24
use std:: io;
24
25
use std:: io:: Write ;
25
26
use std:: path:: Path ;
@@ -44,8 +45,6 @@ impl<'a> DescriptorWriter<'a> {
44
45
45
46
// Sort the descriptors to get a consistent order from run to run and build to build.
46
47
descriptors. sort_by_key ( |desc| ( desc. package , desc. message . name ) ) ;
47
- // Deduplicate by package and name. TODO: ensure duplicates match.
48
- descriptors. dedup_by_key ( |desc| ( desc. package , desc. message . name ) ) ;
49
48
50
49
Self {
51
50
descriptors,
@@ -188,34 +187,39 @@ impl Write for PackageWriter<'_, '_> {
188
187
fn referenced_descriptors < ' a > (
189
188
descriptors : impl IntoIterator < Item = & ' a MessageDescription < ' a > > ,
190
189
) -> Vec < & ' a TopLevelDescriptor < ' a > > {
190
+ // Deduplicate by package and name. TODO: ensure duplicates match.
191
191
let mut descriptors =
192
- Vec :: from_iter ( descriptors. into_iter ( ) . copied ( ) . filter_map ( |d| match d {
193
- MessageDescription :: Internal ( tld) => Some ( tld) ,
192
+ HashMap :: from_iter ( descriptors. into_iter ( ) . copied ( ) . filter_map ( |d| match d {
193
+ MessageDescription :: Internal ( tld) => Some ( ( ( tld. package , tld . message . name ) , tld ) ) ,
194
194
MessageDescription :: External { .. } => None ,
195
195
} ) ) ;
196
- let mut inserted = HashSet :: from_iter ( descriptors. iter ( ) . copied ( ) ) ;
196
+
197
+ let mut queue = VecDeque :: from_iter ( descriptors. values ( ) . copied ( ) ) ;
197
198
198
199
fn process_field_type < ' a > (
199
200
field_type : & FieldType < ' a > ,
200
- descriptors : & mut Vec < & ' a TopLevelDescriptor < ' a > > ,
201
- inserted : & mut HashSet < & ' a TopLevelDescriptor < ' a > > ,
201
+ descriptors : & mut HashMap < ( & ' a str , & ' a str ) , & ' a TopLevelDescriptor < ' a > > ,
202
+ queue : & mut VecDeque < & ' a TopLevelDescriptor < ' a > > ,
202
203
) {
203
204
match field_type. kind {
204
205
FieldKind :: Message ( tld) => {
205
206
if let MessageDescription :: Internal ( tld) = tld ( ) {
206
- if inserted. insert ( tld) {
207
- descriptors. push ( tld) ;
207
+ if descriptors
208
+ . insert ( ( tld. package , tld. message . name ) , tld)
209
+ . is_none ( )
210
+ {
211
+ queue. push_back ( tld) ;
208
212
}
209
213
}
210
214
}
211
215
FieldKind :: Tuple ( tys) => {
212
216
for ty in tys {
213
- process_field_type ( ty, descriptors, inserted ) ;
217
+ process_field_type ( ty, descriptors, queue ) ;
214
218
}
215
219
}
216
220
FieldKind :: KeyValue ( tys) => {
217
221
for ty in tys {
218
- process_field_type ( ty, descriptors, inserted ) ;
222
+ process_field_type ( ty, descriptors, queue ) ;
219
223
}
220
224
}
221
225
FieldKind :: Builtin ( _) | FieldKind :: Local ( _) | FieldKind :: External { .. } => { }
@@ -224,28 +228,26 @@ fn referenced_descriptors<'a>(
224
228
225
229
fn process_message < ' a > (
226
230
message : & MessageDescriptor < ' a > ,
227
- descriptors : & mut Vec < & ' a TopLevelDescriptor < ' a > > ,
228
- inserted : & mut HashSet < & ' a TopLevelDescriptor < ' a > > ,
231
+ descriptors : & mut HashMap < ( & ' a str , & ' a str ) , & ' a TopLevelDescriptor < ' a > > ,
232
+ queue : & mut VecDeque < & ' a TopLevelDescriptor < ' a > > ,
229
233
) {
230
234
for field in message
231
235
. fields
232
236
. iter ( )
233
237
. chain ( message. oneofs . iter ( ) . flat_map ( |oneof| oneof. variants ) )
234
238
{
235
- process_field_type ( & field. field_type , descriptors, inserted ) ;
239
+ process_field_type ( & field. field_type , descriptors, queue ) ;
236
240
}
237
241
for inner in message. messages {
238
- process_message ( inner, descriptors, inserted ) ;
242
+ process_message ( inner, descriptors, queue ) ;
239
243
}
240
244
}
241
245
242
- let mut i = 0 ;
243
- while let Some ( & tld) = descriptors. get ( i) {
244
- process_message ( tld. message , & mut descriptors, & mut inserted) ;
245
- i += 1 ;
246
+ while let Some ( tld) = queue. pop_front ( ) {
247
+ process_message ( tld. message , & mut descriptors, & mut queue) ;
246
248
}
247
249
248
- descriptors
250
+ descriptors. values ( ) . copied ( ) . collect ( )
249
251
}
250
252
251
253
fn package_proto_file ( package : & str ) -> String {
0 commit comments