|
@@ -20,12 +20,12 @@ type Map map[string]reflect.Kind
|
|
|
type Astruct struct {
|
|
|
// Options
|
|
|
|
|
|
- Use32Bit bool // Defaults to false, using 64-bit int and 64-bit float, when true, uses 32-bit variants of int and float
|
|
|
- UseAny bool // Defaults to true, when false the key word any will be replaced with interface{} (unless UseInterface is false, in which error is thrown)
|
|
|
- UseInterface bool // Defaults to true, when astruct isn't able to determine a type (being an array with multiple types) it will fallback to interface{} (unless UseAny is true in which any is used)
|
|
|
- VerboseLogging bool // Dump verbose info into logs (User must setup log first!)
|
|
|
- AssumeStruct bool // Even if a type could be a map it will make a structure for it instead, default false (instead it will try to use a map unless varying types detected)
|
|
|
- PrefixStructName string // If not an empty "" string, Structures will be prefixed (for cases where you're going to have a single file produced with various structures from astruct, helps prevent name collisions, which would normally error out)
|
|
|
+ Use32Bit bool // Defaults to false, using 64-bit int and 64-bit float, when true, uses 32-bit variants of int and float
|
|
|
+ UseAny bool // Defaults to true, when true the key word any (which is an alias to interface{}) will be used, when false an error will be thrown (this only applies to arrays/slices who have varying types)
|
|
|
+ VerboseLogging bool // Dump verbose info into logs (User must setup log first!)
|
|
|
+ AssumeStruct bool // Defaults to true, when true instead of a map of a basic type a structure will be made (even if the type matches), while false a map could be used in places where the type matches
|
|
|
+ PrefixStructName string // If not an empty "" string, Structures will be prefixed (for cases where you're going to have a single file produced with various structures from astruct, helps prevent name collisions, which would normally error out)
|
|
|
+ SuffixForArrayLikes string // If not empty "" string, and it's an array this suffix is added (default's to "Item")
|
|
|
|
|
|
// In-Memory Data (This data is gathered to form final products)
|
|
|
// Almost all of these will be key being field name for in a structure (if one needs to be built) and value of reflect.Kind to determine:
|
|
@@ -42,10 +42,10 @@ type Astruct struct {
|
|
|
func (A *Astruct) Defaults() {
|
|
|
A.Use32Bit = false
|
|
|
A.UseAny = true
|
|
|
- A.UseInterface = true
|
|
|
A.VerboseLogging = false
|
|
|
- A.AssumeStruct = false
|
|
|
+ A.AssumeStruct = true
|
|
|
A.PrefixStructName = ""
|
|
|
+ A.SuffixForArrayLikes = "Item"
|
|
|
A.Init()
|
|
|
}
|
|
|
|
|
@@ -128,8 +128,20 @@ func (A *Astruct) parse(at any, name string) error {
|
|
|
A.MapLikes[name][k] = reflect.TypeOf(v).Kind()
|
|
|
}
|
|
|
}
|
|
|
- } else {
|
|
|
- A.MapLikes[name]["all"] = reflect.TypeOf(m[maps.Keys(m)[0]]).Kind()
|
|
|
+ } else { // We'll use a empty string "", to indicate this map is same type
|
|
|
+ A.MapLikes[name][""] = reflect.TypeOf(m[maps.Keys(m)[0]]).Kind()
|
|
|
+ for k, v := range m {
|
|
|
+ if reflect.TypeOf(v).Kind() == reflect.Float32 || reflect.TypeOf(v).Kind() == reflect.Float64 {
|
|
|
+ f := v.(float64)
|
|
|
+ if IsInt(f) {
|
|
|
+ A.MapLikes[name][k] = reflect.Int64
|
|
|
+ } else {
|
|
|
+ A.MapLikes[name][k] = reflect.Float64
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ A.MapLikes[name][k] = reflect.TypeOf(v).Kind()
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
case reflect.Array, reflect.Slice:
|
|
|
a := at.([]any)
|
|
@@ -147,14 +159,14 @@ func (A *Astruct) parse(at any, name string) error {
|
|
|
switch reflect.TypeOf(v).Kind() {
|
|
|
case reflect.Map:
|
|
|
A.Depth += 1
|
|
|
- err := A.parse(v, fmt.Sprint(i))
|
|
|
+ err := A.parse(v, A.SuffixForArrayLikes)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
A.Depth -= 1
|
|
|
case reflect.Array, reflect.Slice:
|
|
|
A.Depth += 1
|
|
|
- err := A.parse(v, fmt.Sprint(i))
|
|
|
+ err := A.parse(v, A.SuffixForArrayLikes)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
@@ -296,21 +308,25 @@ func (A *Astruct) WriteFile(filename, packageName string, permissions os.FileMod
|
|
|
//var slices_to_structs []string = []string{}
|
|
|
var seen []string = []string{}
|
|
|
for name, m := range A.MapLikes {
|
|
|
- if name == "all" { // Ignore the root node for now
|
|
|
+ /*if name == "" { // Ignore the root node for now
|
|
|
continue
|
|
|
- }
|
|
|
+ }*/
|
|
|
if slices.Contains(seen, name) {
|
|
|
continue
|
|
|
}
|
|
|
- if !A.AssumeStruct || !SameType(m) {
|
|
|
+ _, sameType := m[""] // Check if the empty string exists in this map (if it does it contains same typed data)
|
|
|
+ if !A.AssumeStruct || !sameType {
|
|
|
fh.WriteString(fmt.Sprintf("type %s%s struct {\n", A.PrefixStructName, CamelCase(name)))
|
|
|
for k, v := range m {
|
|
|
if slices.Contains(maps.Keys(A.MapLikes), k) {
|
|
|
- if SameType(A.MapLikes[k]) {
|
|
|
- fh.WriteString(fmt.Sprintf("\t%s map[string]%s\n", CamelCase(k), A.MapLikes[k]["all"].String()))
|
|
|
+ _, sameType2 := A.MapLikes[k][""]
|
|
|
+ if sameType2 && !A.AssumeStruct {
|
|
|
+ fh.WriteString(fmt.Sprintf("\t%s map[string]%s\n", CamelCase(k), A.MapLikes[k][""].String()))
|
|
|
seen = append(seen, k)
|
|
|
- } else {
|
|
|
+ } else if !sameType2 || A.AssumeStruct && v == reflect.Map {
|
|
|
fh.WriteString(fmt.Sprintf("\t%s %s%s\n", CamelCase(k), A.PrefixStructName, CamelCase(k)))
|
|
|
+ } else if !sameType2 || A.AssumeStruct && v != reflect.Map {
|
|
|
+ fh.WriteString(fmt.Sprintf("\t%s %s\n", CamelCase(k), v.String()))
|
|
|
}
|
|
|
} else {
|
|
|
if slices.Contains(maps.Keys(A.ArrayLikes), k) {
|
|
@@ -322,21 +338,16 @@ func (A *Astruct) WriteFile(filename, packageName string, permissions os.FileMod
|
|
|
} else if a[0] == reflect.Int64 && A.Use32Bit {
|
|
|
fh.WriteString(fmt.Sprintf("\t%s []int32\n", CamelCase(k)))
|
|
|
continue
|
|
|
- } else if a[0] == reflect.Map && A.AssumeStruct {
|
|
|
- fh.WriteString(fmt.Sprintf("\t%s []%s\n", CamelCase(k), CamelCase(k)))
|
|
|
- continue
|
|
|
- } else if a[0] == reflect.Map && !A.AssumeStruct {
|
|
|
- fh.WriteString(fmt.Sprintf("\t%s []%s%d\n", CamelCase(k), CamelCase(k), 0))
|
|
|
+ } else if a[0] == reflect.Map {
|
|
|
+ fh.WriteString(fmt.Sprintf("\t%s []%s%s\n", CamelCase(k), CamelCase(k), A.SuffixForArrayLikes))
|
|
|
continue
|
|
|
}
|
|
|
fh.WriteString(fmt.Sprintf("\t%s []%s\n", CamelCase(k), a[0]))
|
|
|
} else {
|
|
|
//fh.WriteString(fmt.Sprintf("\t%s []%s\n", CamelCase(k), CamelCase(k)))
|
|
|
//slices_to_structs = append(slices_to_structs, k)
|
|
|
- if A.UseAny && A.UseInterface {
|
|
|
+ if A.UseAny {
|
|
|
fh.WriteString(fmt.Sprintf("\t%s []any\n", CamelCase(k)))
|
|
|
- } else if !A.UseAny && A.UseInterface {
|
|
|
- fh.WriteString(fmt.Sprintf("\t%s []interface{}\n", CamelCase(k)))
|
|
|
} else {
|
|
|
return fmt.Errorf("astruct.Astruct.WriteFile(filename='%s', packageName='%s', permissions=%d) > Field '%s' is a slice, but it contains varying types (!UseAny, !UseInterface)", filename, packageName, permissions, k)
|
|
|
}
|
|
@@ -354,6 +365,24 @@ func (A *Astruct) WriteFile(filename, packageName string, permissions os.FileMod
|
|
|
}
|
|
|
}
|
|
|
fh.WriteString("}\n\n")
|
|
|
+ } else if A.AssumeStruct && sameType {
|
|
|
+ fh.WriteString(fmt.Sprintf("type %s%s struct {\n", A.PrefixStructName, CamelCase(name)))
|
|
|
+ t := m[""]
|
|
|
+ var kind reflect.Kind
|
|
|
+ if t == reflect.Float64 && A.Use32Bit {
|
|
|
+ kind = reflect.Float32
|
|
|
+ } else if t == reflect.Int64 && A.Use32Bit {
|
|
|
+ kind = reflect.Int32
|
|
|
+ } else {
|
|
|
+ kind = t
|
|
|
+ }
|
|
|
+ for k := range m {
|
|
|
+ if k == "" {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ fh.WriteString(fmt.Sprintf("\t%s %s\n", CamelCase(k), kind))
|
|
|
+ }
|
|
|
+ fh.WriteString("}\n\n")
|
|
|
}
|
|
|
}
|
|
|
/*
|