Skip to content

Commit

Permalink
Add support for decoding into concreet structs
Browse files Browse the repository at this point in the history
The codegen changes means we need to support decoding data into concreet
structs, and not just pointers to structs.
  • Loading branch information
thomaspurchas committed Jul 17, 2024
1 parent 4f34b9a commit a5bc173
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 15 deletions.
32 changes: 24 additions & 8 deletions pkl/decode_struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,15 @@ func getStructFields(typ reflect.Type) map[string]structField {
field := typ.Field(i)
// embedded
if field.Anonymous {
for k, v := range getStructFields(field.Type.Elem()) {
ret[k] = v
switch field.Type.Kind() {
case reflect.Ptr:
for k, v := range getStructFields(field.Type.Elem()) {
ret[k] = v
}
case reflect.Struct:
for k, v := range getStructFields(field.Type) {
ret[k] = v
}
}
} else {
opts := parseStructOpts(&field)
Expand All @@ -328,13 +335,22 @@ func (d *decoder) getOutputValue(typ reflect.Type) (*reflect.Value, error) {
for i := 0; i < numFields; i++ {
field := typ.Field(i)
if field.Anonymous {
fieldValue := reflect.New(field.Type.Elem())
// Assertion: all embedded fields are pointers to structs.
structValue, err := d.getOutputValue(field.Type.Elem())
if err != nil {
return nil, err
var fieldValue reflect.Value
switch field.Type.Kind() {
case reflect.Ptr:
{
fieldValue = reflect.New(field.Type.Elem())
structValue, err := d.getOutputValue(field.Type.Elem())
if err != nil {
return nil, err
}
fieldValue.Elem().Set(*structValue)
}
case reflect.Struct:
{
fieldValue = reflect.New(field.Type).Elem()
}
}
fieldValue.Elem().Set(*structValue)
ret.FieldByName(field.Name).Set(fieldValue)
}
}
Expand Down
14 changes: 7 additions & 7 deletions pkl/unmarshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,29 +310,29 @@ func TestUnmarshal_Dynamic(t *testing.T) {

func TestUnmarshal_Classes(t *testing.T) {
expected := classes.Classes{
Animals: []classes.Animal{
&classes.GreyhoundImpl{
DogImpl: &classes.DogImpl{
Animals: []classes.IAnimal{
&classes.Greyhound{
Dog: classes.Dog{
Name: "Uni",
Barks: false,
Breed: "Greyhound",
},
CanRoach: true,
},
&classes.CatImpl{
&classes.Cat{
Name: "Millie",
Meows: true,
},
},
MyAnimal: &classes.GreyhoundImpl{
DogImpl: &classes.DogImpl{
MyAnimal: &classes.Greyhound{
Dog: classes.Dog{
Name: "Uni",
Barks: false,
Breed: "Greyhound",
},
CanRoach: true,
},
House: &classes.House{
House: classes.House{
Area: 2000,
Bedrooms: 3,
Bathrooms: 2,
Expand Down

0 comments on commit a5bc173

Please sign in to comment.