@@ -22,7 +22,10 @@ pub fn Bool::to_string(self : Bool) -> String {
22
22
}
23
23
24
24
///|
25
- pub fn Int64 ::to_string (self : Int64 ) -> String {
25
+ const ALPHABET : String = "0123456789abcdefghijklmnopqrstuvwxyz"
26
+
27
+ ///|
28
+ pub fn Int64 ::to_string (self : Int64 , radix ~ : Int = 10 ) -> String {
26
29
fn abs (n : Int64 ) -> Int64 {
27
30
if n < 0L {
28
31
0L - n
@@ -31,27 +34,36 @@ pub fn Int64::to_string(self : Int64) -> String {
31
34
}
32
35
}
33
36
34
- // The min and max value of i64 are -9223372036854775808 and 9223372036854775807,
35
- // so max=20 is enough.
36
-
37
- let buf = StringBuilder ::new (size_hint = 20 )
37
+ let size_hint = match radix {
38
+ 2 ..< 7 => 70 // max length is 64, 70 is enough
39
+ 8 ..< 15 => 30 // max length is 23, 30 is enough
40
+ 16 ..= 36 => 20 // max length is 17, 20 is enough
41
+ _ => abort ("radix must be between 2 and 36" )
42
+ }
43
+ let buf = StringBuilder ::new (size_hint ~)
38
44
if self < 0L {
39
45
buf .write_char ('-' )
40
46
}
41
- fn write_digits (num ) {
42
- let num2 = num / 10L
47
+ let radix : Int64 = radix .to_int64 ()
48
+ fn write_digits (num : Int64 ) {
49
+ let num2 = num / radix
43
50
if num2 != 0L {
44
51
write_digits (num2 )
45
52
}
46
- buf .write_char (Char :: from_int ( abs (num % 10L ).to_int () + 48 ) )
53
+ buf .write_char (ALPHABET [ abs (num % radix ).to_int ()] )
47
54
}
48
55
49
- write_digits (self )
56
+ write_digits (abs ( self ) )
50
57
buf .to_string ()
51
58
}
52
59
53
60
///|
54
- pub fn Int ::to_string (self : Int ) -> String {
61
+ pub impl Show for Int64 with to_string (self ) {
62
+ self .to_string (radix = 10 )
63
+ }
64
+
65
+ ///|
66
+ pub fn Int ::to_string (self : Int , radix ~ : Int = 10 ) -> String {
55
67
fn abs (n : Int ) -> Int {
56
68
if n < 0 {
57
69
0 - n
@@ -60,40 +72,60 @@ pub fn Int::to_string(self : Int) -> String {
60
72
}
61
73
}
62
74
63
- // The min and max value of i32 are -2147483648 and 2147483647,
64
- // so max=11 is enough.
65
-
66
- let buf = StringBuilder ::new ()
75
+ let size_hint = match radix {
76
+ 2 ..< 7 => 36 // max length is 32, 36 is enough
77
+ 8 ..< 15 => 18 // max length is 12, 18 is enough
78
+ 16 ..= 36 => 10 // max length is 8, 10 is enough
79
+ _ => abort ("radix must be between 2 and 36" )
80
+ }
81
+ let buf = StringBuilder ::new (size_hint ~)
67
82
if self < 0 {
68
83
buf .write_char ('-' )
69
84
}
70
- fn write_digits (num ) {
71
- let num2 = num / 10
85
+ fn write_digits (num : Int ) {
86
+ let num2 = num / radix
72
87
if num2 != 0 {
73
88
write_digits (num2 )
74
89
}
75
- buf .write_char (Char :: from_int ( abs (num % 10 ) + 48 ) )
90
+ buf .write_char (ALPHABET [ abs (num % radix )] )
76
91
}
77
92
78
- write_digits (self )
93
+ write_digits (abs ( self ) )
79
94
buf .to_string ()
80
95
}
81
96
82
97
///|
83
- pub fn UInt ::to_string (self : UInt ) -> String {
84
- let buf = StringBuilder ::new ()
85
- fn write_digits (num ) {
86
- let num2 = num / 10U
98
+ pub impl Show for Int with to_string (self ) {
99
+ self .to_string (radix = 10 )
100
+ }
101
+
102
+ ///|
103
+ pub fn UInt ::to_string (self : UInt , radix ~ : Int = 10 ) -> String {
104
+ let size_hint = match radix {
105
+ 2 ..< 7 => 36 // max length is 32, 36 is enough
106
+ 8 ..< 15 => 18 // max length is 11, 18 is enough
107
+ 16 ..= 36 => 10 // max length is 8, 10 is enough
108
+ _ => abort ("radix must be between 2 and 36" )
109
+ }
110
+ let buf = StringBuilder ::new (size_hint ~)
111
+ let radix : UInt = radix .reinterpret_as_uint ()
112
+ fn write_digits (num : UInt ) {
113
+ let num2 = num / radix
87
114
if num2 != 0U {
88
115
write_digits (num2 )
89
116
}
90
- buf .write_char (Char :: from_int (( num % 10U ).reinterpret_as_int () + 48 ) )
117
+ buf .write_char (ALPHABET [( num % radix ).reinterpret_as_int ()] )
91
118
}
92
119
93
120
write_digits (self )
94
121
buf .to_string ()
95
122
}
96
123
124
+ ///|
125
+ pub impl Show for UInt with to_string (self ) {
126
+ self .to_string (radix = 10 )
127
+ }
128
+
97
129
///|
98
130
test "UInt::to_string" {
99
131
inspect! (0U , content = "0" )
@@ -102,28 +134,144 @@ test "UInt::to_string" {
102
134
}
103
135
104
136
///|
105
- pub fn UInt64 ::to_string (self : UInt64 ) -> String {
106
- let buf = StringBuilder ::new ()
137
+ pub fn UInt64 ::to_string (self : UInt64 , radix ~ : Int = 10 ) -> String {
138
+ let size_hint = match radix {
139
+ 2 ..< 7 => 70 // max length is 64, 70 is enough
140
+ 8 ..< 15 => 30 // max length is 23, 30 is enough
141
+ 16 ..= 36 => 20 // max length is 17, 20 is enough
142
+ _ => abort ("radix must be between 2 and 36" )
143
+ }
144
+ let buf = StringBuilder ::new (size_hint ~)
145
+ let radix : UInt64 = radix .to_uint64 ()
107
146
fn write_digits (num : UInt64 ) {
108
- let num2 = num / 10UL
147
+ let num2 = num / radix
109
148
if num2 != 0UL {
110
149
write_digits (num2 )
111
150
}
112
- buf .write_char (
113
- Char ::from_int ((num % 10UL ).reinterpret_as_int64 ().to_int () + 48 ),
114
- )
151
+ buf .write_char (ALPHABET [(num % radix ).to_int ()])
115
152
}
116
153
117
154
write_digits (self )
118
155
buf .to_string ()
119
156
}
120
157
121
158
///|
122
- pub fn Int16 ::to_string (self : Int16 ) -> String {
123
- self .to_int ().to_string ()
159
+ pub impl Show for UInt64 with to_string (self ) {
160
+ self .to_string (radix = 10 )
161
+ }
162
+
163
+ ///|
164
+ pub fn Int16 ::to_string (self : Int16 , radix ~ : Int = 10 ) -> String {
165
+ self .to_int ().to_string (radix ~)
166
+ }
167
+
168
+ ///|
169
+ pub impl Show for Int16 with to_string (self ) {
170
+ self .to_string (radix = 10 )
171
+ }
172
+
173
+ ///|
174
+ pub fn UInt16 ::to_string (self : UInt16 , radix ~ : Int = 10 ) -> String {
175
+ self .to_int ().to_string (radix ~)
176
+ }
177
+
178
+ ///|
179
+ pub impl Show for UInt16 with to_string (self ) {
180
+ self .to_string (radix = 10 )
181
+ }
182
+
183
+ ///|
184
+ test "to_string" {
185
+ assert_eq! ((0x100 ).to_string (), "256" )
186
+ assert_eq! ("\{ 0x100 } " , "256" )
187
+ assert_eq! (0x200U .to_string (), "512" )
188
+ assert_eq! ("\{ 0x200U } " , "512" )
189
+ assert_eq! (0x300L .to_string (), "768" )
190
+ assert_eq! ("\{ 0x300L } " , "768" )
191
+ assert_eq! (0x400UL .to_string (), "1024" )
192
+ assert_eq! ("\{ 0x400UL } " , "1024" )
193
+ }
194
+
195
+ ///|
196
+ test "to_string with radix" {
197
+ // Binary
198
+ inspect! ((0 ).to_string (radix = 2 ), content = "0" )
199
+ inspect! ((1 ).to_string (radix = 2 ), content = "1" )
200
+ inspect! ((2 ).to_string (radix = 2 ), content = "10" )
201
+ inspect! ((255 ).to_string (radix = 2 ), content = "11111111" )
202
+ inspect! ((- 255 ).to_string (radix = 2 ), content = "-11111111" )
203
+
204
+ // Octal
205
+ inspect! ((0 ).to_string (radix = 8 ), content = "0" )
206
+ inspect! ((8 ).to_string (radix = 8 ), content = "10" )
207
+ inspect! ((64 ).to_string (radix = 8 ), content = "100" )
208
+ inspect! ((- 64 ).to_string (radix = 8 ), content = "-100" )
209
+
210
+ // Decimal
211
+ inspect! ((0 ).to_string (radix = 10 ), content = "0" )
212
+ inspect! ((123 ).to_string (radix = 10 ), content = "123" )
213
+ inspect! ((- 123 ).to_string (radix = 10 ), content = "-123" )
214
+ inspect! (
215
+ 0x7fff_ffff_ffff_ffffL .to_string (radix = 10 ),
216
+ content = "9223372036854775807" ,
217
+ )
218
+ inspect! (
219
+ 0x8000_0000_0000_0000L .to_string (radix = 10 ),
220
+ content = "-9223372036854775808" ,
221
+ )
222
+
223
+ // Hexadecimal
224
+ inspect! ((0 ).to_string (radix = 16 ), content = "0" )
225
+ inspect! ((0x11 ).to_string (radix = 16 ), content = "11" )
226
+ inspect! ((0x15ef ).to_string (radix = 16 ), content = "15ef" )
227
+ inspect! ((- 0xabcd ).to_string (radix = 16 ), content = "-abcd" )
228
+ inspect! (
229
+ (1.0 : Float ).reinterpret_as_int ().to_string (radix = 16 ),
230
+ content = "3f800000" ,
231
+ )
232
+
233
+ // UInt
234
+ inspect! (0U .to_string (radix = 16 ), content = "0" )
235
+ inspect! (0x1AU .to_string (radix = 16 ), content = "1a" )
236
+ inspect! (0xabcdU .to_string (radix = 16 ), content = "abcd" )
237
+ inspect! (
238
+ (- 2.0 : Float ).reinterpret_as_uint ().to_string (radix = 16 ),
239
+ content = "c0000000" ,
240
+ )
241
+ inspect! ((- 1 ).reinterpret_as_uint ().to_string (radix = 16 ), content = "ffffffff" )
242
+
243
+ // Int64
244
+ inspect! (0L .to_string (radix = 16 ), content = "0" )
245
+ inspect! (0x2fL .to_string (radix = 16 ), content = "2f" )
246
+ inspect! (0xf0aeL .to_string (radix = 16 ), content = "f0ae" )
247
+ inspect! ((- 0x1234eacbL ).to_string (radix = 16 ), content = "-1234eacb" )
248
+ inspect! (
249
+ 1.0 .reinterpret_as_uint64 ().to_string (radix = 16 ),
250
+ content = "3ff0000000000000" ,
251
+ )
252
+
253
+ // UInt64
254
+ inspect! (0UL .to_string (radix = 16 ), content = "0" )
255
+ inspect! (0x11UL .to_string (radix = 16 ), content = "11" )
256
+ inspect! (0x12bdUL .to_string (radix = 16 ), content = "12bd" )
257
+ inspect! (
258
+ (- 1L ).reinterpret_as_uint64 ().to_string (radix = 16 ),
259
+ content = "ffffffffffffffff" ,
260
+ )
261
+ inspect! (
262
+ 2.0 .reinterpret_as_uint64 ().to_string (radix = 16 ),
263
+ content = "4000000000000000" ,
264
+ )
124
265
}
125
266
126
267
///|
127
- pub fn UInt16 ::to_string (self : UInt16 ) -> String {
128
- self .to_int ().to_string ()
268
+ test "panic to_string_by_radix/illegal_radix" {
269
+ ignore ((1 ).to_string (radix = 1 ))
270
+ ignore ((1 ).to_string (radix = 37 ))
271
+ ignore (1L .to_string (radix = 0 ))
272
+ ignore (1L .to_string (radix = 42 ))
273
+ ignore (1U .to_string (radix = - 1 ))
274
+ ignore (1U .to_string (radix = 73 ))
275
+ ignore (1UL .to_string (radix = - 100 ))
276
+ ignore (1UL .to_string (radix = 100 ))
129
277
}
0 commit comments