encoding.go (2277B)
1 package main 2 3 import ( 4 "errors" 5 "math" 6 "strings" 7 ) 8 9 func talerBinaryEncode(byts []byte) string { 10 11 return encodeCrock(byts) 12 } 13 14 func talerBinaryDecode(str string) ([]byte, error) { 15 16 return decodeCrock(str) 17 } 18 19 func ParseWopid(wopid string) ([]byte, error) { 20 21 wopidBytes, err := talerBinaryDecode(wopid) 22 if err != nil { 23 return nil, err 24 } 25 26 if len(wopidBytes) != 32 { 27 err = errors.New("invalid wopid") 28 return nil, err 29 } 30 31 return wopidBytes, nil 32 } 33 34 func FormatWopid(wopid []byte) string { 35 36 return talerBinaryEncode(wopid) 37 } 38 39 func decodeCrock(e string) ([]byte, error) { 40 size := len(e) 41 bitpos := 0 42 bitbuf := 0 43 readPosition := 0 44 outLen := int(math.Floor((float64(size) * 5.0) / 8.0)) 45 out := make([]byte, outLen) 46 outPos := 0 47 48 getValue := func(c byte) (int, error) { 49 alphabet := "0123456789ABCDEFGHJKMNPQRSTVWXYZ" 50 switch c { 51 case 'o', 'O': 52 return 0, nil 53 case 'i', 'I', 'l', 'L': 54 return 1, nil 55 case 'u', 'U': 56 return 27, nil 57 } 58 59 i := strings.IndexRune(alphabet, rune(c)) 60 if i > -1 && i < 32 { 61 return i, nil 62 } 63 64 return -1, errors.New("encoding error") 65 } 66 67 for readPosition < size || bitpos > 0 { 68 if readPosition < size { 69 v, err := getValue(e[readPosition]) 70 if err != nil { 71 return nil, err 72 } 73 readPosition++ 74 bitbuf = bitbuf<<5 | v 75 bitpos += 5 76 } 77 for bitpos >= 8 { 78 d := byte(bitbuf >> (bitpos - 8) & 0xff) 79 out[outPos] = d 80 outPos++ 81 bitpos -= 8 82 } 83 if readPosition == size && bitpos > 0 { 84 bitbuf = bitbuf << (8 - bitpos) & 0xff 85 if bitbuf == 0 { 86 bitpos = 0 87 } else { 88 bitpos = 8 89 } 90 } 91 } 92 return out, nil 93 } 94 95 func encodeCrock(data []byte) string { 96 out := "" 97 bitbuf := 0 98 bitpos := 0 99 100 encodeValue := func(value int) byte { 101 alphabet := "ABCDEFGHJKMNPQRSTVWXYZ" 102 switch { 103 case value >= 0 && value <= 9: 104 return byte('0' + value) 105 case value >= 10 && value <= 31: 106 return alphabet[value-10] 107 default: 108 panic("Invalid value for encoding") 109 } 110 } 111 112 for _, b := range data { 113 bitbuf = bitbuf<<8 | int(b&0xff) 114 bitpos += 8 115 for bitpos >= 5 { 116 value := bitbuf >> (bitpos - 5) & 0x1f 117 out += string(encodeValue(value)) 118 bitpos -= 5 119 } 120 } 121 if bitpos > 0 { 122 bitbuf = bitbuf << (5 - bitpos) 123 value := bitbuf & 0x1f 124 out += string(encodeValue(value)) 125 } 126 return out 127 }