Cut over public engine construction to ConfigKit sources
This commit is contained in:
121
provider_values.go
Normal file
121
provider_values.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package promptkit
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type providerVisit struct {
|
||||
typ reflect.Type
|
||||
ptr uintptr
|
||||
}
|
||||
|
||||
type invalidProviderNumber struct{}
|
||||
|
||||
// providerMapForMapping converts JSON-shaped Go containers to ConfigKit's
|
||||
// built-in mapping containers. Unsupported values remain for Mapping to report
|
||||
// as deferred source diagnostics during construction.
|
||||
func providerMapForMapping(values map[string]any) map[string]any {
|
||||
if values == nil {
|
||||
return nil
|
||||
}
|
||||
converted := make(map[string]any, len(values))
|
||||
active := make(map[providerVisit]bool)
|
||||
for key, value := range values {
|
||||
converted[key] = providerValueForMapping(reflect.ValueOf(value), active, 0)
|
||||
}
|
||||
return converted
|
||||
}
|
||||
|
||||
func providerValueForMapping(value reflect.Value, active map[providerVisit]bool, depth int) any {
|
||||
if !value.IsValid() {
|
||||
return nil
|
||||
}
|
||||
if depth > 100 {
|
||||
return value.Interface()
|
||||
}
|
||||
for value.Kind() == reflect.Interface || value.Kind() == reflect.Pointer {
|
||||
if value.IsNil() {
|
||||
return nil
|
||||
}
|
||||
if value.Kind() == reflect.Pointer {
|
||||
visit := providerVisit{typ: value.Type(), ptr: value.Pointer()}
|
||||
if active[visit] {
|
||||
return value.Interface()
|
||||
}
|
||||
active[visit] = true
|
||||
defer delete(active, visit)
|
||||
}
|
||||
value = value.Elem()
|
||||
}
|
||||
if value.CanInterface() {
|
||||
if number, ok := value.Interface().(json.Number); ok {
|
||||
if _, err := json.Marshal(number); err != nil {
|
||||
return invalidProviderNumber{}
|
||||
}
|
||||
if integer, err := strconv.ParseInt(string(number), 10, 64); err == nil {
|
||||
return integer
|
||||
}
|
||||
if integer, err := strconv.ParseUint(string(number), 10, 64); err == nil {
|
||||
return integer
|
||||
}
|
||||
if decimal, err := strconv.ParseFloat(string(number), 64); err == nil {
|
||||
return decimal
|
||||
}
|
||||
return number
|
||||
}
|
||||
}
|
||||
switch value.Kind() {
|
||||
case reflect.Map:
|
||||
if value.IsNil() {
|
||||
return nil
|
||||
}
|
||||
if value.Type().Key().Kind() != reflect.String {
|
||||
return value.Interface()
|
||||
}
|
||||
visit := providerVisit{typ: value.Type(), ptr: value.Pointer()}
|
||||
if active[visit] {
|
||||
return value.Interface()
|
||||
}
|
||||
active[visit] = true
|
||||
defer delete(active, visit)
|
||||
converted := make(map[string]any, value.Len())
|
||||
iter := value.MapRange()
|
||||
for iter.Next() {
|
||||
converted[iter.Key().String()] = providerValueForMapping(iter.Value(), active, depth+1)
|
||||
}
|
||||
return converted
|
||||
case reflect.Slice, reflect.Array:
|
||||
if value.Kind() == reflect.Slice {
|
||||
if value.IsNil() {
|
||||
return nil
|
||||
}
|
||||
visit := providerVisit{typ: value.Type(), ptr: value.Pointer()}
|
||||
if visit.ptr != 0 {
|
||||
if active[visit] {
|
||||
return value.Interface()
|
||||
}
|
||||
active[visit] = true
|
||||
defer delete(active, visit)
|
||||
}
|
||||
}
|
||||
converted := make([]any, value.Len())
|
||||
for index := range converted {
|
||||
converted[index] = providerValueForMapping(value.Index(index), active, depth+1)
|
||||
}
|
||||
return converted
|
||||
case reflect.String:
|
||||
return value.String()
|
||||
case reflect.Bool:
|
||||
return value.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return value.Int()
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return value.Uint()
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return value.Float()
|
||||
default:
|
||||
return value.Interface()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user