Skip to content

Instantly share code, notes, and snippets.

@shawnsmithdev
Last active July 16, 2020 03:26
Show Gist options
  • Save shawnsmithdev/ca5fa2f3d54d5611de5e5352a950b8b1 to your computer and use it in GitHub Desktop.
Save shawnsmithdev/ca5fa2f3d54d5611de5e5352a950b8b1 to your computer and use it in GitHub Desktop.
Base85 encoding
package main
import (
"encoding/binary"
"fmt"
)
var (
bases = []uint32{1, 85, 85 * 85, 85 * 85 * 85, 85 * 85 * 85 * 85}
)
func toBase85(data []byte) string {
result := ""
// four bytes at a time
enc := make([]rune, 5)
for i := 0; i*4 < len(data); i++ {
start := i * 4
end := (i + 1) * 4
if end > len(data) {
end = len(data)
}
buff := make([]byte, 4)
copy(buff, data[start:end])
// read as a number
val := binary.LittleEndian.Uint32(buff)
delta := val
fmt.Printf("Read bytes [%v, %v) as 0x%x (%v)\n", start, end, buff, val)
// convert to base 85
for j := 4; j >= 0; j-- {
placeBase := bases[j]
placeVal := delta / placeBase
placeTotal := placeVal * placeBase
delta = delta - placeTotal
encVal := '!' + placeVal
r := rune(encVal)
fmt.Printf("At place 85^%v value was %v (%v, %s), %v remains\n",
j, placeVal, placeTotal, string(r), delta)
enc[j] = r
}
fmt.Printf("Encoded 0x%x (%v) to base85 as: %v\n", buff, val, string(enc))
result += string(enc)
fmt.Println()
}
return result
}
func main() {
for i := uint32(0); i < 85; i++ {
fmt.Printf("%v -> %s\n", i, string('!'+i))
}
fmt.Println()
fmt.Println("\"Hello, world!\" in Base85:", toBase85([]byte("Hello, world!")))
}
// 0 -> !
// 1 -> "
// 2 -> #
// 3 -> $
// 4 -> %
// 5 -> &
// 6 -> '
// 7 -> (
// 8 -> )
// 9 -> *
// 10 -> +
// 11 -> ,
// 12 -> -
// 13 -> .
// 14 -> /
// 15 -> 0
// 16 -> 1
// 17 -> 2
// 18 -> 3
// 19 -> 4
// 20 -> 5
// 21 -> 6
// 22 -> 7
// 23 -> 8
// 24 -> 9
// 25 -> :
// 26 -> ;
// 27 -> <
// 28 -> =
// 29 -> >
// 30 -> ?
// 31 -> @
// 32 -> A
// 33 -> B
// 34 -> C
// 35 -> D
// 36 -> E
// 37 -> F
// 38 -> G
// 39 -> H
// 40 -> I
// 41 -> J
// 42 -> K
// 43 -> L
// 44 -> M
// 45 -> N
// 46 -> O
// 47 -> P
// 48 -> Q
// 49 -> R
// 50 -> S
// 51 -> T
// 52 -> U
// 53 -> V
// 54 -> W
// 55 -> X
// 56 -> Y
// 57 -> Z
// 58 -> [
// 59 -> \
// 60 -> ]
// 61 -> ^
// 62 -> _
// 63 -> `
// 64 -> a
// 65 -> b
// 66 -> c
// 67 -> d
// 68 -> e
// 69 -> f
// 70 -> g
// 71 -> h
// 72 -> i
// 73 -> j
// 74 -> k
// 75 -> l
// 76 -> m
// 77 -> n
// 78 -> o
// 79 -> p
// 80 -> q
// 81 -> r
// 82 -> s
// 83 -> t
// 84 -> u
//
// Read bytes [0, 4) as 0x48656c6c (1819043144)
// At place 85^4 value was 34 (1774821250, C), 44221894 remains
// At place 85^3 value was 72 (44217000, i), 4894 remains
// At place 85^2 value was 0 (0, !), 4894 remains
// At place 85^1 value was 57 (4845, Z), 49 remains
// At place 85^0 value was 49 (49, R), 0 remains
// Encoded 0x48656c6c (1819043144) to base85 as: RZ!iC
//
// Read bytes [4, 8) as 0x6f2c2077 (1998597231)
// At place 85^4 value was 38 (1983623750, G), 14973481 remains
// At place 85^3 value was 24 (14739000, 9), 234481 remains
// At place 85^2 value was 32 (231200, A), 3281 remains
// At place 85^1 value was 38 (3230, G), 51 remains
// At place 85^0 value was 51 (51, T), 0 remains
// Encoded 0x6f2c2077 (1998597231) to base85 as: TGA9G
//
// Read bytes [8, 12) as 0x6f726c64 (1684828783)
// At place 85^4 value was 32 (1670420000, A), 14408783 remains
// At place 85^3 value was 23 (14124875, 8), 283908 remains
// At place 85^2 value was 39 (281775, H), 2133 remains
// At place 85^1 value was 25 (2125, :), 8 remains
// At place 85^0 value was 8 (8, )), 0 remains
// Encoded 0x6f726c64 (1684828783) to base85 as: ):H8A
//
// Read bytes [12, 13) as 0x21000000 (33)
// At place 85^4 value was 0 (0, !), 33 remains
// At place 85^3 value was 0 (0, !), 33 remains
// At place 85^2 value was 0 (0, !), 33 remains
// At place 85^1 value was 0 (0, !), 33 remains
// At place 85^0 value was 33 (33, B), 0 remains
// Encoded 0x21000000 (33) to base85 as: B!!!!
//
// "Hello, world!" in Base85: RZ!iCTGA9G):H8AB!!!!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment