github.com/vc42/parquet-go@v0.0.0-20240320194221-1a9adb5f23f5/encoding/bitpacked/bitpacked.go (about)

     1  package bitpacked
     2  
     3  import (
     4  	"github.com/vc42/parquet-go/encoding"
     5  	"github.com/vc42/parquet-go/format"
     6  )
     7  
     8  type Encoding struct {
     9  	encoding.NotSupported
    10  	BitWidth int
    11  }
    12  
    13  func (e *Encoding) String() string {
    14  	return "BIT_PACKED"
    15  }
    16  
    17  func (e *Encoding) Encoding() format.Encoding {
    18  	return format.BitPacked
    19  }
    20  
    21  func (e *Encoding) EncodeLevels(dst, src []byte) ([]byte, error) {
    22  	dst, err := encodeLevels(dst[:0], src, uint(e.BitWidth))
    23  	return dst, e.wrap(err)
    24  }
    25  
    26  func (e *Encoding) DecodeLevels(dst, src []byte) ([]byte, error) {
    27  	dst, err := decodeLevels(dst[:0], src, uint(e.BitWidth))
    28  	return dst, e.wrap(err)
    29  }
    30  
    31  func (e *Encoding) wrap(err error) error {
    32  	if err != nil {
    33  		err = encoding.Error(e, err)
    34  	}
    35  	return err
    36  }
    37  
    38  func encodeLevels(dst, src []byte, bitWidth uint) ([]byte, error) {
    39  	if bitWidth == 0 || len(src) == 0 {
    40  		return append(dst[:0], 0), nil
    41  	}
    42  
    43  	n := ((int(bitWidth) * len(src)) + 7) / 8
    44  	c := n + 1
    45  
    46  	if cap(dst) < c {
    47  		dst = make([]byte, c)
    48  	} else {
    49  		dst = dst[:c]
    50  		for i := range dst {
    51  			dst[i] = 0
    52  		}
    53  	}
    54  
    55  	bitMask := byte(1<<bitWidth) - 1
    56  	bitShift := 8 - bitWidth
    57  	bitOffset := uint(0)
    58  
    59  	for _, value := range src {
    60  		v := bitFlip(value) >> bitShift
    61  		i := bitOffset / 8
    62  		j := bitOffset % 8
    63  		dst[i+0] |= (v & bitMask) << j
    64  		dst[i+1] |= (v >> (8 - j))
    65  		bitOffset += bitWidth
    66  	}
    67  
    68  	return dst[:n], nil
    69  }
    70  
    71  func decodeLevels(dst, src []byte, bitWidth uint) ([]byte, error) {
    72  	if bitWidth == 0 || len(src) == 0 {
    73  		return append(dst[:0], 0), nil
    74  	}
    75  
    76  	numBits := 8 * uint(len(src))
    77  	numValues := int(numBits / bitWidth)
    78  	if (numBits % bitWidth) != 0 {
    79  		numValues++
    80  	}
    81  
    82  	if cap(dst) < numValues {
    83  		dst = make([]byte, numValues)
    84  	} else {
    85  		dst = dst[:numValues]
    86  		for i := range dst {
    87  			dst[i] = 0
    88  		}
    89  	}
    90  
    91  	bitMask := byte(1<<bitWidth) - 1
    92  	bitShift := 8 - bitWidth
    93  	bitOffset := uint(0)
    94  
    95  	for k := range dst {
    96  		i := bitOffset / 8
    97  		j := bitOffset % 8
    98  		v := (src[i+0] >> j)
    99  		if int(i+1) < len(src) {
   100  			v |= (src[i+1] << (8 - j))
   101  		}
   102  		v &= bitMask
   103  		dst[k] = bitFlip(v) >> bitShift
   104  		bitOffset += bitWidth
   105  	}
   106  
   107  	return dst, nil
   108  }
   109  
   110  func bitFlip(b byte) byte {
   111  	return (((b >> 0) & 1) << 7) |
   112  		(((b >> 1) & 1) << 6) |
   113  		(((b >> 2) & 1) << 5) |
   114  		(((b >> 3) & 1) << 4) |
   115  		(((b >> 4) & 1) << 3) |
   116  		(((b >> 5) & 1) << 2) |
   117  		(((b >> 6) & 1) << 1) |
   118  		(((b >> 7) & 1) << 0)
   119  }