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  }