package binary import ( "encoding/binary" "github.com/omniscale/imposm3/element" ) func MarshalIdRefsBunch(idRefs []element.IdRefs) []byte { buf := make([]byte, len(idRefs)*(4+1+6)+binary.MaxVarintLen64) lastRef := int64(0) lastId := int64(0) nextPos := 0 nextPos += binary.PutUvarint(buf[nextPos:], uint64(len(idRefs))) for _, idRef := range idRefs { if len(buf)-nextPos < binary.MaxVarintLen64 { tmp := make([]byte, len(buf)*2) copy(tmp, buf) buf = tmp } nextPos += binary.PutVarint(buf[nextPos:], idRef.Id-lastId) lastId = idRef.Id } for _, idRef := range idRefs { if len(buf)-nextPos < binary.MaxVarintLen64 { tmp := make([]byte, len(buf)*2) copy(tmp, buf) buf = tmp } nextPos += binary.PutUvarint(buf[nextPos:], uint64(len(idRef.Refs))) } for _, idRef := range idRefs { for _, ref := range idRef.Refs { if len(buf)-nextPos < binary.MaxVarintLen64 { tmp := make([]byte, len(buf)*2) copy(tmp, buf) buf = tmp } nextPos += binary.PutVarint(buf[nextPos:], ref-lastRef) lastRef = ref } } return buf[:nextPos] } func MarshalIdRefsBunch2(idRefs []element.IdRefs, buf []byte) []byte { lastRef := int64(0) lastId := int64(0) nextPos := 0 estSize := len(idRefs)*(4+1+6) + binary.MaxVarintLen64 if cap(buf) < estSize { buf = make([]byte, estSize) } else { // expand to full capacity buf = buf[:cap(buf)] } nextPos += binary.PutUvarint(buf[nextPos:], uint64(len(idRefs))) for _, idRef := range idRefs { if len(buf)-nextPos < binary.MaxVarintLen64 { tmp := make([]byte, cap(buf)*2) copy(tmp, buf[:nextPos]) buf = tmp } nextPos += binary.PutVarint(buf[nextPos:], idRef.Id-lastId) lastId = idRef.Id } for _, idRef := range idRefs { if len(buf)-nextPos < binary.MaxVarintLen64 { tmp := make([]byte, cap(buf)*2) copy(tmp, buf[:nextPos]) buf = tmp } nextPos += binary.PutUvarint(buf[nextPos:], uint64(len(idRef.Refs))) } for _, idRef := range idRefs { for _, ref := range idRef.Refs { if len(buf)-nextPos < binary.MaxVarintLen64 { tmp := make([]byte, cap(buf)*2) copy(tmp, buf[:nextPos]) buf = tmp } nextPos += binary.PutVarint(buf[nextPos:], ref-lastRef) lastRef = ref } } return buf[:nextPos] } func UnmarshalIdRefsBunch(buf []byte) []element.IdRefs { length, n := binary.Uvarint(buf) if n <= 0 { return nil } offset := n idRefs := make([]element.IdRefs, length) last := int64(0) for i := 0; uint64(i) < length; i++ { idRefs[i].Id, n = binary.Varint(buf[offset:]) if n <= 0 { panic("no data") } offset += n idRefs[i].Id += last last = idRefs[i].Id } var numRefs uint64 for i := 0; uint64(i) < length; i++ { numRefs, n = binary.Uvarint(buf[offset:]) if n <= 0 { panic("no data") } offset += n idRefs[i].Refs = make([]int64, numRefs) } last = 0 for idIdx := 0; uint64(idIdx) < length; idIdx++ { for refIdx := 0; refIdx < len(idRefs[idIdx].Refs); refIdx++ { idRefs[idIdx].Refs[refIdx], n = binary.Varint(buf[offset:]) if n <= 0 { panic("no data") } offset += n idRefs[idIdx].Refs[refIdx] += last last = idRefs[idIdx].Refs[refIdx] } } return idRefs } func UnmarshalIdRefsBunch2(buf []byte, idRefs []element.IdRefs) []element.IdRefs { length, n := binary.Uvarint(buf) if n <= 0 { return nil } offset := n if uint64(cap(idRefs)) < length { idRefs = make([]element.IdRefs, length) } else { idRefs = idRefs[:length] } last := int64(0) for i := 0; uint64(i) < length; i++ { idRefs[i].Id, n = binary.Varint(buf[offset:]) if n <= 0 { panic("no data") } offset += n idRefs[i].Id += last last = idRefs[i].Id } var numRefs uint64 for i := 0; uint64(i) < length; i++ { numRefs, n = binary.Uvarint(buf[offset:]) if n <= 0 { panic("no data") } offset += n if uint64(cap(idRefs[i].Refs)) < numRefs { idRefs[i].Refs = make([]int64, numRefs) } else { idRefs[i].Refs = idRefs[i].Refs[:numRefs] } } last = 0 for idIdx := 0; uint64(idIdx) < length; idIdx++ { for refIdx := 0; refIdx < len(idRefs[idIdx].Refs); refIdx++ { idRefs[idIdx].Refs[refIdx], n = binary.Varint(buf[offset:]) if n <= 0 { panic("no data") } offset += n idRefs[idIdx].Refs[refIdx] += last last = idRefs[idIdx].Refs[refIdx] } } return idRefs }