Odinovsky
Odinovsky

Reputation: 555

Converting variable-sized []byte to int64 in Golang

I have a method that transposes slice of int64 ([]int64) to a int64 but I haven't found a way to do it.

package main

import "fmt"
import "bytes"
import "encoding/binary"

func main() {
    var mySlice = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 23}
    data := binary.BigEndian.Uint64(mySlice)
    fmt.Println(data)

    var ret int64
    buf := bytes.NewBuffer(mySlice)
    binary.Read(buf, binary.BigEndian, ret)

    fmt.Println(ret)
}

My method initializes []byte from a given size (say, make([]byte, 20)) and my method operates on a given bit and dimension size and interleaves it (bit operations):

So, say a []byte{0 0 0 0 0 0 0 0 0 23} gives 23 and a [more trailing zeroes..., 125, more tailing zeroes...] is 500

I guess I'm looking for something more like java's BigInteger class that takes in []byte (and signum) in BigEndian.

The method I'm trying to port (from Java) would be something like this:

BigInteger toIndex(long... transposedIndex) {
        byte[] b = new byte[length];
        int bIndex = length - 1;
        long mask = 1L << (bits - 1);
        for (int i = 0; i < bits; i++) {
            for (int j = 0; j < transposedIndex.length; j++) {
                if ((transposedIndex[j] & mask) != 0) {
                    b[length - 1 - bIndex / 8] |= 1 << (bIndex % 8);
                }
                bIndex--;
            }
            mask >>= 1;
        }
        // b is expected to be BigEndian
        return new BigInteger(1, b);
    }

and what I have in Golang is this:

func (s *TestStruct) untranspose(x []int64) (b int64) {
    t := make([]byte, s.length)
    bIndex := s.length - 1
    mask := int64(1 << (s.bits - 1))

    for i := 0; i < int(s.bits); i++ {
        for j := 0; j < len(x); j++ {
            if (x[j] & mask) != 0 {
                t[s.length - 1 - bIndex / 8] |= 1 << (bIndex % 8)
            }

            bIndex--
        }
        mask >>= 1
    }

    return int64(binary.BigEndian.Uint64(t))
}

which doesn't seem to be correct. []byte could be longer than 8-bit, say, [0 0 0 0 0 0 0 0 2 170]

Upvotes: 1

Views: 13974

Answers (1)

Joshua Vega
Joshua Vega

Reputation: 599

First, your slice is too long. Because of this, if each value represents a byte, then a 64-bit unsigned integer requires only 8 entries. The slice is read from front to back so in your sample the 23 entry is chopped off because it's the 10th entry.

Also, when reading from the buffer, you need to pass a reference as the last parameter (&ret).

Lastly, you define ret as a uint which is 32-bits long where as the mySlice defines a 64-bit integer (uint64). This means that the last 32-bits of your slice will be cut off.

Below is a the working code for your sample and it's output:

package main

import "fmt"
import "bytes"
import "encoding/binary"

func main() {
    var mySlice = []byte{0, 0, 0, 0, 0, 0, 0, 23}
    data := binary.BigEndian.Uint64(mySlice)
    fmt.Println(data)

    var ret uint64
    buf := bytes.NewBuffer(mySlice)
    binary.Read(buf, binary.BigEndian, &ret)
    fmt.Println(ret)
}
23
23

Upvotes: 6

Related Questions