18
18
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
// THE SOFTWARE.
20
20
21
- //! Encoding and decoding Bech32 format
21
+ //! Encoding and decoding of the Bech32 format
22
22
//!
23
- //! Bech32 is a 5-bit (base-32) encoding scheme that produces strings that comprise
24
- //! a human-readable part, a separator, a data part, and a checksum. The encoding
25
- //! implements a BCH code that guarantees error detection of up to four characters
26
- //! with less than 1 in 1 billion chance of failing to detect more errors.
23
+ //! Bech32 is an encoding scheme that is easy to use for humans and efficient to encode in QR codes.
27
24
//!
28
- //! The Bech32 encoding was originally formulated in [BIP-0173](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki)
25
+ //! A Bech32 string consists of a human-readable part (HRP), a separator (the character `'1'`), and a data part.
26
+ //! A checksum at the end of the string provides error detection to prevent mistakes when the string is written off or read out loud.
27
+ //!
28
+ //! The original description in [BIP-0173](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki) has more details.
29
29
//!
30
30
//! # Examples
31
31
//!
32
- //! ```rust
32
+ //! ```
33
33
//! use bech32::{self, FromBase32, ToBase32};
34
34
//!
35
35
//! let encoded = bech32::encode("bech32", vec![0x00, 0x01, 0x02].to_base32()).unwrap();
44
44
// Allow trait objects without dyn on nightly and make 1.22 ignore the unknown lint
45
45
#![ allow( unknown_lints) ]
46
46
#![ allow( bare_trait_objects) ]
47
-
48
47
#![ deny( missing_docs) ]
49
48
#![ deny( non_upper_case_globals) ]
50
49
#![ deny( non_camel_case_types) ]
51
50
#![ deny( non_snake_case) ]
52
51
#![ deny( unused_mut) ]
53
52
#![ cfg_attr( feature = "strict" , deny( warnings) ) ]
54
53
55
- use std:: { error, fmt} ;
56
54
use std:: borrow:: Cow ;
55
+ use std:: { error, fmt} ;
57
56
58
57
// AsciiExt is needed for Rust 1.14 but not for newer versions
59
58
#[ allow( unused_imports, deprecated) ]
@@ -75,12 +74,12 @@ impl u5 {
75
74
}
76
75
77
76
/// Returns a copy of the underlying `u8` value
78
- pub fn to_u8 ( & self ) -> u8 {
77
+ pub fn to_u8 ( self ) -> u8 {
79
78
self . 0
80
79
}
81
80
82
81
/// Get char representing this 5 bit value as defined in BIP173
83
- pub fn to_char ( & self ) -> char {
82
+ pub fn to_char ( self ) -> char {
84
83
CHARSET [ self . to_u8 ( ) as usize ]
85
84
}
86
85
}
@@ -149,10 +148,11 @@ impl<'a> Bech32Writer<'a> {
149
148
150
149
fn polymod_step ( & mut self , v : u5 ) {
151
150
let b = ( self . chk >> 25 ) as u8 ;
152
- self . chk = ( self . chk & 0x1ffffff ) << 5 ^ ( u32:: from ( * v. as_ref ( ) ) ) ;
153
- for i in 0 ..5 {
151
+ self . chk = ( self . chk & 0x01ff_ffff ) << 5 ^ ( u32:: from ( * v. as_ref ( ) ) ) ;
152
+
153
+ for ( i, item) in GEN . iter ( ) . enumerate ( ) {
154
154
if ( b >> i) & 1 == 1 {
155
- self . chk ^= GEN [ i ]
155
+ self . chk ^= item ;
156
156
}
157
157
}
158
158
}
@@ -173,9 +173,8 @@ impl<'a> Bech32Writer<'a> {
173
173
let plm: u32 = self . chk ^ 1 ;
174
174
175
175
for p in 0 ..6 {
176
- self . formatter . write_char (
177
- u5 ( ( ( plm >> ( 5 * ( 5 - p) ) ) & 0x1f ) as u8 ) . to_char ( )
178
- ) ?;
176
+ self . formatter
177
+ . write_char ( u5 ( ( ( plm >> ( 5 * ( 5 - p) ) ) & 0x1f ) as u8 ) . to_char ( ) ) ?;
179
178
}
180
179
181
180
Ok ( ( ) )
@@ -193,7 +192,8 @@ impl<'a> WriteBase32 for Bech32Writer<'a> {
193
192
194
193
impl < ' a > Drop for Bech32Writer < ' a > {
195
194
fn drop ( & mut self ) {
196
- self . inner_finalize ( ) . expect ( "Unhandled error writing the checksum on drop." )
195
+ self . inner_finalize ( )
196
+ . expect ( "Unhandled error writing the checksum on drop." )
197
197
}
198
198
}
199
199
@@ -265,8 +265,8 @@ impl<T: AsRef<[u8]>> ToBase32 for T {
265
265
// buffer holds too many bits, so we don't have to combine buffer bits with new bits
266
266
// from this rounds byte.
267
267
if buffer_bits >= 5 {
268
- writer. write_u5 ( u5 ( ( buffer & 0b11111000 ) >> 3 ) ) ?;
269
- buffer = buffer << 5 ;
268
+ writer. write_u5 ( u5 ( ( buffer & 0b1111_1000 ) >> 3 ) ) ?;
269
+ buffer <<= 5 ;
270
270
buffer_bits -= 5 ;
271
271
}
272
272
@@ -277,13 +277,13 @@ impl<T: AsRef<[u8]>> ToBase32 for T {
277
277
278
278
writer. write_u5 ( u5 ( from_buffer | from_byte) ) ?;
279
279
buffer = b << ( 5 - buffer_bits) ;
280
- buffer_bits = 3 + buffer_bits ;
280
+ buffer_bits + = 3 ;
281
281
}
282
282
283
283
// There can be at most two u5s left in the buffer after processing all bytes, write them.
284
284
if buffer_bits >= 5 {
285
- writer. write_u5 ( u5 ( ( buffer & 0b11111000 ) >> 3 ) ) ?;
286
- buffer = buffer << 5 ;
285
+ writer. write_u5 ( u5 ( ( buffer & 0b1111_1000 ) >> 3 ) ) ?;
286
+ buffer <<= 5 ;
287
287
buffer_bits -= 5 ;
288
288
}
289
289
@@ -511,10 +511,11 @@ fn polymod(values: &[u5]) -> u32 {
511
511
let mut b: u8 ;
512
512
for v in values {
513
513
b = ( chk >> 25 ) as u8 ;
514
- chk = ( chk & 0x1ffffff ) << 5 ^ ( u32:: from ( * v. as_ref ( ) ) ) ;
515
- for i in 0 ..5 {
514
+ chk = ( chk & 0x01ff_ffff ) << 5 ^ ( u32:: from ( * v. as_ref ( ) ) ) ;
515
+
516
+ for ( i, item) in GEN . iter ( ) . enumerate ( ) {
516
517
if ( b >> i) & 1 == 1 {
517
- chk ^= GEN [ i ]
518
+ chk ^= item ;
518
519
}
519
520
}
520
521
}
@@ -526,26 +527,30 @@ const SEP: char = '1';
526
527
527
528
/// Encoding character set. Maps data value -> char
528
529
const CHARSET : [ char ; 32 ] = [
529
- 'q' , 'p' , 'z' , 'r' , 'y' , '9' , 'x' , '8' ,
530
- 'g' , 'f' , '2' , 't' , 'v' , 'd' , 'w' , '0' ,
531
- 's' , '3' , 'j' , 'n' , '5' , '4' , 'k' , 'h' ,
532
- 'c' , 'e' , '6' , 'm' , 'u' , 'a' , '7' , 'l'
530
+ 'q' , 'p' , 'z' , 'r' , 'y' , '9' , 'x' , '8' , // +0
531
+ 'g' , 'f' , '2' , 't' , 'v' , 'd' , 'w' , '0' , // +8
532
+ 's' , '3' , 'j' , 'n' , '5' , '4' , 'k' , 'h' , // +16
533
+ 'c' , 'e' , '6' , 'm' , 'u' , 'a' , '7' , 'l' , // +24
533
534
] ;
534
535
535
536
/// Reverse character set. Maps ASCII byte -> CHARSET index on [0,31]
536
537
const CHARSET_REV : [ i8 ; 128 ] = [
537
- -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
538
- -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
539
- -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
540
- 15 , -1 , 10 , 17 , 21 , 20 , 26 , 30 , 7 , 5 , -1 , -1 , -1 , -1 , -1 , -1 ,
541
- -1 , 29 , -1 , 24 , 13 , 25 , 9 , 8 , 23 , -1 , 18 , 22 , 31 , 27 , 19 , -1 ,
542
- 1 , 0 , 3 , 16 , 11 , 28 , 12 , 14 , 6 , 4 , 2 , -1 , -1 , -1 , -1 , -1 ,
543
- -1 , 29 , -1 , 24 , 13 , 25 , 9 , 8 , 23 , -1 , 18 , 22 , 31 , 27 , 19 , -1 ,
544
- 1 , 0 , 3 , 16 , 11 , 28 , 12 , 14 , 6 , 4 , 2 , -1 , -1 , -1 , -1 , -1
538
+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
539
+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
540
+ 15 , -1 , 10 , 17 , 21 , 20 , 26 , 30 , 7 , 5 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 29 , -1 , 24 , 13 , 25 , 9 , 8 , 23 ,
541
+ -1 , 18 , 22 , 31 , 27 , 19 , -1 , 1 , 0 , 3 , 16 , 11 , 28 , 12 , 14 , 6 , 4 , 2 , -1 , -1 , -1 , -1 , -1 , -1 , 29 ,
542
+ -1 , 24 , 13 , 25 , 9 , 8 , 23 , -1 , 18 , 22 , 31 , 27 , 19 , -1 , 1 , 0 , 3 , 16 , 11 , 28 , 12 , 14 , 6 , 4 , 2 , -1 ,
543
+ -1 , -1 , -1 , -1 ,
545
544
] ;
546
545
547
546
/// Generator coefficients
548
- const GEN : [ u32 ; 5 ] = [ 0x3b6a57b2 , 0x26508e6d , 0x1ea119fa , 0x3d4233dd , 0x2a1462b3 ] ;
547
+ const GEN : [ u32 ; 5 ] = [
548
+ 0x3b6a_57b2 ,
549
+ 0x2650_8e6d ,
550
+ 0x1ea1_19fa ,
551
+ 0x3d42_33dd ,
552
+ 0x2a14_62b3 ,
553
+ ] ;
549
554
550
555
/// Error types for Bech32 encoding / decoding
551
556
#[ derive( Copy , Clone , PartialEq , Debug ) ]
@@ -669,7 +674,11 @@ mod tests {
669
674
for s in strings {
670
675
let decode_result = decode ( s) ;
671
676
if !decode_result. is_ok ( ) {
672
- panic ! ( "Did not decode: {:?} Reason: {:?}" , s, decode_result. unwrap_err( ) ) ;
677
+ panic ! (
678
+ "Did not decode: {:?} Reason: {:?}" ,
679
+ s,
680
+ decode_result. unwrap_err( )
681
+ ) ;
673
682
}
674
683
assert ! ( decode_result. is_ok( ) ) ;
675
684
let decoded = decode_result. unwrap ( ) ;
@@ -707,7 +716,12 @@ mod tests {
707
716
println ! ( "{:?}" , dec_result. unwrap( ) ) ;
708
717
panic ! ( "Should be invalid: {:?}" , s) ;
709
718
}
710
- assert_eq ! ( dec_result. unwrap_err( ) , expected_error, "testing input '{}'" , s) ;
719
+ assert_eq ! (
720
+ dec_result. unwrap_err( ) ,
721
+ expected_error,
722
+ "testing input '{}'" ,
723
+ s
724
+ ) ;
711
725
}
712
726
}
713
727
@@ -720,7 +734,13 @@ mod tests {
720
734
( vec![ 0x01 ] , 8 , 8 , true , vec![ 0x01 ] ) ,
721
735
( vec![ 0x01 ] , 8 , 4 , true , vec![ 0x00 , 0x01 ] ) ,
722
736
( vec![ 0x01 ] , 8 , 2 , true , vec![ 0x00 , 0x00 , 0x00 , 0x01 ] ) ,
723
- ( vec![ 0x01 ] , 8 , 1 , true , vec![ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 ] ) ,
737
+ (
738
+ vec![ 0x01 ] ,
739
+ 8 ,
740
+ 1 ,
741
+ true ,
742
+ vec![ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 ] ,
743
+ ) ,
724
744
( vec![ 0xff ] , 8 , 5 , true , vec![ 0x1f , 0x1c ] ) ,
725
745
( vec![ 0x1f , 0x1c ] , 5 , 8 , false , vec![ 0xff ] ) ,
726
746
] ;
@@ -770,7 +790,10 @@ mod tests {
770
790
assert ! ( [ 0u8 , 1 , 2 , 30 , 31 , 255 ] . check_base32( ) . is_err( ) ) ;
771
791
772
792
assert ! ( [ 1u8 , 2 , 3 , 4 ] . check_base32( ) . is_ok( ) ) ;
773
- assert_eq ! ( [ 30u8 , 31 , 35 , 20 ] . check_base32( ) , Err ( Error :: InvalidData ( 35 ) ) ) ;
793
+ assert_eq ! (
794
+ [ 30u8 , 31 , 35 , 20 ] . check_base32( ) ,
795
+ Err ( Error :: InvalidData ( 35 ) )
796
+ ) ;
774
797
}
775
798
776
799
#[ test]
@@ -784,7 +807,10 @@ mod tests {
784
807
#[ test]
785
808
fn from_base32 ( ) {
786
809
use FromBase32 ;
787
- assert_eq ! ( Vec :: from_base32( & [ 0x1f , 0x1c ] . check_base32( ) . unwrap( ) ) , Ok ( vec![ 0xff ] ) ) ;
810
+ assert_eq ! (
811
+ Vec :: from_base32( & [ 0x1f , 0x1c ] . check_base32( ) . unwrap( ) ) ,
812
+ Ok ( vec![ 0xff ] )
813
+ ) ;
788
814
assert_eq ! (
789
815
Vec :: from_base32( & [ 0x1f , 0x1f ] . check_base32( ) . unwrap( ) ) ,
790
816
Err ( Error :: InvalidPadding )
0 commit comments