grib/src/main/java/ucar/nc2/grib/collection/Grib2CollectionWriter.java
private GribCollectionProto.SparseArray writeSparseArray(Grib2CollectionBuilder.VariableBag vb, Set<Integer> fileSet) {
    GribCollectionProto.SparseArray.Builder b = GribCollectionProto.SparseArray.newBuilder();
    SparseArray<Grib2Record> sa = vb.coordND.getSparseArray();
    for (int size : sa.getShape())
      b.addSize(size);
    for (int track : sa.getTrack())
      b.addTrack(track);

    for (Grib2Record gr : sa.getContent()) {
      GribCollectionProto.Record.Builder br = GribCollectionProto.Record.newBuilder();

      br.setFileno(gr.getFile());
      fileSet.add(gr.getFile());
      long startPos = gr.getIs().getStartPos();
      br.setStartPos(startPos);

      if (gr.isBmsReplaced()) {
        Grib2SectionBitMap bms = gr.getBitmapSection();
        br.setBmsOffset((int) (bms.getStartingPosition() - startPos));
      }

      Grib2SectionDataRepresentation drs = gr.getDataRepresentationSection();
      br.setDrsOffset((int)(drs.getStartingPosition() - startPos));
      b.addRecords(br);
    }

    b.setNdups(sa.getNdups());
    return b.build();
  }
private GribCollectionProto.SparseArray writeSparseArray(Grib2CollectionBuilder.VariableBag vb, Set<Integer> fileSet) {
    GribCollectionProto.SparseArray.Builder b = GribCollectionProto.SparseArray.newBuilder();
    SparseArray<Grib2Record> sa = vb.coordND.getSparseArray();
    for (int size : sa.getShape())
      b.addSize(size);
    for (int track : sa.getTrack())
      b.addTrack(track);

    for (Grib2Record gr : sa.getContent()) {
      GribCollectionProto.Record.Builder br = GribCollectionProto.Record.newBuilder();

      br.setFileno(gr.getFile());
      fileSet.add(gr.getFile());
      long startPos = gr.getIs().getStartPos();
      br.setStartPos(startPos);

      if (gr.isBmsReplaced()) {
        Grib2SectionBitMap bms = gr.getBitmapSection();
        br.setBmsOffset((int) (bms.getStartingPosition() - startPos));
      }

      Grib2SectionDataRepresentation drs = gr.getDataRepresentationSection();
      br.setDrsOffset((int)(drs.getStartingPosition() - startPos));
      b.addRecords(br);
    }

    b.setNdups(sa.getNdups());
    return b.build();
  }
/*
message Record {
uint32 fileno = 1;               // which GRIB file ? key into GC.fileMap
uint64 pos = 2;                  // offset in GRIB file of the start of entire message
uint64 bmsPos = 3;               // use alternate bms if non-zero
uint32 drsOffset = 4;            // offset of drs from pos (grib2 only)
}

SparseArray only at the GCs (MRC and SRC) not at the Partitions
dont need SparseArray in memory until someone wants to read from the variable
message SparseArray {
repeated uint32 size = 2 [packed=true];     // multidim sizes = shape[]
repeated uint32 track = 3 [packed=true];    // 1-based index into record list, 0 == missing
repeated Record records = 4;                // List<Record>
uint32 ndups = 5;                           // duplicates found when creating
}