imposm3/cache/binary/deltacoords.go

112 lines
2.3 KiB
Go

package binary
import (
"encoding/binary"
"errors"
"github.com/omniscale/imposm3/element"
)
func MarshalDeltaNodes(nodes []element.Node, buf []byte) []byte {
estimatedLength := len(nodes)*4*3 + binary.MaxVarintLen64
if cap(buf) < estimatedLength {
buf = make([]byte, estimatedLength)
} else {
// resize slice to full capacity
buf = buf[:cap(buf)-1]
}
lastId := int64(0)
nextPos := binary.PutUvarint(buf, uint64(len(nodes)))
for i := range nodes {
if len(buf)-nextPos < binary.MaxVarintLen64 {
tmp := make([]byte, len(buf)*3/2)
copy(tmp, buf)
buf = tmp
}
nextPos += binary.PutVarint(buf[nextPos:], nodes[i].Id-lastId)
lastId = nodes[i].Id
}
lastLong := int64(0)
for i := range nodes {
if len(buf)-nextPos < binary.MaxVarintLen64 {
tmp := make([]byte, len(buf)*3/2)
copy(tmp, buf)
buf = tmp
}
long := int64(CoordToInt(nodes[i].Long))
nextPos += binary.PutVarint(buf[nextPos:], long-lastLong)
lastLong = long
}
lastLat := int64(0)
for i := range nodes {
if len(buf)-nextPos < binary.MaxVarintLen64 {
tmp := make([]byte, len(buf)*3/2)
copy(tmp, buf)
buf = tmp
}
lat := int64(CoordToInt(nodes[i].Lat))
nextPos += binary.PutVarint(buf[nextPos:], lat-lastLat)
lastLat = lat
}
return buf[:nextPos]
}
var varintErr = errors.New("unmarshal delta coords: missing data for varint or overflow")
func UnmarshalDeltaNodes(buf []byte, nodes []element.Node) ([]element.Node, error) {
length, n := binary.Uvarint(buf)
if n <= 0 {
return nil, varintErr
}
var offset = n
if uint64(cap(nodes)) < length {
nodes = make([]element.Node, length)
} else {
nodes = nodes[:length]
}
lastId := int64(0)
for i := 0; uint64(i) < length; i++ {
id, n := binary.Varint(buf[offset:])
if n <= 0 {
return nil, varintErr
}
offset += n
id = lastId + id
nodes[i].Id = id
lastId = id
}
lastLong := int64(0)
for i := 0; uint64(i) < length; i++ {
long, n := binary.Varint(buf[offset:])
if n <= 0 {
return nil, varintErr
}
offset += n
long = lastLong + long
nodes[i].Long = IntToCoord(uint32(long))
lastLong = long
}
lastLat := int64(0)
for i := 0; uint64(i) < length; i++ {
lat, n := binary.Varint(buf[offset:])
if n <= 0 {
return nil, varintErr
}
offset += n
lat = lastLat + lat
nodes[i].Lat = IntToCoord(uint32(lat))
lastLat = lat
}
return nodes, nil
}