Add CFI product config variables to platform_mappings

Bug: 269577299
Fixes: 283130542
Test: b test --config=android //build/bazel/rules/cc/...
Change-Id: I2fc4094167c48b1f3b22bee6b7ada309278f7250
diff --git a/starlark_import/unmarshal.go b/starlark_import/unmarshal.go
index 0e6f130..33c0cd9 100644
--- a/starlark_import/unmarshal.go
+++ b/starlark_import/unmarshal.go
@@ -289,16 +289,13 @@
 	}
 }
 
-// NoneableString converts a starlark.Value to a string pointer. If the starlark.Value is NoneType,
-// a nil pointer will be returned instead. All other types of starlark values are errors.
-func NoneableString(value starlark.Value) (*string, error) {
-	switch v := value.(type) {
-	case starlark.String:
-		result := v.GoString()
-		return &result, nil
-	case starlark.NoneType:
+// UnmarshalNoneable is like Unmarshal, but it will accept None as the top level (but not nested)
+// starlark value. If the value is None, a nil pointer will be returned, otherwise a pointer
+// to the result of Unmarshal will be returned.
+func UnmarshalNoneable[T any](value starlark.Value) (*T, error) {
+	if _, ok := value.(starlark.NoneType); ok {
 		return nil, nil
-	default:
-		return nil, fmt.Errorf("expected string or none, got %q", value.Type())
 	}
+	ret, err := Unmarshal[T](value)
+	return &ret, err
 }