1
1
use std:: borrow:: Cow ;
2
+ use std:: cmp:: Ordering ;
2
3
3
4
use either:: Either ;
4
5
use quote:: { ToTokens , Tokens } ;
@@ -120,43 +121,29 @@ struct Region {
120
121
}
121
122
122
123
impl Region {
123
- /// Find the longest common prefix of the identifier names
124
- /// for the fields in this region, if any.
125
- fn common_prefix ( & self ) -> Option < String > {
126
- let mut char_vecs = Vec :: new ( ) ;
127
- let mut min_len = usize:: max_value ( ) ;
128
-
129
- for f in & self . fields {
130
- match f. field . ident {
131
- None => return None ,
132
- Some ( ref ident) => {
133
- let chars : Vec < char > = ident. as_ref ( ) . chars ( ) . collect ( ) ;
134
- min_len = min_len. min ( chars. len ( ) ) ;
135
- char_vecs. push ( chars) ;
124
+ fn shortest_ident ( & self ) -> Option < String > {
125
+ let mut idents: Vec < _ > = self . fields
126
+ . iter ( )
127
+ . filter_map ( |f| {
128
+ match f. field . ident {
129
+ None => None ,
130
+ Some ( ref ident) => {
131
+ Some ( ident. as_ref ( ) )
132
+ }
136
133
}
137
- }
134
+ } )
135
+ . collect ( ) ;
136
+ if idents. is_empty ( ) {
137
+ return None ;
138
138
}
139
-
140
- let mut result = String :: new ( ) ;
141
-
142
- for i in 0 ..min_len {
143
- let c = char_vecs[ 0 ] [ i] ;
144
- for v in & char_vecs {
145
- if v[ i] != c {
146
- break ;
147
- }
139
+ idents. sort_by ( |a, b| {
140
+ // Sort by length and then content
141
+ match a. len ( ) . cmp ( & b. len ( ) ) {
142
+ Ordering :: Equal => a. cmp ( b) ,
143
+ cmp @ _ => cmp
148
144
}
149
-
150
- // This character position is the same across
151
- // all variants, so emit it into the result
152
- result. push ( c) ;
153
- }
154
-
155
- if result. is_empty ( ) {
156
- None
157
- } else {
158
- Some ( result)
159
- }
145
+ } ) ;
146
+ Some ( idents[ 0 ] . to_owned ( ) )
160
147
}
161
148
162
149
/// Return a description of this region
@@ -298,6 +285,8 @@ fn register_or_cluster_block(
298
285
299
286
for reg_block_field in & region. fields {
300
287
if reg_block_field. offset != region. offset {
288
+ // TODO: need to emit padding for this case.
289
+ // Happens for freescale_mkl43z4
301
290
eprintln ! ( "WARNING: field {:?} has different offset {} than its union container {}" ,
302
291
reg_block_field. field. ident,
303
292
reg_block_field. offset,
@@ -319,15 +308,15 @@ fn register_or_cluster_block(
319
308
}
320
309
321
310
if region. fields . len ( ) > 1 && !block_is_union {
322
- let ( type_name, name) = match region. common_prefix ( ) {
311
+ let ( type_name, name) = match region. shortest_ident ( ) {
323
312
Some ( prefix) => {
324
- ( Ident :: new ( format ! ( "{}_union " , prefix) ) ,
313
+ ( Ident :: new ( format ! ( "{}Union " , prefix. to_sanitized_upper_case ( ) ) ) ,
325
314
Ident :: new ( prefix) )
326
315
}
327
- // If we can't find a common prefix for the name, fall back to the
328
- // region index as a unique-within-this-block identifier counter.
316
+ // If we can't find a name, fall back to theregion index as a
317
+ // unique-within-this-block identifier counter.
329
318
None => {
330
- let ident = Ident :: new ( format ! ( "u {}" , i) ) ;
319
+ let ident = Ident :: new ( format ! ( "U {}" , i) ) ;
331
320
( ident. clone ( ) , ident)
332
321
}
333
322
} ;
0 commit comments