@@ -105,6 +105,7 @@ pub enum Format {
105
105
Base2Lsbf ,
106
106
Base2Msbf ,
107
107
Z85 ,
108
+ Base58 ,
108
109
}
109
110
110
111
pub const BASE2LSBF : Encoding = new_encoding ! {
@@ -119,6 +120,8 @@ pub const BASE2MSBF: Encoding = new_encoding! {
119
120
120
121
pub struct Z85Wrapper { }
121
122
123
+ pub struct Base58Wrapper { }
124
+
122
125
pub struct EncodingWrapper {
123
126
pub alphabet : & ' static [ u8 ] ,
124
127
pub encoding : Encoding ,
@@ -181,6 +184,140 @@ pub trait SupportsFastDecodeAndEncode {
181
184
fn valid_decoding_multiple ( & self ) -> usize ;
182
185
}
183
186
187
+ impl SupportsFastDecodeAndEncode for Base58Wrapper {
188
+ fn alphabet ( & self ) -> & ' static [ u8 ] {
189
+ // Base58 alphabet
190
+ b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
191
+ }
192
+
193
+ fn decode_into_vec ( & self , input : & [ u8 ] , output : & mut Vec < u8 > ) -> UResult < ( ) > {
194
+ if input. is_empty ( ) {
195
+ return Ok ( ( ) ) ;
196
+ }
197
+
198
+ // Count leading zeros (will become leading 1s in base58)
199
+ let leading_ones = input. iter ( ) . take_while ( |& & b| b == b'1' ) . count ( ) ;
200
+
201
+ // Skip leading 1s for conversion
202
+ let input_trimmed = & input[ leading_ones..] ;
203
+ if input_trimmed. is_empty ( ) {
204
+ output. resize ( output. len ( ) + leading_ones, 0 ) ;
205
+ return Ok ( ( ) ) ;
206
+ }
207
+
208
+ // Convert base58 to big integer
209
+ let mut num: Vec < u32 > = vec ! [ 0 ] ;
210
+ let alphabet = self . alphabet ( ) ;
211
+
212
+ for & byte in input_trimmed {
213
+ // Find position in alphabet
214
+ let digit = alphabet. iter ( ) . position ( |& b| b == byte)
215
+ . ok_or_else ( || USimpleError :: new ( 1 , "error: invalid input" . to_owned ( ) ) ) ?;
216
+
217
+ // Multiply by 58 and add digit
218
+ let mut carry = digit as u32 ;
219
+ for n in num. iter_mut ( ) {
220
+ let tmp = ( * n as u64 ) * 58 + carry as u64 ;
221
+ * n = tmp as u32 ;
222
+ carry = ( tmp >> 32 ) as u32 ;
223
+ }
224
+ if carry > 0 {
225
+ num. push ( carry) ;
226
+ }
227
+ }
228
+
229
+ // Convert to bytes (little endian, then reverse)
230
+ let mut result = Vec :: new ( ) ;
231
+ for & n in num. iter ( ) {
232
+ result. extend_from_slice ( & n. to_le_bytes ( ) ) ;
233
+ }
234
+
235
+ // Remove trailing zeros and reverse to get big endian
236
+ while result. last ( ) == Some ( & 0 ) && result. len ( ) > 1 {
237
+ result. pop ( ) ;
238
+ }
239
+ result. reverse ( ) ;
240
+
241
+ // Add leading zeros for leading 1s in input
242
+ let mut final_result = vec ! [ 0 ; leading_ones] ;
243
+ final_result. extend_from_slice ( & result) ;
244
+
245
+ output. extend_from_slice ( & final_result) ;
246
+ Ok ( ( ) )
247
+ }
248
+
249
+ fn encode_to_vec_deque ( & self , input : & [ u8 ] , output : & mut VecDeque < u8 > ) -> UResult < ( ) > {
250
+ if input. is_empty ( ) {
251
+ return Ok ( ( ) ) ;
252
+ }
253
+
254
+ // Count leading zeros
255
+ let leading_zeros = input. iter ( ) . take_while ( |& & b| b == 0 ) . count ( ) ;
256
+
257
+ // Skip leading zeros
258
+ let input_trimmed = & input[ leading_zeros..] ;
259
+ if input_trimmed. is_empty ( ) {
260
+ for _ in 0 ..leading_zeros {
261
+ output. push_back ( b'1' ) ;
262
+ }
263
+ return Ok ( ( ) ) ;
264
+ }
265
+
266
+ // Convert bytes to big integer
267
+ let mut num: Vec < u32 > = Vec :: new ( ) ;
268
+ for & byte in input_trimmed {
269
+ let mut carry = byte as u32 ;
270
+ for n in num. iter_mut ( ) {
271
+ let tmp = ( * n as u64 ) * 256 + carry as u64 ;
272
+ * n = tmp as u32 ;
273
+ carry = ( tmp >> 32 ) as u32 ;
274
+ }
275
+ if carry > 0 {
276
+ num. push ( carry) ;
277
+ }
278
+ }
279
+
280
+ // Convert to base58
281
+ let mut result = Vec :: new ( ) ;
282
+ let alphabet = self . alphabet ( ) ;
283
+
284
+ while !num. is_empty ( ) && num. iter ( ) . any ( |& n| n != 0 ) {
285
+ let mut carry = 0u64 ;
286
+ for n in num. iter_mut ( ) . rev ( ) {
287
+ let tmp = carry * ( 1u64 << 32 ) + * n as u64 ;
288
+ * n = ( tmp / 58 ) as u32 ;
289
+ carry = tmp % 58 ;
290
+ }
291
+ result. push ( alphabet[ carry as usize ] ) ;
292
+
293
+ // Remove leading zeros
294
+ while num. last ( ) == Some ( & 0 ) && num. len ( ) > 1 {
295
+ num. pop ( ) ;
296
+ }
297
+ }
298
+
299
+ // Add leading 1s for leading zeros in input
300
+ for _ in 0 ..leading_zeros {
301
+ output. push_back ( b'1' ) ;
302
+ }
303
+
304
+ // Add result (reversed because we built it backwards)
305
+ for byte in result. into_iter ( ) . rev ( ) {
306
+ output. push_back ( byte) ;
307
+ }
308
+
309
+ Ok ( ( ) )
310
+ }
311
+
312
+ fn unpadded_multiple ( & self ) -> usize {
313
+ 1 // Base58 doesn't use padding
314
+ }
315
+
316
+ fn valid_decoding_multiple ( & self ) -> usize {
317
+ 1 // Any length is valid for Base58
318
+ }
319
+ }
320
+
184
321
impl SupportsFastDecodeAndEncode for Z85Wrapper {
185
322
fn alphabet ( & self ) -> & ' static [ u8 ] {
186
323
// Z85 alphabet
0 commit comments