Saving Arbitrary Structs

Now for loading them
This commit is contained in:
Brian Buller 2023-06-08 09:52:03 -05:00
parent 7c152f1273
commit ac4d008f57
3 changed files with 66 additions and 34 deletions

View File

@ -8,25 +8,44 @@ import (
type any interface{} type any interface{}
func (b *DB) LoadStruct(path []string, dest any) error { func (b *DB) Load(path []string, dest any) error {
destValue := reflect.ValueOf(dest) destValue := reflect.ValueOf(dest)
if destValue.Kind().String() != "ptr" { fmt.Println("Loading:", path, destValue)
if destValue.Kind() != reflect.Pointer {
return errors.New("Destination must be a pointer") return errors.New("Destination must be a pointer")
} }
d := reflect.Indirect(destValue) d := reflect.Indirect(destValue)
if d.Kind().String() != "struct" { if d.Kind() != reflect.Struct {
path, name := path[:len(path)-1], path[len(path)-1] path, name := path[:len(path)-1], path[len(path)-1]
return b.GetForInterface(path, name, dest) return b.GetForInterface(path, name, dest)
} }
entityType := reflect.TypeOf(dest).Elem() entityType := reflect.TypeOf(dest).Elem()
fmt.Println("EntityType:", entityType.String())
var ret error var ret error
for i := 0; i < entityType.NumField(); i++ { for i := 0; i < entityType.NumField(); i++ {
structFld := entityType.Field(i) structFld := entityType.Field(i)
fldName := FieldName(structFld) fldName := FieldName(structFld)
fmt.Printf("Field (%d): %s (%s)\n", i, fldName, structFld.Type) fmt.Println("Loading Field:", fldName, "->", structFld.Type.Kind())
switch structFld.Type.Kind() { switch structFld.Type.Kind() {
case reflect.Pointer, reflect.Struct:
var wrk reflect.Value
if structFld.Type.Kind() == reflect.Pointer {
wrk2 := reflect.ValueOf(structFld)
fmt.Println("wrk2:", reflect.TypeOf(wrk2.Interface()))
} else {
wrk = reflect.New(reflect.TypeOf(structFld))
}
fmt.Println("-> Recurse (struct)", reflect.TypeOf(wrk).Kind())
err := b.Load(append(path, fldName), wrk)
if err != nil {
if ret == nil {
ret = err
}
} else {
// Set the value
reflect.ValueOf(dest).Elem().FieldByName(structFld.Name).Set(reflect.ValueOf(wrk))
}
case reflect.String: case reflect.String:
var wrk string var wrk string
err := b.GetForInterface(path, fldName, &wrk) err := b.GetForInterface(path, fldName, &wrk)
@ -95,33 +114,39 @@ func (b *DB) LoadStruct(path []string, dest any) error {
return ret return ret
} }
func (b *DB) SaveStruct(path []string, src any) error { func (b *DB) Save(path []string, src any) error {
t := reflect.TypeOf(src) t := reflect.TypeOf(src)
fmt.Println(t.Kind())
if t.Kind() == reflect.Pointer { if t.Kind() == reflect.Pointer {
// Save the actual struct // Save the actual struct
return b.SaveStruct(path, reflect.Indirect(reflect.ValueOf(src))) elem := reflect.ValueOf(src).Elem()
return b.Save(path, elem.Interface())
} }
fields := reflect.VisibleFields(t) if t.Kind() == reflect.Struct {
r := reflect.ValueOf(src) fields := reflect.VisibleFields(t)
fmt.Println() r := reflect.ValueOf(src)
for _, fld := range fields { for _, fld := range fields {
f := r.FieldByName(fld.Name) f := r.FieldByName(fld.Name)
fmt.Println(f, FieldName(fld))
/*
if (f.Kind() == reflect.Struct || f.Kind() == reflect.Pointer) && f != src { if (f.Kind() == reflect.Struct || f.Kind() == reflect.Pointer) && f != src {
fmt.Println("Recursing on Field:", f) if f.CanInterface() {
err := b.SaveStruct(append(path, FieldName(fld)), f) err := b.Save(append(path, FieldName(fld)), f.Interface())
if err != nil { if err != nil {
return err return err
}
} else {
err := b.Save(append(path, FieldName(fld)), reflect.Indirect(f))
if err != nil {
return err
}
} }
} else { } else {
if err := b.Set(path, FieldName(fld), f); err != nil { if err := b.Set(path, FieldName(fld), f); err != nil {
return err return err
} }
} }
*/ }
} else {
return b.Set(path[:len(path)-1], path[len(path)-1], src)
} }
return nil return nil
} }

View File

@ -157,7 +157,7 @@ func (b *DB) GetForInterface(path []string, key string, val interface{}) error {
} }
return err return err
} }
func (b *DB) Load(path []string, key string, into interface{}) error { func (b *DB) LoadInto(path []string, key string, into interface{}) error {
var err error var err error
switch v := into.(type) { switch v := into.(type) {
case string: case string:

View File

@ -9,8 +9,8 @@ import (
) )
func main() { func main() {
example1() //example1()
fmt.Println() //fmt.Println()
example2() example2()
} }
@ -23,7 +23,7 @@ func example1() {
} }
fmt.Println("## Saving Struct") fmt.Println("## Saving Struct")
err = db.SaveStruct( err = db.Save(
[]string{"examples", "example1"}, []string{"examples", "example1"},
ExampleType{ ExampleType{
Name: "Example 1", Name: "Example 1",
@ -51,7 +51,7 @@ func example1() {
fmt.Println("## Example 1-2: LoadStruct, simple") fmt.Println("## Example 1-2: LoadStruct, simple")
var name string var name string
err = db.LoadStruct( err = db.Load(
[]string{"examples", "example1", "name"}, []string{"examples", "example1", "name"},
&name, &name,
) )
@ -64,7 +64,7 @@ func example1() {
fmt.Println("## Example 1-3: Struct") fmt.Println("## Example 1-3: Struct")
fmt.Println("Loading into Struct") fmt.Println("Loading into Struct")
newStruct := ExampleType{} newStruct := ExampleType{}
err = db.LoadStruct( err = db.Load(
[]string{"examples", "example1"}, []string{"examples", "example1"},
&newStruct, &newStruct,
) )
@ -79,23 +79,28 @@ func example2() {
os.Exit(1) os.Exit(1)
} }
fmt.Println("## Saving Struct") fmt.Println("## Saving Struct")
err = db.SaveStruct( num := 12345
err = db.Save(
[]string{"examples", "example2"}, []string{"examples", "example2"},
&ExampleType2{ &ExampleType2{
Name: "Example 2", Name: "Example 2",
Age: 20, Age: 20,
SubType: &ExampleSubType{ SubTypePtr: &ExampleSubType{
SubName: "Example SubType Pointer",
},
SubType: ExampleSubType{
SubName: "Example SubType", SubName: "Example SubType",
}, },
Number: &num,
}) })
if err != nil { if err != nil {
fmt.Printf("Error saving struct: %s\n", err.Error()) fmt.Printf("Error saving struct: %s\n", err.Error())
os.Exit(1) os.Exit(1)
} }
//newStruct := ExampleType2{} newStruct := ExampleType2{}
//err = db.LoadStruct([]string{"examples", "example2"}, &newStruct) err = db.Load([]string{"examples", "example2"}, &newStruct)
//fmt.Println(newStruct) fmt.Println(newStruct)
} }
type ExampleType struct { type ExampleType struct {
@ -109,9 +114,11 @@ func (e ExampleType) String() string {
} }
type ExampleType2 struct { type ExampleType2 struct {
Name string `boltease:"name"` Name string `boltease:"name"`
Age int `boltease:"age"` Age int `boltease:"age"`
SubType *ExampleSubType `boltease:"subtype"` SubTypePtr *ExampleSubType `boltease:"subtypeptr"`
SubType ExampleSubType `boltease:"subtype"`
Number *int `boltease:"number"`
} }
func (e ExampleType2) String() string { func (e ExampleType2) String() string {