mirror of
https://github.com/metabarcoding/obitools4.git
synced 2026-08-08 14:30:36 +00:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8841c203d | ||
|
|
f1a424343c | ||
|
|
4dae7f708d | ||
|
|
578445f38a | ||
|
|
2edb33ad08 | ||
|
|
b108d4978e | ||
|
|
e9210e28a3 | ||
|
|
13a93fce11 | ||
|
|
14064c919e | ||
|
|
1dfd68aa6d |
@@ -21,6 +21,8 @@ xx
|
|||||||
|
|
||||||
.rhistory
|
.rhistory
|
||||||
/.vscode
|
/.vscode
|
||||||
|
|
||||||
|
/benchmarck
|
||||||
/build
|
/build
|
||||||
/bugs
|
/bugs
|
||||||
autodoc
|
autodoc
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
/cache
|
||||||
|
/project.local.yml
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
# the name by which the project can be referenced within Serena
|
||||||
|
project_name: "obitools4"
|
||||||
|
|
||||||
|
|
||||||
|
# list of languages for which language servers are started; choose from:
|
||||||
|
# al angular ansible bash clojure
|
||||||
|
# cpp cpp_ccls crystal csharp csharp_omnisharp
|
||||||
|
# dart elixir elm erlang fortran
|
||||||
|
# fsharp go groovy haskell haxe
|
||||||
|
# hlsl html java json julia
|
||||||
|
# kotlin lean4 lua luau markdown
|
||||||
|
# matlab msl nix ocaml pascal
|
||||||
|
# perl php php_phpactor powershell python
|
||||||
|
# python_jedi python_ty r rego ruby
|
||||||
|
# ruby_solargraph rust scala scss solidity
|
||||||
|
# svelte swift systemverilog terraform toml
|
||||||
|
# typescript typescript_vts vue yaml zig
|
||||||
|
# (This list may be outdated. For the current list, see values of Language enum here:
|
||||||
|
# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py
|
||||||
|
# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.)
|
||||||
|
# Note:
|
||||||
|
# - For C, use cpp
|
||||||
|
# - For JavaScript, use typescript
|
||||||
|
# - For Angular projects, use angular (subsumes typescript+html; requires `npm install` in the project root)
|
||||||
|
# - For Svelte projects, use svelte (subsumes typescript/javascript for .svelte projects; requires npm)
|
||||||
|
# - For SCSS / Sass / plain CSS, use scss (some-sass-language-server handles all three)
|
||||||
|
# - For Free Pascal/Lazarus, use pascal
|
||||||
|
# Special requirements:
|
||||||
|
# Some languages require additional setup/installations.
|
||||||
|
# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers
|
||||||
|
# When using multiple languages, the first language server that supports a given file will be used for that file.
|
||||||
|
# The first language is the default language and the respective language server will be used as a fallback.
|
||||||
|
# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored.
|
||||||
|
languages:
|
||||||
|
- go
|
||||||
|
|
||||||
|
# the encoding used by text files in the project
|
||||||
|
# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings
|
||||||
|
encoding: "utf-8"
|
||||||
|
|
||||||
|
# line ending convention to use when writing source files.
|
||||||
|
# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default)
|
||||||
|
# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings.
|
||||||
|
line_ending:
|
||||||
|
|
||||||
|
# The language backend to use for this project.
|
||||||
|
# If not set, the global setting from serena_config.yml is used.
|
||||||
|
# Valid values: LSP, JetBrains
|
||||||
|
# Note: the backend is fixed at startup. If a project with a different backend
|
||||||
|
# is activated post-init, an error will be returned.
|
||||||
|
language_backend:
|
||||||
|
|
||||||
|
# whether to use project's .gitignore files to ignore files
|
||||||
|
ignore_all_files_in_gitignore: true
|
||||||
|
|
||||||
|
# advanced configuration option allowing to configure language server-specific options.
|
||||||
|
# Maps the language key to the options.
|
||||||
|
# Have a look at the docstring of the constructors of the LS implementations within solidlsp (e.g., for C# or PHP) to see which options are available.
|
||||||
|
# No documentation on options means no options are available.
|
||||||
|
ls_specific_settings: {}
|
||||||
|
|
||||||
|
# list of additional workspace folder paths for cross-package reference support (e.g. in monorepos).
|
||||||
|
# Paths can be absolute or relative to the project root.
|
||||||
|
# Each folder is registered as an LSP workspace folder, enabling language servers to discover
|
||||||
|
# symbols and references across package boundaries.
|
||||||
|
# Currently supported for: TypeScript.
|
||||||
|
# Example:
|
||||||
|
# additional_workspace_folders:
|
||||||
|
# - ../sibling-package
|
||||||
|
# - ../shared-lib
|
||||||
|
additional_workspace_folders: []
|
||||||
|
|
||||||
|
# list of additional paths to ignore in this project.
|
||||||
|
# Same syntax as gitignore, so you can use * and **.
|
||||||
|
# Note: global ignored_paths from serena_config.yml are also applied additively.
|
||||||
|
ignored_paths: []
|
||||||
|
|
||||||
|
# whether the project is in read-only mode
|
||||||
|
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
|
||||||
|
# Added on 2025-04-18
|
||||||
|
read_only: false
|
||||||
|
|
||||||
|
# list of tool names to exclude.
|
||||||
|
# This extends the existing exclusions (e.g. from the global configuration)
|
||||||
|
# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html
|
||||||
|
excluded_tools: []
|
||||||
|
|
||||||
|
# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default).
|
||||||
|
# This extends the existing inclusions (e.g. from the global configuration).
|
||||||
|
# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html
|
||||||
|
included_optional_tools: []
|
||||||
|
|
||||||
|
# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools.
|
||||||
|
# This cannot be combined with non-empty excluded_tools or included_optional_tools.
|
||||||
|
# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html
|
||||||
|
fixed_tools: []
|
||||||
|
|
||||||
|
# list of mode names that are to be activated by default, overriding the setting in the global configuration.
|
||||||
|
# The full set of modes to be activated is base_modes (from global config) + default_modes + added_modes.
|
||||||
|
# If the setting is undefined/empty, the default_modes from the global configuration (serena_config.yml) apply.
|
||||||
|
# Otherwise, this overrides the setting from the global configuration (serena_config.yml).
|
||||||
|
# Therefore, you can set this to [] if you do not want the default modes defined in the global config to apply
|
||||||
|
# for this project.
|
||||||
|
# This setting can, in turn, be overridden by CLI parameters (--mode).
|
||||||
|
# See https://oraios.github.io/serena/02-usage/050_configuration.html#modes
|
||||||
|
default_modes:
|
||||||
|
|
||||||
|
# list of mode names to be activated additionally for this project, e.g. ["query-projects"]
|
||||||
|
# The full set of modes to be activated is base_modes (from global config) + default_modes + added_modes.
|
||||||
|
# See https://oraios.github.io/serena/02-usage/050_configuration.html#modes
|
||||||
|
added_modes:
|
||||||
|
|
||||||
|
# initial prompt for the project. It will always be given to the LLM upon activating the project
|
||||||
|
# (contrary to the memories, which are loaded on demand).
|
||||||
|
initial_prompt: ""
|
||||||
|
|
||||||
|
# time budget (seconds) per tool call for the retrieval of additional symbol information
|
||||||
|
# such as docstrings or parameter information.
|
||||||
|
# This overrides the corresponding setting in the global configuration; see the documentation there.
|
||||||
|
# If null or missing, use the setting from the global configuration.
|
||||||
|
symbol_info_budget:
|
||||||
|
|
||||||
|
# list of regex patterns which, when matched, mark a memory entry as read‑only.
|
||||||
|
# Extends the list from the global configuration, merging the two lists.
|
||||||
|
read_only_memory_patterns: []
|
||||||
|
|
||||||
|
# list of regex patterns for memories to completely ignore.
|
||||||
|
# Matching memories will not appear in list_memories or activate_project output
|
||||||
|
# and cannot be accessed via read_memory or write_memory.
|
||||||
|
# To access ignored memory files, use the read_file tool on the raw file path.
|
||||||
|
# Extends the list from the global configuration, merging the two lists.
|
||||||
|
# Example: ["_archive/.*", "_episodes/.*"]
|
||||||
|
ignored_memory_patterns: []
|
||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var __obi_header_value_string_pattern__ = regexp.MustCompile(`^'\s*([^']*'|"[^"]*")\s*;`)
|
var __obi_header_value_string_pattern__ = regexp.MustCompile(`^'\s*([^']*'|"[^"]*")\s*;`)
|
||||||
var __obi_header_value_numeric_pattern__ = regexp.MustCompile(`^\s*([+-]?\.\d+|[+-]?\d+(\.\d*)?([eE][+-]?\d+)?)\s*;`)
|
var __obi_header_value_numeric_pattern__ = regexp.MustCompile(`^\s*[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?\s*;`)
|
||||||
var __obi_header_map_int_key__ = regexp.MustCompile("([{,])([0-9]+):")
|
var __obi_header_map_int_key__ = regexp.MustCompile("([{,])([0-9]+):")
|
||||||
|
|
||||||
func __match__dict__(text []byte) []int {
|
func __match__dict__(text []byte) []int {
|
||||||
@@ -347,6 +347,8 @@ func ParseOBIFeatures(text string, annotations obiseq.Annotation) string {
|
|||||||
case float64:
|
case float64:
|
||||||
if vt == math.Floor(vt) {
|
if vt == math.Floor(vt) {
|
||||||
annotations[key] = int(vt)
|
annotations[key] = int(vt)
|
||||||
|
} else {
|
||||||
|
annotations[key] = vt
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
annotations[key] = value
|
annotations[key] = value
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package obioptions
|
|||||||
// Version is automatically updated by the Makefile from version.txt
|
// Version is automatically updated by the Makefile from version.txt
|
||||||
// The patch number (third digit) is incremented on each push to the repository
|
// The patch number (third digit) is incremented on each push to the repository
|
||||||
|
|
||||||
var _Version = "Release 4.4.43"
|
var _Version = "Release 4.4.46"
|
||||||
|
|
||||||
// Version returns the version of the obitools package.
|
// Version returns the version of the obitools package.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -141,6 +141,20 @@ var OBILang = gval.NewLanguage(
|
|||||||
gval.Function("max", func(args ...interface{}) (interface{}, error) {
|
gval.Function("max", func(args ...interface{}) (interface{}, error) {
|
||||||
return obiutils.Max(args[0])
|
return obiutils.Max(args[0])
|
||||||
}),
|
}),
|
||||||
|
gval.Function("whichmax", func(args ...interface{}) (interface{}, error) {
|
||||||
|
result, err := obiutils.WhichMax(args[0])
|
||||||
|
if idx, ok := result.(int); ok {
|
||||||
|
return float64(idx), nil
|
||||||
|
}
|
||||||
|
return result, err
|
||||||
|
}),
|
||||||
|
gval.Function("whichmin", func(args ...interface{}) (interface{}, error) {
|
||||||
|
result, err := obiutils.WhichMin(args[0])
|
||||||
|
if idx, ok := result.(int); ok {
|
||||||
|
return float64(idx), nil
|
||||||
|
}
|
||||||
|
return result, err
|
||||||
|
}),
|
||||||
|
|
||||||
gval.Function("filtermin", func(args ...interface{}) (interface{}, error) {
|
gval.Function("filtermin", func(args ...interface{}) (interface{}, error) {
|
||||||
return obiutils.FilterMin(args[0], args[1])
|
return obiutils.FilterMin(args[0], args[1])
|
||||||
|
|||||||
+128
-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())
|
||||||
}
|
}
|
||||||
@@ -365,11 +365,121 @@ func filterMaxFromIterable(v reflect.Value, maximum interface{}) (interface{}, e
|
|||||||
return result.Interface(), nil
|
return result.Interface(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// whichMaxFromIterable returns the index of the maximum element in a slice/array.
|
||||||
|
func whichMaxFromIterable(v reflect.Value) (int, error) {
|
||||||
|
var best reflect.Value
|
||||||
|
bestIdx := 0
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
elem := unwrapInterface(v.Index(i))
|
||||||
|
if !isOrderedKind(elem.Kind()) {
|
||||||
|
return 0, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
||||||
|
}
|
||||||
|
if i == 0 || greater(elem, best) {
|
||||||
|
best = elem
|
||||||
|
bestIdx = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bestIdx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// whichMinFromIterable returns the index of the minimum element in a slice/array.
|
||||||
|
func whichMinFromIterable(v reflect.Value) (int, error) {
|
||||||
|
var minVal reflect.Value
|
||||||
|
minIdx := 0
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
elem := unwrapInterface(v.Index(i))
|
||||||
|
if !isOrderedKind(elem.Kind()) {
|
||||||
|
return 0, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
||||||
|
}
|
||||||
|
if i == 0 || less(elem, minVal) {
|
||||||
|
minVal = elem
|
||||||
|
minIdx = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return minIdx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// whichMaxFromMap returns the key associated with the maximum value in a map.
|
||||||
|
func whichMaxFromMap(v reflect.Value) (interface{}, error) {
|
||||||
|
var best reflect.Value
|
||||||
|
var bestKey reflect.Value
|
||||||
|
first := true
|
||||||
|
for _, key := range v.MapKeys() {
|
||||||
|
elem := unwrapInterface(v.MapIndex(key))
|
||||||
|
if !isOrderedKind(elem.Kind()) {
|
||||||
|
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
||||||
|
}
|
||||||
|
if first || greater(elem, best) {
|
||||||
|
best = elem
|
||||||
|
bestKey = key
|
||||||
|
first = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bestKey.Interface(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// whichMinFromMap returns the key associated with the minimum value in a map.
|
||||||
|
func whichMinFromMap(v reflect.Value) (interface{}, error) {
|
||||||
|
var minVal reflect.Value
|
||||||
|
var minKey reflect.Value
|
||||||
|
first := true
|
||||||
|
for _, key := range v.MapKeys() {
|
||||||
|
elem := unwrapInterface(v.MapIndex(key))
|
||||||
|
if !isOrderedKind(elem.Kind()) {
|
||||||
|
return nil, fmt.Errorf("unsupported element type: %s", elem.Kind())
|
||||||
|
}
|
||||||
|
if first || less(elem, minVal) {
|
||||||
|
minVal = elem
|
||||||
|
minKey = key
|
||||||
|
first = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return minKey.Interface(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhichMax returns the key (for a map) or index (for a slice/array) of the maximum value.
|
||||||
|
func WhichMax(data interface{}) (interface{}, error) {
|
||||||
|
v := reflect.ValueOf(data)
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
if v.Len() == 0 {
|
||||||
|
return nil, errors.New("empty slice or array")
|
||||||
|
}
|
||||||
|
return whichMaxFromIterable(v)
|
||||||
|
case reflect.Map:
|
||||||
|
if v.Len() == 0 {
|
||||||
|
return nil, errors.New("empty map")
|
||||||
|
}
|
||||||
|
return whichMaxFromMap(v)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported type: %s", v.Kind())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhichMin returns the key (for a map) or index (for a slice/array) of the minimum value.
|
||||||
|
func WhichMin(data interface{}) (interface{}, error) {
|
||||||
|
v := reflect.ValueOf(data)
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
if v.Len() == 0 {
|
||||||
|
return nil, errors.New("empty slice or array")
|
||||||
|
}
|
||||||
|
return whichMinFromIterable(v)
|
||||||
|
case reflect.Map:
|
||||||
|
if v.Len() == 0 {
|
||||||
|
return nil, errors.New("empty map")
|
||||||
|
}
|
||||||
|
return whichMinFromMap(v)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported type: %s", v.Kind())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func filterMinFromMap(v reflect.Value, minimum interface{}) (interface{}, error) {
|
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 +494,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 +510,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 +527,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 +550,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 {
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
4.4.43
|
4.4.46
|
||||||
|
|||||||
Reference in New Issue
Block a user