Copyright 2017, The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE.md file.

package cmpopts

import (
	
	
	

	
	
)
SortSlices returns a Transformer option that sorts all []V. The less function must be of the form "func(T, T) bool" which is used to sort any slice with element type V that is assignable to T. The less function must be: • Deterministic: less(x, y) == less(x, y) • Irreflexive: !less(x, x) • Transitive: if !less(x, y) and !less(y, z), then !less(x, z) The less function does not have to be "total". That is, if !less(x, y) and !less(y, x) for two elements x and y, their relative order is maintained. SortSlices can be used in conjunction with EquateEmpty.
func ( interface{}) cmp.Option {
	 := reflect.ValueOf()
	if !function.IsType(.Type(), function.Less) || .IsNil() {
		panic(fmt.Sprintf("invalid less function: %T", ))
	}
	 := sliceSorter{.Type().In(0), }
	return cmp.FilterValues(.filter, cmp.Transformer("cmpopts.SortSlices", .sort))
}

type sliceSorter struct {
	in  reflect.Type  // T
	fnc reflect.Value // func(T, T) bool
}

func ( sliceSorter) (,  interface{}) bool {
	,  := reflect.ValueOf(), reflect.ValueOf()
	if !( != nil &&  != nil && .Type() == .Type()) ||
		!(.Kind() == reflect.Slice && .Type().Elem().AssignableTo(.in)) ||
		(.Len() <= 1 && .Len() <= 1) {
		return false
Check whether the slices are already sorted to avoid an infinite recursion cycle applying the same transform to itself.
	 := sort.SliceIsSorted(, func(,  int) bool { return .less(, , ) })
	 := sort.SliceIsSorted(, func(,  int) bool { return .less(, , ) })
	return ! || !
}
func ( sliceSorter) ( interface{}) interface{} {
	 := reflect.ValueOf()
	 := reflect.MakeSlice(.Type(), .Len(), .Len())
	for  := 0;  < .Len(); ++ {
		.Index().Set(.Index())
	}
	sort.SliceStable(.Interface(), func(,  int) bool { return .less(, , ) })
	.checkSort()
	return .Interface()
}
func ( sliceSorter) ( reflect.Value) {
	 := -1 // Start of a sequence of equal elements.
	for  := 1;  < .Len(); ++ {
Check that first and last elements in v[start:i] are equal.
			if  >= 0 && (.less(, , -1) || .less(, -1, )) {
				panic(fmt.Sprintf("incomparable values detected: want equal elements: %v", .Slice(, )))
			}
			 = -1
		} else if  == -1 {
			 = 
		}
	}
}
func ( sliceSorter) ( reflect.Value, ,  int) bool {
	,  := .Index(), .Index()
	return .fnc.Call([]reflect.Value{, })[0].Bool()
}
SortMaps returns a Transformer option that flattens map[K]V types to be a sorted []struct{K, V}. The less function must be of the form "func(T, T) bool" which is used to sort any map with key K that is assignable to T. Flattening the map into a slice has the property that cmp.Equal is able to use Comparers on K or the K.Equal method if it exists. The less function must be: • Deterministic: less(x, y) == less(x, y) • Irreflexive: !less(x, x) • Transitive: if !less(x, y) and !less(y, z), then !less(x, z) • Total: if x != y, then either less(x, y) or less(y, x) SortMaps can be used in conjunction with EquateEmpty.
func ( interface{}) cmp.Option {
	 := reflect.ValueOf()
	if !function.IsType(.Type(), function.Less) || .IsNil() {
		panic(fmt.Sprintf("invalid less function: %T", ))
	}
	 := mapSorter{.Type().In(0), }
	return cmp.FilterValues(.filter, cmp.Transformer("cmpopts.SortMaps", .sort))
}

type mapSorter struct {
	in  reflect.Type  // T
	fnc reflect.Value // func(T, T) bool
}

func ( mapSorter) (,  interface{}) bool {
	,  := reflect.ValueOf(), reflect.ValueOf()
	return ( != nil &&  != nil && .Type() == .Type()) &&
		(.Kind() == reflect.Map && .Type().Key().AssignableTo(.in)) &&
		(.Len() != 0 || .Len() != 0)
}
func ( mapSorter) ( interface{}) interface{} {
	 := reflect.ValueOf()
	 := reflect.StructOf([]reflect.StructField{
		{Name: "K", Type: .Type().Key()},
		{Name: "V", Type: .Type().Elem()},
	})
	 := reflect.MakeSlice(reflect.SliceOf(), .Len(), .Len())
	for ,  := range .MapKeys() {
		 := reflect.New().Elem()
		.Field(0).Set()
		.Field(1).Set(.MapIndex())
		.Index().Set()
	}
	sort.Slice(.Interface(), func(,  int) bool { return .less(, , ) })
	.checkSort()
	return .Interface()
}
func ( mapSorter) ( reflect.Value) {
	for  := 1;  < .Len(); ++ {
		if !.less(, -1, ) {
			panic(fmt.Sprintf("partial order detected: want %v < %v", .Index(-1), .Index()))
		}
	}
}
func ( mapSorter) ( reflect.Value, ,  int) bool {
	,  := .Index().Field(0), .Index().Field(0)
	return .fnc.Call([]reflect.Value{, })[0].Bool()