|
|
|
@ -6,29 +6,51 @@ import ( |
|
|
|
|
"math" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
func EncodeSlice(slice []interface{}) []byte { |
|
|
|
|
var buff bytes.Buffer |
|
|
|
|
func BinaryLength(n uint64) uint64 { |
|
|
|
|
if n == 0 { return 0 } |
|
|
|
|
|
|
|
|
|
for _, val := range slice { |
|
|
|
|
switch t := val.(type) { |
|
|
|
|
case []interface{}, []string: |
|
|
|
|
buff.Write(Encode(t)) |
|
|
|
|
} |
|
|
|
|
return 1 + BinaryLength(n / 256) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func ToBinarySlice(n uint64, length uint64) []uint64 { |
|
|
|
|
if length == 0 { |
|
|
|
|
length = BinaryLength(n) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return buff.Bytes() |
|
|
|
|
if n == 0 { return make([]uint64, 1) } |
|
|
|
|
|
|
|
|
|
slice := ToBinarySlice(n / 256, 0) |
|
|
|
|
slice = append(slice, n % 256) |
|
|
|
|
|
|
|
|
|
return slice |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func ToBin(n uint64, length uint64) string { |
|
|
|
|
var buf bytes.Buffer |
|
|
|
|
for _, val := range ToBinarySlice(n, length) { |
|
|
|
|
buf.WriteString(string(val)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return buf.String() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func FromBin(data []byte) uint64 { |
|
|
|
|
if len(data) == 0 { return 0 } |
|
|
|
|
|
|
|
|
|
return FromBin(data[:len(data)-1]) * 256 + uint64(data[len(data)-1]) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func Decode(data []byte, pos int) { |
|
|
|
|
char := int(data[pos]) |
|
|
|
|
switch { |
|
|
|
|
case char < 24: |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func Encode(object interface{}) []byte { |
|
|
|
|
var buff bytes.Buffer |
|
|
|
|
|
|
|
|
|
switch t := object.(type) { |
|
|
|
|
case string: |
|
|
|
|
if len(t) < 56 { |
|
|
|
|
buff.WriteString(string(len(t) + 64) + t) |
|
|
|
|
} else { |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
case uint32, uint64: |
|
|
|
|
var num uint64 |
|
|
|
|
if _num, ok := t.(uint64); ok { |
|
|
|
@ -40,12 +62,49 @@ func Encode(object interface{}) []byte { |
|
|
|
|
if num >= 0 && num < 24 { |
|
|
|
|
buff.WriteString(string(num)) |
|
|
|
|
} else if num <= uint64(math.Pow(2, 256)) { |
|
|
|
|
b := ToBin(num, 0) |
|
|
|
|
buff.WriteString(string(len(b) + 23) + b) |
|
|
|
|
} else { |
|
|
|
|
b := ToBin(num, 0) |
|
|
|
|
b2 := ToBin(uint64(len(b)), 0) |
|
|
|
|
buff.WriteString(string(len(b2) + 55) + b2 + b) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case string: |
|
|
|
|
if len(t) < 56 { |
|
|
|
|
buff.WriteString(string(len(t) + 64) + t) |
|
|
|
|
} else { |
|
|
|
|
b2 := ToBin(uint64(len(t)), 0) |
|
|
|
|
buff.WriteString(string(len(b2) + 119) + b2 + t) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case []byte: |
|
|
|
|
// Cast the byte slice to a string
|
|
|
|
|
buff.Write(Encode(string(t))) |
|
|
|
|
case []interface{}: |
|
|
|
|
buff.Write(EncodeSlice(t)) |
|
|
|
|
|
|
|
|
|
case []interface{}, []string: |
|
|
|
|
// Inline function for writing the slice header
|
|
|
|
|
WriteSliceHeader := func(length int) { |
|
|
|
|
if length < 56 { |
|
|
|
|
buff.WriteString(string(length + 128)) |
|
|
|
|
} else { |
|
|
|
|
b2 := ToBin(uint64(length), 0) |
|
|
|
|
buff.WriteString(string(len(b2) + 183) + b2) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// FIXME How can I do this "better"?
|
|
|
|
|
if interSlice, ok := t.([]interface{}); ok { |
|
|
|
|
WriteSliceHeader(len(interSlice)) |
|
|
|
|
for _, val := range interSlice { |
|
|
|
|
buff.Write(Encode(val)) |
|
|
|
|
} |
|
|
|
|
} else if stringSlice, ok := t.([]string); ok { |
|
|
|
|
WriteSliceHeader(len(stringSlice)) |
|
|
|
|
for _, val := range stringSlice { |
|
|
|
|
buff.Write(Encode(val)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return buff.Bytes() |
|
|
|
|