status-go/edn/malli.go

78 lines
1.6 KiB
Go
Raw Permalink Normal View History

2024-10-02 15:13:49 +00:00
package edn
import (
"fmt"
"reflect"
"regexp"
"strings"
)
var primitiveGoTypeToMalli = map[string]string{
"bool": ":boolean",
"string": ":string",
"float64": ":double",
"int": ":int",
"int32": ":int",
"uint8": ":int",
"uint32": ":int",
"uint64": ":int",
}
func convertCamelToKebab(input string) string {
re := regexp.MustCompile("([a-z])([A-Z])")
kebab := re.ReplaceAllString(input, "${1}-${2}")
return strings.ToLower(kebab)
}
func handleType(fieldType reflect.Type) any {
kind := fieldType.Kind()
if kind == reflect.Interface {
return ":any"
}
if kind == reflect.Struct {
return ConvertStructToMalli(fieldType)
}
if kind == reflect.Slice {
elemType := fieldType.Elem()
// Handle the type that the pointer points to.
if elemType.Kind() == reflect.Ptr {
return []any{handleType(elemType.Elem())}
}
return []any{handleType(elemType)}
}
return primitiveGoTypeToMalli[kind.String()]
}
func ConvertStructToMalli(typ reflect.Type) map[string]any {
if typ.Kind() == reflect.Ptr {
typ = typ.Elem() // Dereference if it's a pointer to a struct type
}
if typ.Kind() != reflect.Struct {
panic("ConvertStructToMalli expects a struct type or pointer to a struct type")
}
malliSchema := make(map[string]any)
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
fmt.Println(field)
if !field.IsExported() {
continue
}
kebabFieldName := convertCamelToKebab(field.Name)
if field.Type.Kind() == reflect.Ptr {
malliSchema[kebabFieldName] = handleType(field.Type.Elem())
} else {
malliSchema[kebabFieldName] = handleType(field.Type)
}
}
return malliSchema
}