diff --git a/src/Generator/Types/Std/Stdlib.CLI.cs b/src/Generator/Types/Std/Stdlib.CLI.cs index 2f12e5b4..ccb98ec0 100644 --- a/src/Generator/Types/Std/Stdlib.CLI.cs +++ b/src/Generator/Types/Std/Stdlib.CLI.cs @@ -121,6 +121,110 @@ namespace CppSharp.Types.Std.CLI ctx.ReturnVarName); } } + + [TypeMap("std::optional", GeneratorKindID = GeneratorKind.CLI_ID)] + public class Optional : TypeMap + { + public override bool IsIgnored + { + get + { + var finalType = Type.GetFinalPointee() ?? Type; + if (finalType is not TemplateSpecializationType type) + { + var injectedClassNameType = (InjectedClassNameType)finalType; + type = (TemplateSpecializationType)injectedClassNameType.InjectedSpecializationType.Type; + } + var checker = new TypeIgnoreChecker(TypeMapDatabase); + type.Arguments[0].Type.Visit(checker); + + return checker.IsIgnored; + } + } + + public override Type SignatureType(TypePrinterContext ctx) + { + return new CustomType($"System::Nullable<{ ctx.GetTemplateParameterList() }>"); + } + + public override void MarshalToNative(MarshalContext ctx) + { + var desugared = Type.Desugar(); + var templateType = desugared as TemplateSpecializationType; + var type = templateType!.Arguments[0].Type; + var isPointerToPrimitive = type.Type.IsPointerToPrimitiveType(); + var managedType = isPointerToPrimitive + ? new CILType(typeof(nint)) + : type.Type; + + var paramName = ctx.Parameter?.Name ?? ctx.ArgName; + + ctx.Before.WriteLineIndent("if (!{0}.HasValue)", paramName); + ctx.Before.WriteOpenBraceAndIndent(); + { + ctx.Before.WriteLine("{0} = std::nullopt;", ctx.ReturnVarName); + ctx.Before.WriteLine("return;"); + ctx.Before.UnindentAndWriteCloseBrace(); + } + + var param = new Parameter + { + Name = paramName + ".Value", + QualifiedType = type + }; + + var elementCtx = new MarshalContext(ctx.Context, ctx.Indentation) + { + Parameter = param, + ArgName = param.Name, + }; + + var marshal = new CLIMarshalManagedToNativePrinter(elementCtx); + type.Type.Visit(marshal); + + if (!string.IsNullOrWhiteSpace(marshal.Context.Before)) + ctx.Before.Write(marshal.Context.Before); + + if (isPointerToPrimitive) + ctx.Return.Write("{0}.ToPointer()", marshal.Context.Return); + else + ctx.Return.Write(marshal.Context.Return); + } + + public override void MarshalToManaged(MarshalContext ctx) + { + var desugared = Type.Desugar(); + var templateType = desugared as TemplateSpecializationType; + var type = templateType!.Arguments[0].Type; + var isPointerToPrimitive = type.Type.IsPointerToPrimitiveType(); + var managedType = isPointerToPrimitive + ? new CILType(typeof(nint)) + : type.Type; + + ctx.Before.WriteLineIndent("if (!{0}.has_value())", ctx.ArgName); + { + ctx.Before.WriteLine("return {};"); + ctx.Before.Unindent(); + } + + var elementCtx = new MarshalContext(ctx.Context, ctx.Indentation) + { + ReturnVarName = ctx.ReturnVarName + ".value()", + ReturnType = type + }; + + var marshal = new CLIMarshalNativeToManagedPrinter(elementCtx); + type.Type.Visit(marshal); + + if (!string.IsNullOrWhiteSpace(marshal.Context.Before)) + ctx.Before.Write(marshal.Context.Before); + + if (isPointerToPrimitive) + ctx.Return.Write("{0}({1})", managedType, marshal.Context.Return); + else + ctx.Return.Write(marshal.Context.Return); + } + } [TypeMap("std::vector", GeneratorKindID = GeneratorKind.CLI_ID)] public class Vector : TypeMap @@ -159,8 +263,7 @@ namespace CppSharp.Types.Std.CLI ? new CILType(typeof(System.IntPtr)) : type.Type; - var entryString = (ctx.Parameter != null) ? ctx.Parameter.Name - : ctx.ArgName; + var entryString = ctx.Parameter?.Name ?? ctx.ArgName; var tmpVarName = "_tmp" + entryString; @@ -314,7 +417,7 @@ namespace CppSharp.Types.Std.CLI [TypeMap("std::nullptr_t", GeneratorKindID = GeneratorKind.CLI_ID)] public class NullPtr : TypeMap { - public override bool DoesMarshalling { get { return false; } } + public override bool DoesMarshalling => false; public override void CLITypeReference(CLITypeReferenceCollector collector, ASTRecord loc)