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