spec: https://github.com/RoaringBitmap/RoaringFormatSpec
(w io.Writer)
| 491 | |
| 492 | // spec: https://github.com/RoaringBitmap/RoaringFormatSpec |
| 493 | func (ra *roaringArray) writeTo(w io.Writer) (n int64, err error) { |
| 494 | hasRun := ra.hasRunCompression() |
| 495 | isRunSizeInBytes := 0 |
| 496 | cookieSize := 8 |
| 497 | if hasRun { |
| 498 | cookieSize = 4 |
| 499 | isRunSizeInBytes = (len(ra.keys) + 7) / 8 |
| 500 | } |
| 501 | descriptiveHeaderSize := 4 * len(ra.keys) |
| 502 | preambleSize := cookieSize + isRunSizeInBytes + descriptiveHeaderSize |
| 503 | |
| 504 | buf := make([]byte, preambleSize+4*len(ra.keys)) |
| 505 | |
| 506 | nw := 0 |
| 507 | |
| 508 | if hasRun { |
| 509 | binary.LittleEndian.PutUint16(buf[0:], uint16(serialCookie)) |
| 510 | nw += 2 |
| 511 | binary.LittleEndian.PutUint16(buf[2:], uint16(len(ra.keys)-1)) |
| 512 | nw += 2 |
| 513 | // compute isRun bitmap without temporary allocation |
| 514 | runbitmapslice := buf[nw : nw+isRunSizeInBytes] |
| 515 | for i, c := range ra.containers { |
| 516 | switch c.(type) { |
| 517 | case *runContainer16: |
| 518 | runbitmapslice[i/8] |= 1 << (uint(i) % 8) |
| 519 | } |
| 520 | } |
| 521 | nw += isRunSizeInBytes |
| 522 | } else { |
| 523 | binary.LittleEndian.PutUint32(buf[0:], uint32(serialCookieNoRunContainer)) |
| 524 | nw += 4 |
| 525 | binary.LittleEndian.PutUint32(buf[4:], uint32(len(ra.keys))) |
| 526 | nw += 4 |
| 527 | } |
| 528 | |
| 529 | // descriptive header |
| 530 | for i, key := range ra.keys { |
| 531 | binary.LittleEndian.PutUint16(buf[nw:], key) |
| 532 | nw += 2 |
| 533 | c := ra.containers[i] |
| 534 | binary.LittleEndian.PutUint16(buf[nw:], uint16(c.getCardinality()-1)) |
| 535 | nw += 2 |
| 536 | } |
| 537 | |
| 538 | startOffset := int64(preambleSize + 4*len(ra.keys)) |
| 539 | if !hasRun || (len(ra.keys) >= noOffsetThreshold) { |
| 540 | // offset header |
| 541 | for _, c := range ra.containers { |
| 542 | binary.LittleEndian.PutUint32(buf[nw:], uint32(startOffset)) |
| 543 | nw += 4 |
| 544 | switch rc := c.(type) { |
| 545 | case *runContainer16: |
| 546 | startOffset += 2 + int64(len(rc.iv))*4 |
| 547 | default: |
| 548 | startOffset += int64(getSizeInBytesFromCardinality(c.getCardinality())) |
| 549 | } |
| 550 | } |
no test coverage detected