114 lines
2.6 KiB
Go
114 lines
2.6 KiB
Go
|
// +build 386 amd64,!appengine
|
||
|
|
||
|
package roaring
|
||
|
|
||
|
import (
|
||
|
"io"
|
||
|
"reflect"
|
||
|
"unsafe"
|
||
|
)
|
||
|
|
||
|
func (ac *arrayContainer) writeTo(stream io.Writer) (int, error) {
|
||
|
buf := uint16SliceAsByteSlice(ac.content)
|
||
|
return stream.Write(buf)
|
||
|
}
|
||
|
|
||
|
func (bc *bitmapContainer) writeTo(stream io.Writer) (int, error) {
|
||
|
buf := uint64SliceAsByteSlice(bc.bitmap)
|
||
|
return stream.Write(buf)
|
||
|
}
|
||
|
|
||
|
// readFrom reads an arrayContainer from stream.
|
||
|
// PRE-REQUISITE: you must size the arrayContainer correctly (allocate b.content)
|
||
|
// *before* you call readFrom. We can't guess the size in the stream
|
||
|
// by this point.
|
||
|
func (ac *arrayContainer) readFrom(stream io.Reader) (int, error) {
|
||
|
buf := uint16SliceAsByteSlice(ac.content)
|
||
|
return io.ReadFull(stream, buf)
|
||
|
}
|
||
|
|
||
|
func (bc *bitmapContainer) readFrom(stream io.Reader) (int, error) {
|
||
|
buf := uint64SliceAsByteSlice(bc.bitmap)
|
||
|
n, err := io.ReadFull(stream, buf)
|
||
|
bc.computeCardinality()
|
||
|
return n, err
|
||
|
}
|
||
|
|
||
|
func uint64SliceAsByteSlice(slice []uint64) []byte {
|
||
|
// make a new slice header
|
||
|
header := *(*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||
|
|
||
|
// update its capacity and length
|
||
|
header.Len *= 8
|
||
|
header.Cap *= 8
|
||
|
|
||
|
// return it
|
||
|
return *(*[]byte)(unsafe.Pointer(&header))
|
||
|
}
|
||
|
|
||
|
func uint16SliceAsByteSlice(slice []uint16) []byte {
|
||
|
// make a new slice header
|
||
|
header := *(*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||
|
|
||
|
// update its capacity and length
|
||
|
header.Len *= 2
|
||
|
header.Cap *= 2
|
||
|
|
||
|
// return it
|
||
|
return *(*[]byte)(unsafe.Pointer(&header))
|
||
|
}
|
||
|
|
||
|
func (bc *bitmapContainer) asLittleEndianByteSlice() []byte {
|
||
|
return uint64SliceAsByteSlice(bc.bitmap)
|
||
|
}
|
||
|
|
||
|
// Deserialization code follows
|
||
|
|
||
|
func byteSliceAsUint16Slice(slice []byte) []uint16 {
|
||
|
if len(slice)%2 != 0 {
|
||
|
panic("Slice size should be divisible by 2")
|
||
|
}
|
||
|
|
||
|
// make a new slice header
|
||
|
header := *(*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||
|
|
||
|
// update its capacity and length
|
||
|
header.Len /= 2
|
||
|
header.Cap /= 2
|
||
|
|
||
|
// return it
|
||
|
return *(*[]uint16)(unsafe.Pointer(&header))
|
||
|
}
|
||
|
|
||
|
func byteSliceAsUint64Slice(slice []byte) []uint64 {
|
||
|
if len(slice)%8 != 0 {
|
||
|
panic("Slice size should be divisible by 8")
|
||
|
}
|
||
|
|
||
|
// make a new slice header
|
||
|
header := *(*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||
|
|
||
|
// update its capacity and length
|
||
|
header.Len /= 8
|
||
|
header.Cap /= 8
|
||
|
|
||
|
// return it
|
||
|
return *(*[]uint64)(unsafe.Pointer(&header))
|
||
|
}
|
||
|
|
||
|
func byteSliceAsInterval16Slice(slice []byte) []interval16 {
|
||
|
if len(slice)%4 != 0 {
|
||
|
panic("Slice size should be divisible by 4")
|
||
|
}
|
||
|
|
||
|
// make a new slice header
|
||
|
header := *(*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||
|
|
||
|
// update its capacity and length
|
||
|
header.Len /= 4
|
||
|
header.Cap /= 4
|
||
|
|
||
|
// return it
|
||
|
return *(*[]interval16)(unsafe.Pointer(&header))
|
||
|
}
|