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