github.com/segmentio/parquet-go@v0.0.0-20230712180008-5d42db8f0d47/order.go (about)

     1  package parquet
     2  
     3  import (
     4  	"bytes"
     5  
     6  	"github.com/segmentio/parquet-go/internal/unsafecast"
     7  )
     8  
     9  func orderOfBool(data []bool) int {
    10  	switch len(data) {
    11  	case 0, 1:
    12  		return 0
    13  	default:
    14  		k := 0
    15  		i := 0
    16  
    17  		if data[0] { // true => false: descending
    18  			k = -1
    19  			i = streakOfTrue(data)
    20  			if i == len(data) {
    21  				k = +1
    22  			} else {
    23  				i += streakOfFalse(data[i:])
    24  			}
    25  		} else { // false => true: ascending
    26  			k = +1
    27  			i = streakOfFalse(data)
    28  			i += streakOfTrue(data[i:])
    29  		}
    30  
    31  		if i != len(data) {
    32  			k = 0
    33  		}
    34  		return k
    35  	}
    36  }
    37  
    38  func streakOfTrue(data []bool) int {
    39  	if i := bytes.IndexByte(unsafecast.BoolToBytes(data), 0); i >= 0 {
    40  		return i
    41  	}
    42  	return len(data)
    43  }
    44  
    45  func streakOfFalse(data []bool) int {
    46  	if i := bytes.IndexByte(unsafecast.BoolToBytes(data), 1); i >= 0 {
    47  		return i
    48  	}
    49  	return len(data)
    50  }
    51  
    52  func orderOfBytes(data [][]byte) int {
    53  	switch len(data) {
    54  	case 0, 1:
    55  		return 0
    56  	}
    57  	data = skipBytesStreak(data)
    58  	if len(data) < 2 {
    59  		return 1
    60  	}
    61  	ordering := bytes.Compare(data[0], data[1])
    62  	switch {
    63  	case ordering < 0:
    64  		if bytesAreInAscendingOrder(data[1:]) {
    65  			return +1
    66  		}
    67  	case ordering > 0:
    68  		if bytesAreInDescendingOrder(data[1:]) {
    69  			return -1
    70  		}
    71  	}
    72  	return 0
    73  }
    74  
    75  func skipBytesStreak(data [][]byte) [][]byte {
    76  	for i := 1; i < len(data); i++ {
    77  		if !bytes.Equal(data[i], data[0]) {
    78  			return data[i-1:]
    79  		}
    80  	}
    81  	return data[len(data)-1:]
    82  }
    83  
    84  func bytesAreInAscendingOrder(data [][]byte) bool {
    85  	for i := len(data) - 1; i > 0; i-- {
    86  		k := bytes.Compare(data[i-1], data[i])
    87  		if k > 0 {
    88  			return false
    89  		}
    90  	}
    91  	return true
    92  }
    93  
    94  func bytesAreInDescendingOrder(data [][]byte) bool {
    95  	for i := len(data) - 1; i > 0; i-- {
    96  		k := bytes.Compare(data[i-1], data[i])
    97  		if k < 0 {
    98  			return false
    99  		}
   100  	}
   101  	return true
   102  }