/*Package base36 provides a reasonably fast implementation of a binary base36 codec.*/
package base36// Simplified code based on https://godoc.org/github.com/mr-tron/base58// which in turn is based on https://github.com/trezor/trezor-crypto/commit/89a7d7797b806facimport ()constUcAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"constLcAlphabet = "0123456789abcdefghijklmnopqrstuvwxyz"const maxDigitOrdinal = 'z'const maxDigitValueB36 = 35var revAlphabet [maxDigitOrdinal + 1]bytefunc init() {for := rangerevAlphabet {revAlphabet[] = maxDigitValueB36 + 1 }for , := rangeUcAlphabet {revAlphabet[byte()] = byte()if > '9' {revAlphabet[byte()+32] = byte() } }}// EncodeToStringUc encodes the given byte-buffer as base36 using [0-9A-Z] as// the digit-alphabetfunc ( []byte) string { returnencode(, UcAlphabet) }// EncodeToStringLc encodes the given byte-buffer as base36 using [0-9a-z] as// the digit-alphabetfunc ( []byte) string { returnencode(, LcAlphabet) }func encode( []byte, string) string { := len() := 0for < && [] == 0 { ++ }// It is crucial to make this as short as possible, especially for // the usual case of CIDs. = +// This is an integer simplification of // ceil(log(256)/log(36)) (-)*277/179 + 1// Note: pools *DO NOT* help, the overhead of zeroing // kills any performance gain to be had := make([]byte, )var , intvaruint32 = - 1for , := range [:] { = - 1for = uint32(); > || != 0; -- { += uint32(([])) * 256 [] = byte( % 36) /= 36 } = }// Determine the additional "zero-gap" in the buffer (aside from zcnt)for = ; < && [] == 0; ++ { }// Now encode the values with actual alphabet in-place := [-:] = len()for = 0; < ; ++ { [] = [[]] }returnstring([:])}// DecodeString takes a base36 encoded string and returns a slice of the decoded// bytes.func ( string) ([]byte, error) {iflen() == 0 {returnnil, fmt.Errorf("can not decode zero-length string") } := 0for < len() && [] == '0' { ++ }// the 32bit algo stretches the result up to 2 times := make([]byte, 2*(((len())*179/277)+1)) // no more than 84 bytes when len(s) <= 64 := make([]uint32, (len()+3)/4) // no more than 16 bytes when len(s) <= 64for , := range {if > maxDigitOrdinal || revAlphabet[] > maxDigitValueB36 {returnnil, fmt.Errorf("invalid base36 character (%q)", ) } := uint64(revAlphabet[])for := len() - 1; >= 0; -- { := uint64([])*36 + = ( >> 32) [] = uint32( & 0xFFFFFFFF) } } := (uint(len()%4) * 8)if == 0 { = 32 } -= 8 := 0for := 0; < len(); ++ {for < 32 { // loop relies on uint overflow [] = byte([] >> ) -= 8 ++ } = 24 }// find the most significant byte post-decode, if anyfor := ; < ; ++ {if [] > 0 {return [- : : ], nil } }// it's all zeroesreturn [::], nil}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.