When creating uint32, an incomplete byte array is returned

I try to accommodate two addresses and a port in an array and then, as seen by the code, convert to uint16 for further work, but I do not get the desired result at the output.

s, d := net.IP{172, 16, 100, 11}, net.IP{10, 0, 88, 11}
var sp uint16 = 54876
//var dp uint16 = 445

var spByte = make([]byte, 2)
binary.BigEndian.PutUint16(spByte, sp)

var x = make([]byte, 10) // [172 16 100 11 10 0 88 11 214 92]
copy(x[:4], s)
copy(x[4:], d)
copy(x[8:], spByte)

ret := binary.BigEndian.Uint32(x)

var a, z uint16
a = uint16(ret >> 16)
z = uint16(ret & 0xFFFF)

newret := (uint32(a) << 16) | uint32(z)

var xs = make([]byte,10) // [172 16 100 11 0 0 0 0 0 0]

@11132 What’s your desired output? If you’re referring to the 0s in the slice at the end, it’s because you’re taking a 10 byte array, encoding only the first 4 into a uint32, and then “unpacking” those 4 bytes.

yes, I already understood this, I took a step further and I just need to pack two uint16 into one and somehow put it back here is my code at the moment

    s, d  := net.IP{172, 16, 100, 11}, net.IP{10, 0, 88, 11}
var sp uint16 = 54876
//var dp uint16 = 445

var b, x = make([]byte,4),make([]byte,2)
n := copy(b,s[3:])
n += copy(b[n:],d[3:])

ret := binary.LittleEndian.Uint32(b)

var a, z uint16
a = uint16(ret >> 16)
z = uint16(ret & 0xffff)

fmt.Printf("a = %d z = %d\n",a,z)

w := (z << 16) | a

fmt.Printf("Packing: %d\n", w)

a = w & 0xffff
z = (w >> 16 ) & 0xffff
fmt.Printf("a = %d z = %d\n",a,z)

newret := (uint32(a) << 16) | uint32(z)

var xs = make([]byte,4)

I got errors that you can’t shift a 16 bit integer by 16 bits, so I used uint32 for temporary values and got this: https://play.golang.org/p/cUrflqi37fV

As I understand it, it is practically impossible to convert two uint16 numbers into one and then and get it back to these two numbers? I just need a number in the range 1-65535

@11132 You can’t take two 16 bit values (for a total of 32 bits of data), store it into a single 16 bit value and then get the original 32-bits back out of it unless you’re using compression. I think it’s impossible to get this level of compression when you’re talking about individual 16- and 32-bit values, but if you have a lot of these values and store them as 32-bit ints, you could compress them with an algorithm like LZMA to take advantage of repeating patterns (if any) in the bits.

Is there then the possibility of compressing three bytes into two bytes? for example [11 92 214] such an array lead to uint16?

You can’t compress individual bytes like this with any conventional compression algorithms like Huffman encoding, Lempel-Ziv(-Markov), etc. Those algorithms usually need hundreds of bytes (usually KiB, MiB) to get any real space savings (10-75%, depending on the data).

If you can completely discard bits from the value, then you might be able to shrink these values down. For example, are you only storing intranet IPv4 addresses? If so, you might be able to do something like this:

Instead of actually storing the full 10.AAA.AAA.AAA, 172.16.BBB.BBB, or 192.168.CCC.CCC address, maybe encode the class in 2 bits:

01 - Class A (10…)
10 - Class B (172.16…)
11 - Class C

And then you only need 21, 14 and 14 bits (for class A, B, and C, respectively).

Note that it’s been about a decade since I had to think about IP addresses, CIDR, subnet mask bits, etc., so I might get the details wrong about the intranet network classes, but I’m just trying to illustrate that you can save bits if you don’t need to actually store the full data.

After all of this, one more question: Why are you trying to store 32- or 24-bits of data into uint16s?

I’m trying to save the last octet of source adrresss and destination adrress as well as the real destination port in a network packet, specifically in the source port (uint16) field, so that I can then restore the route from this data on another device, I can probably use the destination port as an auxiliary field, therefore I actually have 4 bytes of information, so I’m trying to write an algorithm such as transmitting a route in a packet, I tried to use NATS to transmit information if a new connection appeared, but it really slows down the work. I just got lost in finding a solution.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.