@@ -198,6 +198,30 @@ func getPathSpec(ni *util.NodeInfo) (*pathSpec, error) {
198198 return nil , fmt .Errorf ("could not find path specification annotation" )
199199}
200200
201+ // pathInfo contains the path-value information for a single gNMI leaf.
202+ type pathInfo struct {
203+ val interface {}
204+ path * gnmipb.Path
205+ }
206+
207+ // toStringPathMap converts the pathSpec-value map to a simple path-value map.
208+ func toStringPathMap (pathMap map [* pathSpec ]interface {}) (map [string ]* pathInfo , error ) {
209+ strPathMap := map [string ]* pathInfo {}
210+ for paths , val := range pathMap {
211+ for _ , path := range paths .gNMIPaths {
212+ strPath , err := PathToString (path )
213+ if err != nil {
214+ return nil , err
215+ }
216+ strPathMap [strPath ] = & pathInfo {
217+ val : val ,
218+ path : path ,
219+ }
220+ }
221+ }
222+ return strPathMap , nil
223+ }
224+
201225// findSetLeaves iteratively walks the fields of the supplied GoStruct, s, and
202226// returns a map, keyed by the path of the leaves that are set, with a the value
203227// that the leaf is set to. YANG lists (Go maps), and containers (Go structs) are
@@ -336,18 +360,16 @@ func leastSpecificPath(paths [][]string) []string {
336360}
337361
338362// appendUpdate adds an update to the supplied gNMI Notification message corresponding
339- // to the path and value supplied.
340- func appendUpdate (n * gnmipb.Notification , path * pathSpec , val interface {} ) error {
341- v , err := EncodeTypedValue (val , gnmipb .Encoding_PROTO )
363+ // to the path and value supplied. path is the string version of the path in pathInfo.
364+ func appendUpdate (n * gnmipb.Notification , path string , pathInfo * pathInfo ) error {
365+ v , err := EncodeTypedValue (pathInfo . val , gnmipb .Encoding_PROTO )
342366 if err != nil {
343- return fmt .Errorf ("cannot represent field value %v as TypedValue for path %v: %v" , val , path , err )
344- }
345- for _ , p := range path .gNMIPaths {
346- n .Update = append (n .Update , & gnmipb.Update {
347- Path : p ,
348- Val : v ,
349- })
367+ return fmt .Errorf ("cannot represent field value %v as TypedValue for path %v: %v" , pathInfo .val , path , err )
350368 }
369+ n .Update = append (n .Update , & gnmipb.Update {
370+ Path : pathInfo .path ,
371+ Val : v ,
372+ })
351373 return nil
352374}
353375
@@ -440,38 +462,38 @@ func Diff(original, modified GoStruct, opts ...DiffOpt) (*gnmipb.Notification, e
440462 return nil , fmt .Errorf ("could not extract set leaves from modified struct: %v" , err )
441463 }
442464
443- matched := map [* pathSpec ]bool {}
465+ origLeavesStr , err := toStringPathMap (origLeaves )
466+ if err != nil {
467+ return nil , fmt .Errorf ("could not convert leaf path map to string path map: %v" , err )
468+ }
469+ modLeavesStr , err := toStringPathMap (modLeaves )
470+ if err != nil {
471+ return nil , fmt .Errorf ("could not convert leaf path map to string path map: %v" , err )
472+ }
473+
444474 n := & gnmipb.Notification {}
445- for origPath , origVal := range origLeaves {
446- var origMatched bool
447- for modPath , modVal := range modLeaves {
448- if origPath .Equal (modPath ) {
449- // This path is set in both of the structs, so check whether the value
450- // is equal.
451- matched [modPath ] = true
452- origMatched = true
453- if ! reflect .DeepEqual (origVal , modVal ) {
454- // The contents of the value should indicate that value a has changed
455- // to value b.
456- if err := appendUpdate (n , origPath , modVal ); err != nil {
457- return nil , err
458- }
475+ for origPath , origVal := range origLeavesStr {
476+ if modVal , ok := modLeavesStr [origPath ]; ok {
477+ if ! reflect .DeepEqual (origVal .val , modVal .val ) {
478+ // The contents of the value should indicate that value a has changed
479+ // to value b.
480+ if err := appendUpdate (n , origPath , modVal ); err != nil {
481+ return nil , err
459482 }
460483 }
461- }
462- if ! origMatched {
484+ } else if ! ok {
463485 // This leaf was set in the original struct, but not in the modified
464486 // struct, therefore it has been deleted.
465- n .Delete = append (n .Delete , origPath . gNMIPaths ... )
487+ n .Delete = append (n .Delete , origVal . path )
466488 }
467489 }
468490 if hasIgnoreAdditions (opts ) != nil {
469491 return n , nil
470492 }
471493 // Check that all paths that are in the modified struct have been examined, if
472494 // not they are updates.
473- for modPath , modVal := range modLeaves {
474- if ! matched [modPath ] {
495+ for modPath , modVal := range modLeavesStr {
496+ if _ , ok := origLeavesStr [modPath ]; ! ok {
475497 if err := appendUpdate (n , modPath , modVal ); err != nil {
476498 return nil , err
477499 }
0 commit comments