base83.go (1571B)
1 package base83 2 3 import ( 4 "fmt" 5 "math" 6 "strings" 7 ) 8 9 const characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~" 10 11 // An InvalidCharacterError occurs when a characters is found which is not part of the Base83 character set. 12 type InvalidCharacterError rune 13 14 func (e InvalidCharacterError) Error() string { 15 return fmt.Sprintf("base83: invalid string (character %q out of range)", rune(e)) 16 } 17 18 // An InvalidLengthError occurs when a given value cannot be encoded to a string of given length. 19 type InvalidLengthError int 20 21 func (e InvalidLengthError) Error() string { 22 return fmt.Sprintf("base83: invalid length (%d)", int(e)) 23 } 24 25 // Encode will encode the given integer value to a Base83 string with given length. 26 // If length is too short to encode the given value InvalidLengthError will be returned. 27 func Encode(value, length int) (string, error) { 28 divisor := int(math.Pow(83, float64(length))) 29 if value/divisor != 0 { 30 return "", InvalidLengthError(length) 31 } 32 divisor /= 83 33 34 var str strings.Builder 35 str.Grow(length) 36 for i := 0; i < length; i++ { 37 if divisor <= 0 { 38 return "", InvalidLengthError(length) 39 } 40 digit := (value / divisor) % 83 41 divisor /= 83 42 str.WriteRune(rune(characters[digit])) 43 } 44 45 return str.String(), nil 46 } 47 48 // Decode will decode the given Base83 string to an integer. 49 func Decode(str string) (value int, err error) { 50 for _, r := range str { 51 idx := strings.IndexRune(characters, r) 52 if idx == -1 { 53 return 0, InvalidCharacterError(r) 54 } 55 value = value*83 + idx 56 } 57 return value, nil 58 }