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