mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
Support encoding map types to CycloneDX properties (#1332)
This commit is contained in:
parent
5ed002e1a9
commit
f3528132a7
@ -85,6 +85,7 @@ func Sorted(values map[string]string) (out []NameValue) {
|
||||
return
|
||||
}
|
||||
|
||||
//nolint:funlen
|
||||
func encode(out map[string]string, value reflect.Value, prefix string, fn FieldName) {
|
||||
if !value.IsValid() || value.Type() == nil {
|
||||
return
|
||||
@ -130,6 +131,11 @@ func encode(out map[string]string, value reflect.Value, prefix string, fn FieldN
|
||||
}
|
||||
encode(out, pv, name, fn)
|
||||
}
|
||||
case reflect.Map:
|
||||
// currently only map[string]string is really supported
|
||||
for _, key := range value.MapKeys() {
|
||||
encode(out, value.MapIndex(key), fmt.Sprintf("%s:%v", prefix, key.Interface()), fn)
|
||||
}
|
||||
default:
|
||||
log.Warnf("skipping encoding of unsupported property: %s", prefix)
|
||||
}
|
||||
@ -284,6 +290,55 @@ func decode(vals map[string]string, value reflect.Value, prefix string, fn Field
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case reflect.Map:
|
||||
values := false
|
||||
keyType := typ.Key()
|
||||
valueType := typ.Elem()
|
||||
outMap := reflect.MakeMap(typ)
|
||||
str := fmt.Sprintf("%s:", prefix)
|
||||
keyVals := map[string]string{}
|
||||
// iterate through all keys to find those prefixed with a reference to this map
|
||||
// NOTE: this will not work for nested maps
|
||||
for key := range vals {
|
||||
// test for map prefix
|
||||
if strings.HasPrefix(key, str) {
|
||||
keyVals[key] = strings.TrimPrefix(key, str)
|
||||
// create new placeholder and decode key
|
||||
newKeyType := keyType
|
||||
if keyType.Kind() == reflect.Ptr {
|
||||
newKeyType = keyType.Elem()
|
||||
}
|
||||
k := reflect.New(newKeyType)
|
||||
if !decode(keyVals, k.Elem(), key, fn) {
|
||||
log.Debugf("unable to decode key for: %s", key)
|
||||
continue
|
||||
}
|
||||
if keyType.Kind() != reflect.Ptr {
|
||||
k = k.Elem()
|
||||
}
|
||||
|
||||
// create new placeholder and decode value
|
||||
newValueType := valueType
|
||||
if valueType.Kind() == reflect.Ptr {
|
||||
newValueType = valueType.Elem()
|
||||
}
|
||||
v := reflect.New(newValueType)
|
||||
if decode(vals, v.Elem(), key, fn) {
|
||||
if valueType.Kind() != reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
// set in map
|
||||
outMap.SetMapIndex(k, v)
|
||||
values = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if values {
|
||||
value.Set(outMap)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case reflect.Struct:
|
||||
values := false
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
|
||||
@ -37,6 +37,10 @@ type T4 struct {
|
||||
IntPtr *int
|
||||
}
|
||||
|
||||
type T5 struct {
|
||||
Map map[string]string
|
||||
}
|
||||
|
||||
func Test_EncodeDecodeCycle(t *testing.T) {
|
||||
val := 99
|
||||
|
||||
@ -118,6 +122,15 @@ func Test_EncodeDecodeCycle(t *testing.T) {
|
||||
{"t2 elem 1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "map of strings",
|
||||
value: &T5{
|
||||
Map: map[string]string{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user