mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-09-16 09:36:18 +02:00
Refactor structdiff
package
This commit is contained in:
@@ -71,11 +71,7 @@ func setMetadata(ctx context.Context, key string, value any) {
|
||||
}
|
||||
|
||||
func SetMetadata(ctx context.Context, key string, value any) {
|
||||
type diffable interface {
|
||||
Diff() structdiff.Entries
|
||||
}
|
||||
|
||||
if diff, ok := value.(diffable); ok {
|
||||
if diff, ok := value.(structdiff.Diffable); ok {
|
||||
m := diff.Diff().Flatten()
|
||||
for k, v := range m {
|
||||
setMetadata(ctx, fmt.Sprintf("%s.%s", key, k), v)
|
||||
|
@@ -6,19 +6,10 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var bufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(bytes.Buffer)
|
||||
},
|
||||
}
|
||||
|
||||
var builderPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(strings.Builder)
|
||||
},
|
||||
type Diffable interface {
|
||||
Diff() Entries
|
||||
}
|
||||
|
||||
type Entry struct {
|
||||
@@ -29,11 +20,9 @@ type Entry struct {
|
||||
type Entries []Entry
|
||||
|
||||
func (d Entries) String() string {
|
||||
buf := builderPool.Get().(*strings.Builder)
|
||||
buf := new(strings.Builder)
|
||||
last := len(d) - 1
|
||||
|
||||
buf.Reset()
|
||||
|
||||
for i, e := range d {
|
||||
buf.WriteString(e.Name)
|
||||
buf.WriteString(": ")
|
||||
@@ -43,7 +32,7 @@ func (d Entries) String() string {
|
||||
buf.WriteString(dd.String())
|
||||
buf.WriteByte('}')
|
||||
} else {
|
||||
fmt.Fprint(buf, e.Value)
|
||||
fmt.Fprintf(buf, "%+v", e.Value)
|
||||
}
|
||||
|
||||
if i != last {
|
||||
@@ -55,11 +44,9 @@ func (d Entries) String() string {
|
||||
}
|
||||
|
||||
func (d Entries) MarshalJSON() ([]byte, error) {
|
||||
buf := bufPool.Get().(*bytes.Buffer)
|
||||
buf := new(bytes.Buffer)
|
||||
last := len(d) - 1
|
||||
|
||||
buf.Reset()
|
||||
|
||||
buf.WriteByte('{')
|
||||
|
||||
for i, e := range d {
|
||||
@@ -101,6 +88,45 @@ func (d Entries) Flatten() map[string]interface{} {
|
||||
return m
|
||||
}
|
||||
|
||||
func valDiff(a, b reflect.Value) (any, bool) {
|
||||
if !a.CanInterface() || !b.CanInterface() {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
typeB := b.Type()
|
||||
|
||||
if a.Type() != typeB {
|
||||
return b.Interface(), true
|
||||
}
|
||||
|
||||
intA := a.Interface()
|
||||
intB := b.Interface()
|
||||
|
||||
if reflect.DeepEqual(intA, intB) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if typeB.Kind() == reflect.Struct {
|
||||
return Diff(intA, intB), true
|
||||
}
|
||||
|
||||
if typeB.Kind() == reflect.Ptr && typeB.Elem().Kind() == reflect.Struct {
|
||||
if !a.IsNil() && !b.IsNil() {
|
||||
return Diff(intA, intB), true
|
||||
}
|
||||
|
||||
if !b.IsNil() {
|
||||
if diffable, ok := intB.(Diffable); ok {
|
||||
return diffable.Diff(), true
|
||||
}
|
||||
}
|
||||
|
||||
return nil, true
|
||||
}
|
||||
|
||||
return intB, true
|
||||
}
|
||||
|
||||
func Diff(a, b interface{}) Entries {
|
||||
valA := reflect.Indirect(reflect.ValueOf(a))
|
||||
valB := reflect.Indirect(reflect.ValueOf(b))
|
||||
@@ -115,22 +141,9 @@ func Diff(a, b interface{}) Entries {
|
||||
fieldA := valA.Field(i)
|
||||
fieldB := valB.Field(i)
|
||||
|
||||
if !fieldA.CanInterface() || !fieldB.CanInterface() {
|
||||
continue
|
||||
}
|
||||
|
||||
intA := fieldA.Interface()
|
||||
intB := fieldB.Interface()
|
||||
|
||||
if !reflect.DeepEqual(intA, intB) {
|
||||
if v, ok := valDiff(fieldA, fieldB); ok {
|
||||
name := valB.Type().Field(i).Name
|
||||
value := intB
|
||||
|
||||
if fieldB.Kind() == reflect.Struct {
|
||||
value = Diff(intA, intB)
|
||||
}
|
||||
|
||||
d = append(d, Entry{name, value})
|
||||
d = append(d, Entry{name, v})
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user