2023-02-07 21:29:26 +00:00
|
|
|
package docs
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
|
2023-11-10 20:36:15 +00:00
|
|
|
"git.sr.ht/~ashkeel/strimertul/docs/interfaces"
|
2023-02-07 21:29:26 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type DataObject struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
Description string `json:"description,omitempty"`
|
|
|
|
Kind Kind `json:"kind"`
|
|
|
|
Keys []DataObject `json:"keys,omitempty"`
|
|
|
|
Key *DataObject `json:"key,omitempty"`
|
|
|
|
Element *DataObject `json:"element,omitempty"`
|
|
|
|
EnumValues []string `json:"enumValues,omitempty"`
|
2023-02-18 12:33:36 +00:00
|
|
|
IsPointer bool `json:"isPointer,omitempty"`
|
2023-02-07 21:29:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type KeyObject struct {
|
|
|
|
Description string `json:"description"`
|
|
|
|
Schema DataObject `json:"schema"`
|
|
|
|
Tags []interfaces.KeyTag `json:"tags,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type Kind string
|
|
|
|
|
|
|
|
const (
|
|
|
|
KindString Kind = "string"
|
|
|
|
KindInt Kind = "int"
|
|
|
|
KindFloat Kind = "float"
|
|
|
|
KindStruct Kind = "object"
|
|
|
|
KindBoolean Kind = "boolean"
|
|
|
|
KindEnum Kind = "enum"
|
|
|
|
KindUnknown Kind = "unknown"
|
|
|
|
KindArray Kind = "array"
|
|
|
|
KindDict Kind = "dictionary"
|
2023-02-18 12:33:36 +00:00
|
|
|
KindDate Kind = "datetime"
|
2023-02-07 21:29:26 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func getKind(typ reflect.Kind) Kind {
|
|
|
|
switch typ {
|
2023-02-18 12:33:36 +00:00
|
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
2023-02-07 21:29:26 +00:00
|
|
|
return KindInt
|
|
|
|
case reflect.Float32, reflect.Float64:
|
|
|
|
return KindFloat
|
|
|
|
case reflect.String:
|
|
|
|
return KindString
|
|
|
|
case reflect.Bool:
|
|
|
|
return KindBoolean
|
|
|
|
case reflect.Struct:
|
|
|
|
return KindStruct
|
|
|
|
case reflect.Map:
|
|
|
|
return KindDict
|
|
|
|
case reflect.Array, reflect.Slice:
|
|
|
|
return KindArray
|
|
|
|
}
|
|
|
|
return KindUnknown
|
|
|
|
}
|
|
|
|
|
|
|
|
func parseType(typ reflect.Type) (out DataObject) {
|
|
|
|
out.Name = typ.Name()
|
2023-02-18 12:33:36 +00:00
|
|
|
|
|
|
|
// Check for common complex types
|
|
|
|
switch typ.String() {
|
|
|
|
case "time.Time":
|
|
|
|
out.Kind = KindDate
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for known enums
|
2023-02-07 21:29:26 +00:00
|
|
|
if enum, ok := Enums[out.Name]; ok {
|
|
|
|
out.Kind = KindEnum
|
|
|
|
for _, it := range enum.Values {
|
|
|
|
out.EnumValues = append(out.EnumValues, fmt.Sprint(it))
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2023-02-18 12:33:36 +00:00
|
|
|
|
|
|
|
// Dereference pointers
|
|
|
|
for typ.Kind() == reflect.Pointer {
|
|
|
|
out.IsPointer = true
|
|
|
|
typ = typ.Elem()
|
|
|
|
}
|
|
|
|
|
2023-02-07 21:29:26 +00:00
|
|
|
out.Kind = getKind(typ.Kind())
|
2023-05-04 13:14:21 +00:00
|
|
|
|
|
|
|
switch out.Kind {
|
|
|
|
case KindStruct:
|
|
|
|
out.Keys = parseStruct(typ)
|
|
|
|
case KindArray, KindDict:
|
2023-02-07 21:29:26 +00:00
|
|
|
elem := parseType(typ.Elem())
|
|
|
|
out.Element = &elem
|
|
|
|
if out.Kind == KindDict {
|
|
|
|
key := parseType(typ.Key())
|
|
|
|
out.Key = &key
|
|
|
|
}
|
|
|
|
}
|
2023-05-04 13:14:21 +00:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func parseStruct(typ reflect.Type) (out []DataObject) {
|
|
|
|
for index := 0; index < typ.NumField(); index++ {
|
|
|
|
field := typ.Field(index)
|
|
|
|
obj := parseType(field.Type)
|
|
|
|
if jsonName, ok := field.Tag.Lookup("json"); ok {
|
|
|
|
parts := strings.SplitN(jsonName, ",", 2)
|
|
|
|
obj.Name = parts[0]
|
|
|
|
} else {
|
|
|
|
obj.Name = field.Name
|
2023-02-07 21:29:26 +00:00
|
|
|
}
|
2023-05-04 13:14:21 +00:00
|
|
|
obj.Description = field.Tag.Get("desc")
|
|
|
|
out = append(out, obj)
|
2023-02-07 21:29:26 +00:00
|
|
|
}
|
2023-05-04 13:14:21 +00:00
|
|
|
return out
|
2023-02-07 21:29:26 +00:00
|
|
|
}
|