Chromium Code Reviews| Index: render/render.go |
| diff --git a/render/render.go b/render/render.go |
| index bdb307ce9d49be5f2662606dbe61c7e6485edea8..e9287396ca5178d6a9b7dd88d91c60126cead6ed 100644 |
| --- a/render/render.go |
| +++ b/render/render.go |
| @@ -330,40 +330,147 @@ func writeType(buf *bytes.Buffer, ptrs int, t reflect.Type) { |
| } |
| } |
| +type cmpFn func(a, b reflect.Value) int |
| + |
| type sortableValueSlice struct { |
| - kind reflect.Kind |
| + cmp cmpFn |
| elements []reflect.Value |
| } |
| -func (s *sortableValueSlice) Len() int { |
| +func (s sortableValueSlice) Len() int { |
| return len(s.elements) |
| } |
| -func (s *sortableValueSlice) Less(i, j int) bool { |
| - switch s.kind { |
| +func (s sortableValueSlice) Less(i, j int) bool { |
| + return s.cmp(s.elements[i], s.elements[j]) < 0 |
| +} |
| + |
| +func (s sortableValueSlice) Swap(i, j int) { |
| + s.elements[i], s.elements[j] = s.elements[j], s.elements[i] |
| +} |
| + |
| +func cmpForType(t reflect.Type) cmpFn { |
|
dnj
2016/02/19 19:31:10
nit: document that this specifically aims to opera
iannucci
2016/02/19 21:18:28
Done.
|
| + switch t.Kind() { |
| case reflect.String: |
| - return s.elements[i].String() < s.elements[j].String() |
| + return func(av, bv reflect.Value) int { |
| + a, b := av.String(), bv.String() |
| + if a < b { |
| + return -1 |
| + } else if a > b { |
| + return 1 |
| + } |
| + return 0 |
| + } |
| - case reflect.Int: |
| - return s.elements[i].Int() < s.elements[j].Int() |
| + case reflect.Bool: |
| + return func(av, bv reflect.Value) int { |
| + a, b := av.Bool(), bv.Bool() |
| + if !a && b { |
| + return -1 |
| + } else if a && !b { |
| + return 1 |
| + } |
| + return 0 |
| + } |
| - default: |
| - panic(fmt.Errorf("unsupported sort kind: %s", s.kind)) |
| + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: |
| + return func(av, bv reflect.Value) int { |
| + a, b := av.Int(), bv.Int() |
| + if a < b { |
| + return -1 |
| + } else if a > b { |
| + return 1 |
| + } |
| + return 0 |
| + } |
| + |
| + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, |
| + reflect.Uint64, reflect.Uintptr, reflect.UnsafePointer: |
| + return func(av, bv reflect.Value) int { |
| + a, b := av.Uint(), bv.Uint() |
| + if a < b { |
| + return -1 |
| + } else if a > b { |
| + return 1 |
| + } |
| + return 0 |
| + } |
| + |
| + case reflect.Float32, reflect.Float64: |
| + return func(av, bv reflect.Value) int { |
| + a, b := av.Float(), bv.Float() |
| + if a < b { |
| + return -1 |
| + } else if a > b { |
| + return 1 |
| + } |
| + return 0 |
| + } |
| + |
| + case reflect.Interface: |
| + return func(av, bv reflect.Value) int { |
| + a, b := av.InterfaceData(), bv.InterfaceData() |
| + if a[0] < b[0] { |
| + return -1 |
| + } else if a[0] > b[0] { |
| + return 1 |
| + } |
| + if a[1] < b[1] { |
| + return -1 |
| + } else if a[1] > b[1] { |
| + return 1 |
| + } |
| + return 0 |
| + } |
| + |
| + case reflect.Complex64, reflect.Complex128: |
| + return func(av, bv reflect.Value) int { |
| + a, b := av.Complex(), bv.Complex() |
| + if real(a) < real(b) { |
| + return -1 |
| + } else if real(a) > real(b) { |
| + return 1 |
| + } |
| + if imag(a) < imag(b) { |
| + return -1 |
| + } else if imag(a) > imag(b) { |
| + return 1 |
| + } |
| + return 0 |
| + } |
| + |
| + case reflect.Ptr, reflect.Chan: |
| + return func(av, bv reflect.Value) int { |
| + a, b := av.Pointer(), bv.Pointer() |
| + if a < b { |
| + return -1 |
| + } else if a > b { |
| + return 1 |
| + } |
| + return 0 |
| + } |
| + |
| + case reflect.Struct: |
| + cmpLst := make([]cmpFn, t.NumField()) |
| + for i := range cmpLst { |
| + cmpLst[i] = cmpForType(t.Field(i).Type) |
| + } |
| + return func(a, b reflect.Value) int { |
| + for i, cmp := range cmpLst { |
| + rslt := cmp(a.Field(i), b.Field(i)) |
|
dnj
2016/02/19 19:31:10
nit: if rstl := cmp(); rstl != 0 { ... }
iannucci
2016/02/19 21:18:28
Done.
|
| + if rslt != 0 { |
| + return rslt |
| + } |
| + } |
| + return 0 |
| + } |
| } |
| -} |
| -func (s *sortableValueSlice) Swap(i, j int) { |
| - s.elements[i], s.elements[j] = s.elements[j], s.elements[i] |
| + return nil |
| } |
| func tryAndSortMapKeys(mt reflect.Type, k []reflect.Value) { |
| - // Try our stock sortable values. |
| - switch mt.Key().Kind() { |
| - case reflect.String, reflect.Int: |
| - vs := &sortableValueSlice{ |
| - kind: mt.Key().Kind(), |
| - elements: k, |
| - } |
| - sort.Sort(vs) |
| + if cmp := cmpForType(mt.Key()); cmp != nil { |
| + sort.Sort(sortableValueSlice{cmp, k}) |
| } |
| } |