1// Copyright 2020 Jebbs. All rights reserved.
2// Use of this source code is governed by MIT
3// license that can be found in the LICENSE file.
4
5package rule
6
7import (
8 "math"
9 "sort"
10)
11
12type meta struct {
13 index int
14 order float64
15 value interface{}
16}
17
18// sortByFields sort slice elements by specified fields
19func sortByFields(slice []interface{}, fields []Field) {
20 if len(slice) == 0 || len(fields) == 0 {
21 return
22 }
23 metas := make([]meta, len(slice))
24 for i, v := range slice {
25 metas[i] = meta{
26 index: i,
27 order: getOrder(v, fields),
28 value: v,
29 }
30 }
31 sort.Slice(
32 metas,
33 func(i, j int) bool {
34 if metas[i].order != metas[j].order {
35 return metas[i].order < metas[j].order
36 }
37 return metas[i].index < metas[j].index
38 },
39 )
40 for i, m := range metas {
41 slice[i] = m.value
42 }
43}
44
45func getOrder(v interface{}, fields []Field) float64 {
46 m, ok := v.(map[string]interface{})
47 if !ok {
48 return 0
49 }
50 hasField := false
51 min := math.Inf(1)
52 for _, field := range fields {
53 value, ok := m[field.Key]
54 if !ok || value == nil {
55 continue
56 }
57 hasField = true
58 var num float64
59 switch v := value.(type) {
60 case float64:
61 num = v
62 case float32:
63 num = float64(v)
64 case int:
65 num = float64(v)
66 case int8:
67 num = float64(v)
68 case int16:
69 num = float64(v)
70 case int32:
71 num = float64(v)
72 case int64:
73 num = float64(v)
74 case uint:
75 num = float64(v)
76 case uint8:
77 num = float64(v)
78 case uint16:
79 num = float64(v)
80 case uint32:
81 num = float64(v)
82 case uint64:
83 num = float64(v)
84 default:
85 num = 0
86 }
87 if num < min {
88 min = num
89 }
90 }
91 if !hasField {
92 return 0
93 }
94 return min
95}