github.com/consensys/gnark@v0.11.0/internal/backend/ioutils/intcomp.go (about)

     1  package ioutils
     2  
     3  import (
     4  	"encoding/binary"
     5  	"io"
     6  
     7  	"github.com/ronanh/intcomp"
     8  )
     9  
    10  // CompressAndWriteUints32 compresses a slice of uint32 and writes it to w.
    11  // It returns the input buffer (possibly extended) for future use.
    12  func CompressAndWriteUints32(w io.Writer, input []uint32, buffer []uint32) ([]uint32, error) {
    13  	buffer = buffer[:0]
    14  	buffer = intcomp.CompressUint32(input, buffer)
    15  	if err := binary.Write(w, binary.LittleEndian, uint64(len(buffer))); err != nil {
    16  		return nil, err
    17  	}
    18  	if err := binary.Write(w, binary.LittleEndian, buffer); err != nil {
    19  		return nil, err
    20  	}
    21  	return buffer, nil
    22  }
    23  
    24  // CompressAndWriteUints64 compresses a slice of uint64 and writes it to w.
    25  // It returns the input buffer (possibly extended) for future use.
    26  func CompressAndWriteUints64(w io.Writer, input []uint64) error {
    27  	buffer := intcomp.CompressUint64(input, nil)
    28  	if err := binary.Write(w, binary.LittleEndian, uint64(len(buffer))); err != nil {
    29  		return err
    30  	}
    31  	return binary.Write(w, binary.LittleEndian, buffer)
    32  }
    33  
    34  // ReadAndDecompressUints32 reads a compressed slice of uint32 from r and decompresses it.
    35  // It returns the number of bytes read, the decompressed slice and an error.
    36  func ReadAndDecompressUints32(in []byte, buf32 []uint32) (outbuf32 []uint32, read int, out []uint32, err error) {
    37  	if len(in) < 8 {
    38  		return buf32, 0, nil, io.ErrUnexpectedEOF
    39  	}
    40  	length := binary.LittleEndian.Uint64(in[:8])
    41  	if uint64(len(in)) < 8+4*length {
    42  		return buf32, 0, nil, io.ErrUnexpectedEOF
    43  	}
    44  	in = in[8 : 8+4*length]
    45  	if cap(buf32) < int(length) {
    46  		buf32 = make([]uint32, length)
    47  	} else {
    48  		buf32 = buf32[:length]
    49  	}
    50  
    51  	for i := 0; i < int(length); i++ {
    52  		buf32[i] = binary.LittleEndian.Uint32(in[4*i : 4*(i+1)])
    53  	}
    54  
    55  	return buf32, 8 + 4*int(length), intcomp.UncompressUint32(buf32, nil), nil
    56  }
    57  
    58  // ReadAndDecompressUints64 reads a compressed slice of uint64 from r and decompresses it.
    59  // It returns the number of bytes read, the decompressed slice and an error.
    60  func ReadAndDecompressUints64(in []byte) (int, []uint64, error) {
    61  	if len(in) < 8 {
    62  		return 0, nil, io.ErrUnexpectedEOF
    63  	}
    64  	length := binary.LittleEndian.Uint64(in[:8])
    65  	if uint64(len(in)) < 8+8*length {
    66  		return 0, nil, io.ErrUnexpectedEOF
    67  	}
    68  	in = in[8 : 8+8*length]
    69  	buffer := make([]uint64, length)
    70  	for i := 0; i < int(length); i++ {
    71  		buffer[i] = binary.LittleEndian.Uint64(in[8*i : 8*(i+1)])
    72  	}
    73  	return 8 + 8*int(length), intcomp.UncompressUint64(buffer, nil), nil
    74  }