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 }