@@ -6,9 +6,9 @@ use std::borrow::Cow;
66use std:: cmp:: Ordering ;
77use std:: collections:: { BTreeMap , BTreeSet , HashMap } ;
88use std:: fmt:: Write ;
9- use std:: iter:: { once, Peekable } ;
9+ use std:: iter:: once;
1010use std:: path:: PathBuf ;
11- use std:: str:: { Chars , FromStr } ;
11+ use std:: str:: FromStr ;
1212
1313/// Generates the [type stubs](https://typing.readthedocs.io/en/latest/source/stubs.html) of a given module.
1414/// It returns a map between the file name and the file content.
@@ -140,18 +140,25 @@ fn dunder_all_stubs(module: &Module, imports: &Imports) -> Option<String> {
140140 if module. incomplete {
141141 return None ;
142142 }
143- let mut names = module
144- . modules
145- . iter ( )
146- . map ( |m| & m. name )
147- . chain ( module. classes . iter ( ) . map ( |c| & c. name ) )
148- . chain ( module. functions . iter ( ) . map ( |f| & f. name ) )
149- . chain ( module. attributes . iter ( ) . map ( |a| & a. name ) )
150- . collect :: < Vec < _ > > ( ) ;
151- if names. is_empty ( ) {
143+ let member_count = module. modules . len ( )
144+ + module. classes . len ( )
145+ + module. functions . len ( )
146+ + module. attributes . len ( ) ;
147+ if member_count == 0 {
152148 // Nothing was ever added to the module, so it has no `__all__` at runtime either
153149 return None ;
154150 }
151+
152+ let mut names = Vec :: with_capacity ( member_count) ;
153+ names. extend (
154+ module
155+ . modules
156+ . iter ( )
157+ . map ( |m| & m. name )
158+ . chain ( module. classes . iter ( ) . map ( |c| & c. name ) )
159+ . chain ( module. functions . iter ( ) . map ( |f| & f. name ) )
160+ . chain ( module. attributes . iter ( ) . map ( |a| & a. name ) ) ,
161+ ) ;
155162 names. sort_unstable_by ( |a, b| isort_style_cmp ( a, b) ) ;
156163
157164 let mut buffer = "__all__ = " . to_string ( ) ;
@@ -214,40 +221,37 @@ fn isort_style_cmp(a: &str, b: &str) -> Ordering {
214221/// (so `arg2` comes before `arg10`), everything else by code point.
215222///
216223/// [natural order]: https://en.wikipedia.org/wiki/Natural_sort_order
217- fn natural_cmp ( a : & str , b : & str ) -> Ordering {
218- fn take_digits ( chars : & mut Peekable < Chars < ' _ > > ) -> String {
219- let mut digits = String :: new ( ) ;
220- while let Some ( c) = chars. next_if ( char:: is_ascii_digit) {
221- digits. push ( c) ;
222- }
223- digits
224+ fn natural_cmp ( mut a : & str , mut b : & str ) -> Ordering {
225+ /// Splits the leading run of digits from the rest
226+ fn split_digits ( s : & str ) -> ( & str , & str ) {
227+ s. split_at ( s. find ( |c : char | !c. is_ascii_digit ( ) ) . unwrap_or ( s. len ( ) ) )
224228 }
225229
226- let mut a = a. chars ( ) . peekable ( ) ;
227- let mut b = b. chars ( ) . peekable ( ) ;
228230 loop {
229231 // The one that is exhausted first comes first
230- let ( next_a, next_b) = match ( a. peek ( ) . copied ( ) , b. peek ( ) . copied ( ) ) {
232+ let ( next_a, next_b) = match ( a. chars ( ) . next ( ) , b. chars ( ) . next ( ) ) {
231233 ( None , None ) => return Ordering :: Equal ,
232234 ( None , Some ( _) ) => return Ordering :: Less ,
233235 ( Some ( _) , None ) => return Ordering :: Greater ,
234236 ( Some ( next_a) , Some ( next_b) ) => ( next_a, next_b) ,
235237 } ;
236238 let ordering = if next_a. is_ascii_digit ( ) && next_b. is_ascii_digit ( ) {
237- let ( digits_a, digits_b) = ( take_digits ( & mut a) , take_digits ( & mut b) ) ;
239+ let ( digits_a, digits_b) ;
240+ ( digits_a, a) = split_digits ( a) ;
241+ ( digits_b, b) = split_digits ( b) ;
238242 if next_a == '0' || next_b == '0' {
239243 // A leading zero makes the run a fraction, compared digit by digit
240- digits_a. cmp ( & digits_b)
244+ digits_a. cmp ( digits_b)
241245 } else {
242246 // The longest run spells the biggest number, ties go to the first differing digit
243247 digits_a
244248 . len ( )
245249 . cmp ( & digits_b. len ( ) )
246- . then_with ( || digits_a. cmp ( & digits_b) )
250+ . then_with ( || digits_a. cmp ( digits_b) )
247251 }
248252 } else {
249- a. next ( ) ;
250- b. next ( ) ;
253+ a = & a [ next_a . len_utf8 ( ) .. ] ;
254+ b = & b [ next_b . len_utf8 ( ) .. ] ;
251255 next_a. cmp ( & next_b)
252256 } ;
253257 if ordering != Ordering :: Equal {
0 commit comments