1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
// Copyright ©2014 The bíogo Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package internal
import (
"encoding/binary"
"fmt"
"io"
"github.com/biogo/hts/bgzf"
)
// WriteIndex writes the Index to the given io.Writer.
func WriteIndex(w io.Writer, idx *Index, typ string) error {
idx.sort()
err := writeIndices(w, idx.Refs, typ)
if err != nil {
return err
}
if idx.Unmapped != nil {
err = binary.Write(w, binary.LittleEndian, *idx.Unmapped)
}
return err
}
func writeIndices(w io.Writer, idx []RefIndex, typ string) error {
for i := range idx {
err := writeBins(w, idx[i].Bins, idx[i].Stats, typ)
if err != nil {
return err
}
err = writeIntervals(w, idx[i].Intervals, typ)
if err != nil {
return err
}
}
return nil
}
func writeBins(w io.Writer, bins []Bin, stats *ReferenceStats, typ string) error {
n := int32(len(bins))
if stats != nil {
n++
}
err := binary.Write(w, binary.LittleEndian, &n)
if err != nil {
return err
}
for _, b := range bins {
err = binary.Write(w, binary.LittleEndian, b.Bin)
if err != nil {
return fmt.Errorf("%s: failed to write bin number: %v", typ, err)
}
err = writeChunks(w, b.Chunks, typ)
if err != nil {
return err
}
}
if stats != nil {
return writeStats(w, stats, typ)
}
return nil
}
func writeChunks(w io.Writer, chunks []bgzf.Chunk, typ string) error {
err := binary.Write(w, binary.LittleEndian, int32(len(chunks)))
if err != nil {
return fmt.Errorf("%s: failed to write bin count: %v", typ, err)
}
for _, c := range chunks {
err = binary.Write(w, binary.LittleEndian, vOffset(c.Begin))
if err != nil {
return fmt.Errorf("%s: failed to write chunk begin virtual offset: %v", typ, err)
}
err = binary.Write(w, binary.LittleEndian, vOffset(c.End))
if err != nil {
return fmt.Errorf("%s: failed to write chunk end virtual offset: %v", typ, err)
}
}
return nil
}
func writeStats(w io.Writer, stats *ReferenceStats, typ string) error {
var err error
err = binary.Write(w, binary.LittleEndian, [2]uint32{StatsDummyBin, 2})
if err != nil {
return fmt.Errorf("%s: failed to write stats bin header: %v", typ, err)
}
err = binary.Write(w, binary.LittleEndian, vOffset(stats.Chunk.Begin))
if err != nil {
return fmt.Errorf("%s: failed to write index stats chunk begin virtual offset: %v", typ, err)
}
err = binary.Write(w, binary.LittleEndian, vOffset(stats.Chunk.End))
if err != nil {
return fmt.Errorf("%s: failed to write index stats chunk end virtual offset: %v", typ, err)
}
err = binary.Write(w, binary.LittleEndian, stats.Mapped)
if err != nil {
return fmt.Errorf("%s: failed to write index stats mapped count: %v", typ, err)
}
err = binary.Write(w, binary.LittleEndian, stats.Unmapped)
if err != nil {
return fmt.Errorf("%s: failed to write index stats unmapped count: %v", typ, err)
}
return nil
}
func writeIntervals(w io.Writer, offsets []bgzf.Offset, typ string) error {
err := binary.Write(w, binary.LittleEndian, int32(len(offsets)))
if err != nil {
return err
}
for _, o := range offsets {
err := binary.Write(w, binary.LittleEndian, vOffset(o))
if err != nil {
return fmt.Errorf("%s: failed to write tile interval virtual offset: %v", typ, err)
}
}
return nil
}
|