mirror of
https://github.com/metabarcoding/obitools4.git
synced 2026-06-24 01:31:00 +00:00
fix(obiutils): correctly unwrap interface values in min/max
Introduces an `unwrapInterface` reflection helper to dereference `interface{}`-wrapped values before type validation. Updates slice and map iteration loops in min/max functions to apply this helper, ensuring `isOrderedKind` accurately identifies underlying concrete types instead of incorrectly rejecting `reflect.Interface` elements.
This commit is contained in:
+18
-8
@@ -309,7 +309,7 @@ func saturatingSubValues(a, b reflect.Value) (reflect.Value, error) {
|
|||||||
func maxFromIterable(v reflect.Value) (interface{}, error) {
|
func maxFromIterable(v reflect.Value) (interface{}, error) {
|
||||||
var best reflect.Value
|
var best reflect.Value
|
||||||
for i := 0; i < v.Len(); i++ {
|
for i := 0; i < v.Len(); i++ {
|
||||||
elem := v.Index(i)
|
elem := unwrapInterface(v.Index(i))
|
||||||
if !isOrderedKind(elem.Kind()) {
|
if !isOrderedKind(elem.Kind()) {
|
||||||
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
||||||
}
|
}
|
||||||
@@ -324,7 +324,7 @@ func maxFromIterable(v reflect.Value) (interface{}, error) {
|
|||||||
func minFromIterable(v reflect.Value) (interface{}, error) {
|
func minFromIterable(v reflect.Value) (interface{}, error) {
|
||||||
var minVal reflect.Value
|
var minVal reflect.Value
|
||||||
for i := 0; i < v.Len(); i++ {
|
for i := 0; i < v.Len(); i++ {
|
||||||
elem := v.Index(i)
|
elem := unwrapInterface(v.Index(i))
|
||||||
if !isOrderedKind(elem.Kind()) {
|
if !isOrderedKind(elem.Kind()) {
|
||||||
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
||||||
}
|
}
|
||||||
@@ -339,7 +339,7 @@ func filterMinFromIterable(v reflect.Value, minimum interface{}) (interface{}, e
|
|||||||
minVal := reflect.ValueOf(minimum)
|
minVal := reflect.ValueOf(minimum)
|
||||||
result := reflect.MakeSlice(v.Type(), 0, v.Len())
|
result := reflect.MakeSlice(v.Type(), 0, v.Len())
|
||||||
for i := 0; i < v.Len(); i++ {
|
for i := 0; i < v.Len(); i++ {
|
||||||
elem := v.Index(i)
|
elem := unwrapInterface(v.Index(i))
|
||||||
if !isOrderedKind(elem.Kind()) {
|
if !isOrderedKind(elem.Kind()) {
|
||||||
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
||||||
}
|
}
|
||||||
@@ -354,7 +354,7 @@ func filterMaxFromIterable(v reflect.Value, maximum interface{}) (interface{}, e
|
|||||||
maxVal := reflect.ValueOf(maximum)
|
maxVal := reflect.ValueOf(maximum)
|
||||||
result := reflect.MakeSlice(v.Type(), 0, v.Len())
|
result := reflect.MakeSlice(v.Type(), 0, v.Len())
|
||||||
for i := 0; i < v.Len(); i++ {
|
for i := 0; i < v.Len(); i++ {
|
||||||
elem := v.Index(i)
|
elem := unwrapInterface(v.Index(i))
|
||||||
if !isOrderedKind(elem.Kind()) {
|
if !isOrderedKind(elem.Kind()) {
|
||||||
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
||||||
}
|
}
|
||||||
@@ -369,7 +369,7 @@ func filterMinFromMap(v reflect.Value, minimum interface{}) (interface{}, error)
|
|||||||
minVal := reflect.ValueOf(minimum)
|
minVal := reflect.ValueOf(minimum)
|
||||||
result := reflect.MakeMap(v.Type())
|
result := reflect.MakeMap(v.Type())
|
||||||
for _, key := range v.MapKeys() {
|
for _, key := range v.MapKeys() {
|
||||||
elem := v.MapIndex(key)
|
elem := unwrapInterface(v.MapIndex(key))
|
||||||
if !isOrderedKind(elem.Kind()) {
|
if !isOrderedKind(elem.Kind()) {
|
||||||
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
||||||
}
|
}
|
||||||
@@ -384,7 +384,7 @@ func filterMaxFromMap(v reflect.Value, maximum interface{}) (interface{}, error)
|
|||||||
maxVal := reflect.ValueOf(maximum)
|
maxVal := reflect.ValueOf(maximum)
|
||||||
result := reflect.MakeMap(v.Type())
|
result := reflect.MakeMap(v.Type())
|
||||||
for _, key := range v.MapKeys() {
|
for _, key := range v.MapKeys() {
|
||||||
elem := v.MapIndex(key)
|
elem := unwrapInterface(v.MapIndex(key))
|
||||||
if !isOrderedKind(elem.Kind()) {
|
if !isOrderedKind(elem.Kind()) {
|
||||||
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
||||||
}
|
}
|
||||||
@@ -400,7 +400,7 @@ func maxFromMap(v reflect.Value) (interface{}, error) {
|
|||||||
var best reflect.Value
|
var best reflect.Value
|
||||||
first := true
|
first := true
|
||||||
for _, key := range v.MapKeys() {
|
for _, key := range v.MapKeys() {
|
||||||
elem := v.MapIndex(key)
|
elem := unwrapInterface(v.MapIndex(key))
|
||||||
if !isOrderedKind(elem.Kind()) {
|
if !isOrderedKind(elem.Kind()) {
|
||||||
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
||||||
}
|
}
|
||||||
@@ -417,7 +417,7 @@ func minFromMap(v reflect.Value) (interface{}, error) {
|
|||||||
var minVal reflect.Value
|
var minVal reflect.Value
|
||||||
first := true
|
first := true
|
||||||
for _, key := range v.MapKeys() {
|
for _, key := range v.MapKeys() {
|
||||||
elem := v.MapIndex(key)
|
elem := unwrapInterface(v.MapIndex(key))
|
||||||
if !isOrderedKind(elem.Kind()) {
|
if !isOrderedKind(elem.Kind()) {
|
||||||
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
||||||
}
|
}
|
||||||
@@ -440,6 +440,16 @@ func isNumericKind(k reflect.Kind) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unwrapInterface returns v.Elem() when v holds an interface value, otherwise v unchanged.
|
||||||
|
// This is necessary when iterating map[string]interface{} or []interface{} via reflection:
|
||||||
|
// the element Kind is reflect.Interface, not the underlying concrete type.
|
||||||
|
func unwrapInterface(v reflect.Value) reflect.Value {
|
||||||
|
if v.Kind() == reflect.Interface {
|
||||||
|
return v.Elem()
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
// isOrderedKind reports whether k supports comparison ordering.
|
// isOrderedKind reports whether k supports comparison ordering.
|
||||||
func isOrderedKind(k reflect.Kind) bool {
|
func isOrderedKind(k reflect.Kind) bool {
|
||||||
switch k {
|
switch k {
|
||||||
|
|||||||
Reference in New Issue
Block a user