func compareRule(a, b *Rule) int {
	switch {
	case a.groupIndex() < b.groupIndex():
		return -1
	case a.groupIndex() > b.groupIndex():
		return 1
	case a.GroupID < b.GroupID:
		return -1
	case a.GroupID > b.GroupID:
		return 1
	case a.Index < b.Index:
		return -1
	case a.Index > b.Index:
		return 1
	case a.ID < b.ID:
		return -1
	case a.ID > b.ID:
		return 1
	default:
		return 0
	}
}
Rules are ordered by (GroupID, Index, ID).
package placement
import (
	"encoding/hex"
	"encoding/json"
	"sort"
	"github.com/pingcap/kvproto/pkg/metapb"
)
type PeerRoleType string
const (
	Voter PeerRoleType = "voter"
	Leader PeerRoleType = "leader"
	Follower PeerRoleType = "follower"
	Learner PeerRoleType = "learner"
)
func validateRole(s PeerRoleType) bool {
	return s == Voter || s == Leader || s == Follower || s == Learner
}
func (s PeerRoleType) MetaPeerRole() metapb.PeerRole {
	if s == Learner {
		return metapb.PeerRole_Learner
	}
	return metapb.PeerRole_Voter
}
type Rule struct {
	GroupID          string            `json:"group_id"`                     
	ID               string            `json:"id"`                           
	Index            int               `json:"index,omitempty"`              
	Override         bool              `json:"override,omitempty"`           
	StartKey         []byte            `json:"-"`                            
	StartKeyHex      string            `json:"start_key"`                    
	EndKey           []byte            `json:"-"`                            
	EndKeyHex        string            `json:"end_key"`                      
	Role             PeerRoleType      `json:"role"`                         
	Count            int               `json:"count"`                        
	LabelConstraints []LabelConstraint `json:"label_constraints,omitempty"`  
	LocationLabels   []string          `json:"location_labels,omitempty"`    
	IsolationLevel   string            `json:"isolation_level,omitempty"`    
	Version          uint64            `json:"version,omitempty"`            
	CreateTimestamp  uint64            `json:"create_timestamp,omitempty"`   
	group            *RuleGroup         
}
func (r *Rule) String() string {
	b, _ := json.Marshal(r)
	return string(b)
}
func (r *Rule) Clone() *Rule {
	var clone Rule
	json.Unmarshal([]byte(r.String()), &clone)
	clone.StartKey = append(r.StartKey[:0:0], r.StartKey...)
	clone.EndKey = append(r.EndKey[:0:0], r.EndKey...)
	return &clone
}
func (r *Rule) Key() [2]string {
	return [2]string{r.GroupID, r.ID}
}
func (r *Rule) StoreKey() string {
	return hex.EncodeToString([]byte(r.GroupID)) + "-" + hex.EncodeToString([]byte(r.ID))
}
func (r *Rule) groupIndex() int {
	if r.group != nil {
		return r.group.Index
	}
	return 0
}
type RuleGroup struct {
	ID       string `json:"id,omitempty"`
	Index    int    `json:"index,omitempty"`
	Override bool   `json:"override,omitempty"`
}
func (g *RuleGroup) isDefault() bool {
	return g.Index == 0 && !g.Override
}
func (g *RuleGroup) String() string {
	b, _ := json.Marshal(g)
	return string(b)
}