@@ -37,6 +37,43 @@ impl Index<Range<Position>> for Url {
37
37
}
38
38
}
39
39
40
+ // Counts how many base-10 digits are required to represent n in the given base
41
+ fn count_digits ( n : u16 ) -> usize {
42
+ // just use ilog10 in 1.67+
43
+ if cfg ! ( int_log) {
44
+ return n. checked_ilog10 ( ) . unwrap_or ( 0 ) as usize + 1 ;
45
+ }
46
+ // fall-back before 1.67
47
+ // we avoid a branch to handle the special case of n == 0 by starting at m = 10 instead of m = 1
48
+ let mut m = 10 ;
49
+ let mut log10m = 1 ;
50
+ while m <= n {
51
+ log10m += 1 ;
52
+ if let Some ( m_times_10) = m. checked_mul ( 10 ) {
53
+ m = m_times_10;
54
+ } else {
55
+ // m * 10 would overflow, so it must be bigger than n
56
+ // we break our invariant log10(m) == log10m
57
+ // it's okay because we won't use m anymore
58
+ break ;
59
+ }
60
+ }
61
+ // we now have 10**(log10m - 1) <= n < 10**log10m
62
+ log10m
63
+ }
64
+
65
+ #[ test]
66
+ fn test_count_digits ( ) {
67
+ assert_eq ! ( count_digits( 0 ) , 1 ) ;
68
+ assert_eq ! ( count_digits( 1 ) , 1 ) ;
69
+ assert_eq ! ( count_digits( 9 ) , 1 ) ;
70
+ assert_eq ! ( count_digits( 10 ) , 2 ) ;
71
+ assert_eq ! ( count_digits( 99 ) , 2 ) ;
72
+ assert_eq ! ( count_digits( 100 ) , 3 ) ;
73
+ assert_eq ! ( count_digits( 9999 ) , 4 ) ;
74
+ assert_eq ! ( count_digits( 65535 ) , 5 ) ;
75
+ }
76
+
40
77
/// Indicates a position within a URL based on its components.
41
78
///
42
79
/// A range of positions can be used for slicing `Url`:
@@ -152,8 +189,7 @@ impl Url {
152
189
Position :: AfterPort => {
153
190
if let Some ( port) = self . port {
154
191
debug_assert ! ( self . byte_at( self . host_end) == b':' ) ;
155
- let port_length = port. checked_ilog10 ( ) . unwrap_or ( 0 ) as usize + 1 ;
156
- self . host_end as usize + ":" . len ( ) + port_length
192
+ self . host_end as usize + ":" . len ( ) + count_digits ( port)
157
193
} else {
158
194
self . host_end as usize
159
195
}
0 commit comments