diff --git a/nucleus/southbound.go b/nucleus/southbound.go index 1823b89db54dec74149534c76f2594496d127e74..8f93d13128e1714b46ef3af7cf791de5f721e9cd 100644 --- a/nucleus/southbound.go +++ b/nucleus/southbound.go @@ -82,8 +82,7 @@ func (oc *OpenConfig) Unmarshal(bytes []byte, fields []*path.GnmiPathPiece, goSt return unmarshal(oc.Schema(), bytes, fields, goStruct, opt...) } -// unmarshal parses gNMI response to a go struct. If it's a root level response -// it uses +//unmarshal parses a gNMI response to a go struct. func unmarshal(schema *ytypes.Schema, bytes []byte, fields []*path.GnmiPathPiece, goStruct ygot.ValidatedGoStruct, opt ...ytypes.UnmarshalOpt) error { defer func() { if r := recover(); r != nil { @@ -160,7 +159,10 @@ func getField(inStruct ygot.ValidatedGoStruct, fields []*path.GnmiPathPiece) (yg return outStruct, nil } -// initialiseMapWithKey +// initialiseMapWithKey takes the map type as reflect.Type (expects it to be a +// map[T]*L, where T and L can be everything) and the value that should be +// initialised as reflect.Value. A new map is created and a new key-value pair +// is set, the newly created value is initialised and returned func initialiseMapWithKey(mType reflect.Type, mValue reflect.Value, gpp *path.GnmiPathPiece) (ygot.ValidatedGoStruct, error) { defer func() { if r := recover(); r != nil { @@ -169,26 +171,31 @@ func initialiseMapWithKey(mType reflect.Type, mValue reflect.Value, gpp *path.Gn }() newMap := reflect.MakeMap(mType) mValue.Set(newMap) - // This should only contain one entry. since its a map[T]T the type and - // value of the key are not known - therefore it is necessary to loop over + // This should only contain one entry. Since its a map[string]string and the + // key is not known it is necessary to loop over the map to get the entry for _, k := range gpp.Keys { - kConv, err := convertToType(k, mType.Key().Kind()) + ck, err := convertToType(k, mType.Key().Kind()) if err != nil { return nil, err } - mValue.SetMapIndex(reflect.ValueOf(kConv), reflect.New(mType.Elem().Elem())) - h := mValue.MapIndex(reflect.ValueOf(kConv)).Interface() + // Add a new key-value pair with the key from gpp.Keys and a pointer to + // a new zero value of type mType.Elem().Elem(), since the map was created + // from mType this is the expected ValueType + mValue.SetMapIndex(reflect.ValueOf(ck), reflect.New(mType.Elem().Elem())) + h := mValue.MapIndex(reflect.ValueOf(ck)).Interface() outStruct, ok := h.(ygot.ValidatedGoStruct) if !ok { return nil, fmt.Errorf("expected ValidatedGoStruct got %v", h) } + //Initialise the yang tree of the newly created GoStruct ygot.BuildEmptyTree(outStruct) return outStruct, nil } return nil, fmt.Errorf("could not initialise the map with a key, length of given keys is: %d", len(gpp.Keys)) } -// TODO: refactor: move somewhere else and check which other types are needed +// convertToType allows to convert a string to a specific type, which is +// provided as reflect.Kind func convertToType(tc string, k reflect.Kind) (interface{}, error) { switch k { case reflect.String: diff --git a/nucleus/util/path/translate.go b/nucleus/util/path/translate.go index 4b6f73b92c71572f7041d7b1e0e63aef6d79db19..180d0983a855a8a7b034bc2f535ad1e8272715a7 100644 --- a/nucleus/util/path/translate.go +++ b/nucleus/util/path/translate.go @@ -6,6 +6,7 @@ import ( gpb "github.com/openconfig/gnmi/proto/gnmi" ) +// GnmiPathPiece represents a piece of a gnmi.Path and holds its Name and Keys type GnmiPathPiece struct { Name string Keys map[string]string