Repository: FlaxEngine/FlaxEngine
File: Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs (C#)

Code before:
                CppReferencesFiles.Add(apiType.File);
                if (apiType.IsStruct && !apiType.IsPod && !CppUsedNonPodTypes.Contains(apiType))
                    CppUsedNonPodTypes.Add(apiType);

                if (apiType.IsEnum)
                    return $"Variant::Enum(VariantType(VariantType::Enum, StringAnsiView(\"{apiType.FullNameManaged}\", {apiType.FullNameManaged.Length})), {value})";
                if (apiType.IsStruct && !CppInBuildVariantStructures.Contains(apiType.Name))
                    if (typeInfo.IsPtr)
                        return $"Variant::Structure(VariantType(VariantType::Structure, StringAnsiView(\"{apiType.FullNameManaged}\", {apiType.FullNameManaged.Length})), *{value})";
                    else
                        return $"Variant::Structure(VariantType(VariantType::Structure, StringAnsiView(\"{apiType.FullNameManaged}\", {apiType.FullNameManaged.Length})), {value})";
            }

            if (typeInfo.IsPtr && typeInfo.IsConst)
                return $"Variant(({typeInfo.Type}*){value})";
            return $"Variant({value})";
        }

        public static string GenerateCppWrapperVariantToNative(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller, string value)
        {
            if (typeInfo.Type == "Variant")
                return value;
            if (typeInfo.Type == "String")
                return $"(StringView){value}";
            if (typeInfo.IsPtr && typeInfo.IsConst && typeInfo.Type == "Char")
                return $"((StringView){value}).GetNonTerminatedText()"; // This is a bug, as we need a null-terminated strig here. Any idea how to fix it?
            if (typeInfo.Type == "AssetReference" || typeInfo.Type == "WeakAssetReference")
                return $"ScriptingObject::Cast<{typeInfo.GenericArgs[0].Type}>((Asset*){value})";
            if (typeInfo.Type == "ScriptingObjectReference" || typeInfo.Type == "SoftObjectReference")
                return $"ScriptingObject::Cast<{typeInfo.GenericArgs[0].Type}>((ScriptingObject*){value})";
            if (typeInfo.IsArray)
                throw new Exception($"Not supported type to convert from the Variant to fixed-size array '{typeInfo}[{typeInfo.ArraySize}]'.");
            if (typeInfo.Type == "Array" && typeInfo.GenericArgs != null)
            {
                CppVariantToTypes.Add(typeInfo);
                return $"MoveTemp(VariantTo{GenerateCppWrapperNativeToVariantMethodName(typeInfo)}({value}))";
            }
            if (typeInfo.Type == "Dictionary" && typeInfo.GenericArgs != null)
            {
                CppVariantToTypes.Add(typeInfo);
                return $"MoveTemp(VariantTo{GenerateCppWrapperNativeToVariantMethodName(typeInfo)}({value}))";
            }

            var apiType = FindApiTypeInfo(buildData, typeInfo, caller);
            if (apiType != null)
            {
                CppReferencesFiles.Add(apiType.File);
                if (apiType.IsStruct && !apiType.IsPod && !CppUsedNonPodTypes.Contains(apiType))
                    CppUsedNonPodTypes.Add(apiType);

                if (apiType.IsEnum)

Review comment (suggestion):
I think it's not a problem as `Variant` if it's String type it contains null-terminator character so it's safe to access it. It will be null if string is empty.

Code after:
                CppReferencesFiles.Add(apiType.File);
                if (apiType.IsStruct && !apiType.IsPod && !CppUsedNonPodTypes.Contains(apiType))
                    CppUsedNonPodTypes.Add(apiType);

                if (apiType.IsEnum)
                    return $"Variant::Enum(VariantType(VariantType::Enum, StringAnsiView(\"{apiType.FullNameManaged}\", {apiType.FullNameManaged.Length})), {value})";
                if (apiType.IsStruct && !CppInBuildVariantStructures.Contains(apiType.Name))
                    if (typeInfo.IsPtr)
                        return $"Variant::Structure(VariantType(VariantType::Structure, StringAnsiView(\"{apiType.FullNameManaged}\", {apiType.FullNameManaged.Length})), *{value})";
                    else
                        return $"Variant::Structure(VariantType(VariantType::Structure, StringAnsiView(\"{apiType.FullNameManaged}\", {apiType.FullNameManaged.Length})), {value})";
            }

            if (typeInfo.IsPtr && typeInfo.IsConst)
                return $"Variant(({typeInfo.Type}*){value})";
            return $"Variant({value})";
        }

        public static string GenerateCppWrapperVariantToNative(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller, string value)
        {
            if (typeInfo.Type == "Variant")
                return value;
            if (typeInfo.Type == "String")
                return $"(StringView){value}";
            if (typeInfo.IsPtr && typeInfo.IsConst && typeInfo.Type == "Char")
                return $"((StringView){value}).GetNonTerminatedText()"; // (StringView)Variant, if not empty, is guaranteed to point to a null-terminated buffer.
            if (typeInfo.Type == "AssetReference" || typeInfo.Type == "WeakAssetReference")
                return $"ScriptingObject::Cast<{typeInfo.GenericArgs[0].Type}>((Asset*){value})";
            if (typeInfo.Type == "ScriptingObjectReference" || typeInfo.Type == "SoftObjectReference")
                return $"ScriptingObject::Cast<{typeInfo.GenericArgs[0].Type}>((ScriptingObject*){value})";
            if (typeInfo.IsArray)
                throw new Exception($"Not supported type to convert from the Variant to fixed-size array '{typeInfo}[{typeInfo.ArraySize}]'.");
            if (typeInfo.Type == "Array" && typeInfo.GenericArgs != null)
            {
                CppVariantToTypes.Add(typeInfo);
                return $"MoveTemp(VariantTo{GenerateCppWrapperNativeToVariantMethodName(typeInfo)}({value}))";
            }
            if (typeInfo.Type == "Dictionary" && typeInfo.GenericArgs != null)
            {
                CppVariantToTypes.Add(typeInfo);
                return $"MoveTemp(VariantTo{GenerateCppWrapperNativeToVariantMethodName(typeInfo)}({value}))";
            }

            var apiType = FindApiTypeInfo(buildData, typeInfo, caller);
            if (apiType != null)
            {
                CppReferencesFiles.Add(apiType.File);
                if (apiType.IsStruct && !apiType.IsPod && !CppUsedNonPodTypes.Contains(apiType))
                    CppUsedNonPodTypes.Add(apiType);

                if (apiType.IsEnum)