github.com/vc42/parquet-go@v0.0.0-20240320194221-1a9adb5f23f5/order.go (about) 1 package parquet 2 3 import ( 4 "bytes" 5 6 "github.com/vc42/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 }