/// <summary> /// Writes this struct to a file. /// </summary> /// <param name="struct">The enum to write.</param> /// <param name="file">The file to write to.</param> /// <param name="profile">The subsystem containing this enum.</param> /// <param name="project">The project containing this enum.</param> /// <param name="task">The bind state.</param> public static void WriteStruct (this Struct @struct, string file, Profile profile, Project project, BindState task) { if (@struct.Attributes.IsBuildToolsIntrinsic(out var args) && args.FirstOrDefault() == "$PFN") { WriteBuildToolsIntrinsic(@struct, file, profile, project, task, args); return; } var sw = new StreamWriter(file) { NewLine = "\n" }; sw.WriteLine(task.LicenseText()); sw.WriteLine(); sw.WriteCoreUsings(); sw.WriteLine(); sw.WriteLine("#pragma warning disable 1591"); sw.WriteLine(); var ns = project.IsRoot ? task.Task.Namespace : task.Task.ExtensionsNamespace; sw.WriteLine($"namespace {ns}{project.Namespace}"); sw.WriteLine("{"); string guid = null;
/// <summary> /// Create a class that extends SearchPathContainer. /// </summary> /// <param name="project">The current project.</param> /// <param name="profile">The profile to write the object for.</param> /// <param name="file">The file to write the class to.</param> public static void WriteNameContainer(this Project project, Profile profile, string file, BindState task) { if (File.Exists(file) || task.Task.Controls.Contains("no-name-container")) { return; } using var sw = new StreamWriter(file) { NewLine = "\n" }; sw.WriteLine(task.LicenseText()); sw.WriteLine("using Silk.NET.Core.Loader;"); sw.WriteLine(); sw.WriteLine($"namespace {task.Task.Namespace}{project.Namespace}"); sw.WriteLine("{"); sw.WriteLine(" /// <summary>"); sw.WriteLine($" /// Contains the library name of {profile.Name}."); sw.WriteLine(" /// </summary>"); sw.WriteLine($" internal class {task.Task.NameContainer.ClassName} : SearchPathContainer"); sw.WriteLine(" {"); sw.WriteLine(" /// <inheritdoc />"); sw.WriteLine($" public override string Linux => \"{task.Task.NameContainer.Linux}\";"); sw.WriteLine(); sw.WriteLine(" /// <inheritdoc />"); sw.WriteLine($" public override string MacOS => \"{task.Task.NameContainer.MacOS}\";"); sw.WriteLine(); sw.WriteLine(" /// <inheritdoc />"); sw.WriteLine($" public override string Android => \"{task.Task.NameContainer.Android}\";"); sw.WriteLine(); sw.WriteLine(" /// <inheritdoc />"); sw.WriteLine($" public override string IOS => \"{task.Task.NameContainer.IOS}\";"); sw.WriteLine(); sw.WriteLine(" /// <inheritdoc />"); sw.WriteLine($" public override string Windows64 => \"{task.Task.NameContainer.Windows64}\";"); sw.WriteLine(); sw.WriteLine(" /// <inheritdoc />"); sw.WriteLine($" public override string Windows86 => \"{task.Task.NameContainer.Windows86}\";"); sw.WriteLine(" }"); sw.WriteLine("}"); }
/// <summary> /// Writes this enum to a file. /// </summary> /// <param name="enum">The enum to write.</param> /// <param name="file">The file to write to.</param> /// <param name="profile">The subsystem containing this enum.</param> /// <param name="project">The project containing this enum.</param> public static void WriteEnum(this Enum @enum, string file, Profile profile, Project project, BindState task) { var sw = new StreamWriter(file) { NewLine = "\n" }; sw.WriteLine(task.LicenseText()); sw.WriteLine(); var ns = project.IsRoot ? task.Task.Namespace : task.Task.ExtensionsNamespace; sw.WriteLine("using System;"); sw.WriteLine("using Silk.NET.Core.Attributes;"); sw.WriteLine(); sw.WriteLine("#pragma warning disable 1591"); sw.WriteLine(); sw.WriteLine($"namespace {ns}{project.Namespace}"); sw.WriteLine("{"); foreach (var attr in @enum.Attributes) { sw.WriteLine($" {attr}"); } sw.WriteLine($" [NativeName(\"Name\", \"{@enum.NativeName}\")]"); sw.WriteLine($" public enum {@enum.Name} : {@enum.EnumBaseType}"); sw.WriteLine(" {"); for (var index = 0; index < @enum.Tokens.Count; index++) { var token = @enum.Tokens[index]; sw.WriteLine($" [NativeName(\"Name\", \"{token.NativeName}\")]"); sw.Write($" {token.Name} = {MakeUnchecked(token.Value, @enum.EnumBaseType)}"); sw.WriteLine($"{(index != @enum.Tokens.Count ? "," : string.Empty)}"); } sw.WriteLine(" }"); sw.WriteLine("}"); sw.Flush(); sw.Dispose(); }
/// <summary> /// Write mixed-mode (partial) classes. /// </summary> /// <param name="project">The current project.</param> /// <param name="profile">The profile to write mixed-mode classes for.</param> /// <param name="folder">The folder to store the generated classes in.</param> public static void WriteMixedModeClasses(this Project project, Profile profile, string folder, BindState task) { // public abstract class MixedModeClass : IMixedModeClass // { // } foreach (var @class in project.Classes) { if ((@class.NativeApis.Values.Sum(x => x.Functions.Count) + @class.Functions.Count) == 0) { Console.WriteLine($"Warning: No functions, writing of class \"{@class.ClassName}\" skipped..."); continue; } if (project.IsRoot) { var sw = new StreamWriter(Path.Combine(folder, $"{@class.ClassName}.gen.cs")) { NewLine = "\n" }; StreamWriter?swOverloads = null; sw.Write(task.LicenseText()); sw.WriteCoreUsings(); sw.WriteLine(); sw.WriteLine("#pragma warning disable 1591"); sw.WriteLine(); sw.WriteLine($"namespace {task.Task.Namespace}{project.Namespace}"); sw.WriteLine("{"); sw.WriteLine ($" public unsafe partial class {@class.ClassName} : NativeAPI"); sw.WriteLine(" {"); foreach (var constant in @class.Constants) { sw.WriteLine($" [NativeName(\"Type\", \"{constant.Type.OriginalName}\")]"); sw.WriteLine($" [NativeName(\"Name\", \"{constant.NativeName}\")]"); sw.WriteLine ( $" public const {constant.Type} {constant.Name} = " + $"unchecked(({constant.Type}) {constant.Value});" ); } sw.WriteLine(); var allFunctions = @class.NativeApis.SelectMany (x => x.Value.Functions) .RemoveDuplicates() .ToArray(); foreach (var function in allFunctions) { AddInjectionAttributes(function, task); if (!string.IsNullOrWhiteSpace(function.PreprocessorConditions)) { sw.WriteLine($"#if {function.PreprocessorConditions}"); } using (var sr = new StringReader(function.Doc)) { string line; while ((line = sr.ReadLine()) != null) { sw.WriteLine($" {line}"); } } foreach (var attr in function.Attributes) { sw.WriteLine($" [{attr.Name}({string.Join(", ", attr.Arguments)})]"); } if (function.Convention != CallingConvention.Cdecl) { sw.WriteLine ( $" [NativeApi(EntryPoint = \"{function.NativeName}\", " + $"Convention = CallingConvention.{function.Convention})]" ); } else { sw.WriteLine($" [NativeApi(EntryPoint = \"{function.NativeName}\")]"); } using (var sr = new StringReader(function.ToString(null, true, true))) { string line; while ((line = sr.ReadLine()) != null) { sw.WriteLine($" {line}"); } } if (!string.IsNullOrWhiteSpace(function.PreprocessorConditions)) { sw.WriteLine("#endif"); } sw.WriteLine(); } foreach (var overload in Overloader.GetOverloads(allFunctions, profile.Projects["Core"])) { var sw2u = overload.Signature.Kind == SignatureKind.PotentiallyConflictingOverload ? swOverloads ??= CreateOverloadsFile(folder, @class.ClassName, false) : sw; if (!string.IsNullOrWhiteSpace(overload.Base.PreprocessorConditions)) { sw2u.WriteLine($"#if {overload.Base.PreprocessorConditions}"); } if (sw2u == swOverloads) { overload.Signature.Parameters.Insert ( 0, new Parameter { Name = "thisApi", Type = new Common.Functions.Type { Name = @class.ClassName, IsThis = true } } ); } using (var sr = new StringReader(overload.Signature.Doc)) { string line; while ((line = sr.ReadLine()) != null) { sw2u.WriteLine($" {line}"); } } foreach (var attr in overload.Signature.Attributes) { sw2u.WriteLine($" [{attr.Name}({string.Join(", ", attr.Arguments)})]"); } sw2u.WriteLine($" public {overload.Signature.ToString(overload.IsUnsafe, @static: sw2u == swOverloads).TrimEnd(';')}"); sw2u.WriteLine(" {"); foreach (var line in overload.Body) { sw2u.WriteLine($" {line}"); } sw2u.WriteLine(" }"); if (!string.IsNullOrWhiteSpace(overload.Base.PreprocessorConditions)) { sw2u.WriteLine($"#endif"); } sw2u.WriteLine(); } sw.WriteLine(); sw.WriteLine($" public {@class.ClassName}(INativeContext ctx)"); sw.WriteLine(" : base(ctx)"); sw.WriteLine(" {"); sw.WriteLine(" }"); sw.WriteLine(" }"); sw.WriteLine("}"); sw.WriteLine(); FinishOverloadsFile(swOverloads); sw.Flush(); sw.Dispose(); if (!File.Exists(Path.Combine(folder, $"{@class.ClassName}.cs"))) { sw = new StreamWriter(Path.Combine(folder, $"{@class.ClassName}.cs")) { NewLine = "\n" }; sw.WriteCoreUsings(); sw.WriteLine(); sw.WriteLine("#pragma warning disable 1591"); sw.WriteLine(); sw.WriteLine($"namespace {task.Task.Namespace}{project.Namespace}"); sw.WriteLine("{"); sw.WriteLine($" public partial class {@class.ClassName}"); sw.WriteLine(" {"); sw.WriteLine($" public static {@class.ClassName} GetApi()"); sw.WriteLine(" {"); if (!(task.Task.NameContainer is null)) { sw.WriteLine ( $" return new {@class.ClassName}(CreateDefaultContext" + $"(new {task.Task.NameContainer.ClassName}().GetLibraryName()));" ); } else { sw.WriteLine(" throw new NotImplementedException();"); } sw.WriteLine(" }"); sw.WriteLine(); sw.WriteLine(" public bool TryGetExtension<T>(out T ext)"); sw.WriteLine($" where T:NativeExtension<{@class.ClassName}>"); sw.WriteLine(" {"); sw.WriteLine(" ext = IsExtensionPresent(" + "ExtensionAttribute.GetExtensionAttribute(typeof(T)).Name)"); sw.WriteLine(" ? (T) Activator.CreateInstance(typeof(T), Context)"); sw.WriteLine(" : null;"); sw.WriteLine(" return ext is not null;"); sw.WriteLine(" }"); sw.WriteLine(); sw.WriteLine(" public override bool IsExtensionPresent(string extension)"); sw.WriteLine(" {"); sw.WriteLine(" throw new NotImplementedException();"); sw.WriteLine(" }"); sw.WriteLine(" }"); sw.WriteLine("}"); sw.WriteLine(); sw.Flush(); sw.Dispose(); } if (!(task.Task.NameContainer is null)) { project.WriteNameContainer (profile, Path.Combine(folder, $"{task.Task.NameContainer.ClassName}.cs"), task); } }
/// <summary> /// Writes this struct to a file. /// </summary> /// <param name="struct">The enum to write.</param> /// <param name="file">The file to write to.</param> /// <param name="profile">The subsystem containing this enum.</param> /// <param name="project">The project containing this enum.</param> public static void WriteStruct(this Struct @struct, string file, Profile profile, Project project, BindState task) { if (@struct.Attributes.IsBuildToolsIntrinsic(out var args)) { WriteBuildToolsIntrinsic(@struct, file, profile, project, task, args); return; } var sw = new StreamWriter(file); sw.WriteLine(task.LicenseText()); sw.WriteLine(); sw.WriteCoreUsings(); sw.WriteLine(); sw.WriteLine("#pragma warning disable 1591"); sw.WriteLine(); var ns = project.IsRoot ? task.Task.Namespace : task.Task.ExtensionsNamespace; sw.WriteLine($"namespace {ns}{project.Namespace}"); sw.WriteLine("{"); string guid = null; foreach (var attr in @struct.Attributes) { if (attr.Name == "BuildToolsIntrinsic") { continue; } if (guid is null && attr.Name == "Guid") { guid = string.Join(", ", attr.Arguments); } sw.WriteLine($" {attr}"); } sw.WriteLine($" [NativeName(\"Name\", \"{@struct.NativeName}\")]"); sw.WriteLine($" public unsafe partial struct {@struct.Name}"); sw.WriteLine(" {"); if (guid is not null) { sw.WriteLine($" public static readonly Guid Guid = new({guid});"); sw.WriteLine(); } foreach (var comBase in @struct.ComBases) { var asSuffix = comBase.Split('.').Last(); asSuffix = (asSuffix.StartsWith('I') ? asSuffix.Substring(1) : comBase); asSuffix = asSuffix.StartsWith(task.Task.FunctionPrefix) ? asSuffix.Substring(task.Task.FunctionPrefix.Length) : asSuffix; var fromSuffix = @struct.Name.Split('.').Last(); fromSuffix = (fromSuffix.StartsWith('I') ? fromSuffix.Substring(1) : comBase); fromSuffix = fromSuffix.StartsWith(task.Task.FunctionPrefix) ? fromSuffix.Substring(task.Task.FunctionPrefix.Length) : fromSuffix; sw.WriteLine($" public static implicit operator {comBase}({@struct.Name} val)"); sw.WriteLine($" => Unsafe.As<{@struct.Name}, {comBase}>(ref val);"); sw.WriteLine(); if (@struct.Functions.Any(x => x.Signature.Name.Equals("QueryInterface"))) { sw.WriteLine($" public static explicit operator {@struct.Name}({comBase} val)"); sw.WriteLine($" => From{fromSuffix}(in val);"); sw.WriteLine(); sw.WriteLine($" public readonly ref {comBase} As{asSuffix}()"); sw.WriteLine(" {"); // yes i know this is unsafe and that there's a good reason why struct members can't return themselves // by reference, but this should work well enough. sw.WriteLine("#if NETSTANDARD2_1 || NET5_0 || NETCOREAPP3_1"); sw.WriteLine($" return ref Unsafe.As<{@struct.Name}, {comBase}>"); sw.WriteLine($" ("); sw.WriteLine($" ref MemoryMarshal.GetReference"); sw.WriteLine($" ("); sw.WriteLine($" MemoryMarshal.CreateSpan"); sw.WriteLine($" ("); sw.WriteLine($" ref Unsafe.AsRef(in this),"); sw.WriteLine($" 1"); sw.WriteLine($" )"); sw.WriteLine($" )"); sw.WriteLine($" );"); sw.WriteLine("#else"); sw.WriteLine($" fixed ({@struct.Name}* @this = &this)"); sw.WriteLine($" {{"); sw.WriteLine($" return ref *({comBase}*) @this;"); sw.WriteLine($" }}"); sw.WriteLine("#endif"); sw.WriteLine(" }"); sw.WriteLine(); sw.WriteLine($" public static ref {@struct.Name} From{fromSuffix}(in {comBase} @this)"); sw.WriteLine(" {"); sw.WriteLine($" {@struct.Name}* ret = default;"); sw.WriteLine($" SilkMarshal.ThrowHResult"); sw.WriteLine($" ("); sw.WriteLine($" @this.QueryInterface"); sw.WriteLine($" ("); sw.WriteLine($" ref SilkMarshal.GuidOf<{@struct.Name}>(),"); sw.WriteLine($" (void**) &ret"); sw.WriteLine($" )"); sw.WriteLine($" );"); sw.WriteLine(); sw.WriteLine($" return ref *ret;"); sw.WriteLine(" }"); sw.WriteLine(); } } if (@struct.Fields.Any(x => x.Count is null)) { sw.WriteLine($" public {@struct.Name}"); sw.WriteLine(" ("); var first = true; foreach (var field in @struct.Fields) { if (!(field.Count is null) || field.Type.IsByRef || field.Type.IsIn || field.Type.IsOut) { continue; // I've chosen not to initialize multi-count fields from ctors. } var argName = field.Name[0].ToString().ToLower() + field.Name.Substring(1); argName = Utilities.CSharpKeywords.Contains(argName) ? $"@{argName}" : argName; if (!first) { sw.WriteLine(","); } else { first = false; } var nullable = field.Type.ToString().Contains('*') ? null : "?"; sw.Write($" {field.Type}{nullable} {argName} = {field.DefaultAssignment ?? "null"}"); } sw.WriteLine(); sw.WriteLine(" ) : this()"); sw.WriteLine(" {"); first = true; foreach (var field in @struct.Fields) { if (!(field.Count is null) || field.Type.IsByRef || field.Type.IsIn || field.Type.IsOut) { continue; // I've chosen not to initialize multi-count fields from ctors. } var argName = field.Name[0].ToString().ToLower() + field.Name.Substring(1); argName = Utilities.CSharpKeywords.Contains(argName) ? $"@{argName}" : argName; if (!first) { sw.WriteLine(); } else { first = false; } sw.WriteLine($" if ({argName} is not null)"); sw.WriteLine(" {"); var value = field.Type.ToString().Contains('*') ? null : ".Value"; sw.WriteLine($" {field.Name} = {argName}{value};"); sw.WriteLine(" }"); } sw.WriteLine(" }"); sw.WriteLine(); } foreach (var structField in @struct.Fields) { if (structField.Attributes.IsBuildToolsIntrinsic(out var intrinsic) && intrinsic[0] == "$FUSEFLD") { WriteFusedField(structField, intrinsic, sw); }
/// <summary> /// Writes this struct to a file. /// </summary> /// <param name="struct">The enum to write.</param> /// <param name="file">The file to write to.</param> /// <param name="profile">The subsystem containing this enum.</param> /// <param name="project">The project containing this enum.</param> public static void WriteStruct(this Struct @struct, string file, Profile profile, Project project, BindState task) { if (@struct.Attributes.IsBuildToolsIntrinsic(out var args)) { WriteBuildToolsIntrinsic(@struct, file, profile, project, task, args); return; } var sw = new StreamWriter(file); sw.WriteLine(task.LicenseText()); sw.WriteLine(); sw.WriteCoreUsings(); sw.WriteLine(); sw.WriteLine("#pragma warning disable 1591"); sw.WriteLine(); var ns = project.IsRoot ? task.Task.Namespace : task.Task.ExtensionsNamespace; sw.WriteLine($"namespace {ns}{project.Namespace}"); sw.WriteLine("{"); foreach (var attr in @struct.Attributes) { if (attr.Name == "BuildToolsIntrinsic") { continue; } sw.WriteLine($" {attr}"); } sw.WriteLine($" [NativeName(\"Name\", \"{@struct.NativeName}\")]"); sw.WriteLine($" public unsafe partial struct {@struct.Name}"); sw.WriteLine(" {"); foreach (var comBase in @struct.ComBases) { var asSuffix = comBase.Split('.').Last(); asSuffix = (asSuffix.StartsWith('I') ? asSuffix.Substring(1) : comBase); asSuffix = asSuffix.StartsWith(task.Task.FunctionPrefix) ? asSuffix.Substring(task.Task.FunctionPrefix.Length) : asSuffix; var fromSuffix = @struct.Name.Split('.').Last(); fromSuffix = (fromSuffix.StartsWith('I') ? fromSuffix.Substring(1) : comBase); fromSuffix = fromSuffix.StartsWith(task.Task.FunctionPrefix) ? fromSuffix.Substring(task.Task.FunctionPrefix.Length) : fromSuffix; sw.WriteLine($" public static implicit operator {comBase}({@struct.Name} val)"); sw.WriteLine($" => Unsafe.As<{@struct.Name}, {comBase}>(ref val);"); sw.WriteLine(); if (@struct.Functions.Any(x => x.Signature.Name.Equals("QueryInterface"))) { sw.WriteLine($" public static explicit operator {@struct.Name}({comBase} val)"); sw.WriteLine($" => From{fromSuffix}(in val);"); sw.WriteLine(); sw.WriteLine($" public readonly ref {comBase} As{asSuffix}()"); sw.WriteLine(" {"); // yes i know this is unsafe and that there's a good reason why struct members can't return themselves // by reference, but this should work well enough. sw.WriteLine("#if NETSTANDARD2_1 || NET5_0 || NETCOREAPP3_1"); sw.WriteLine($" return ref Unsafe.As<{@struct.Name}, {comBase}>"); sw.WriteLine($" ("); sw.WriteLine($" ref MemoryMarshal.GetReference"); sw.WriteLine($" ("); sw.WriteLine($" MemoryMarshal.CreateSpan"); sw.WriteLine($" ("); sw.WriteLine($" ref Unsafe.AsRef(in this),"); sw.WriteLine($" 1"); sw.WriteLine($" )"); sw.WriteLine($" )"); sw.WriteLine($" );"); sw.WriteLine("#else"); sw.WriteLine($" fixed ({@struct.Name}* @this = &this)"); sw.WriteLine($" {{"); sw.WriteLine($" return ref *({comBase}*) @this;"); sw.WriteLine($" }}"); sw.WriteLine("#endif"); sw.WriteLine(" }"); sw.WriteLine(); sw.WriteLine($" public static ref {@struct.Name} From{fromSuffix}(in {comBase} @this)"); sw.WriteLine(" {"); sw.WriteLine($" {@struct.Name}* ret = default;"); sw.WriteLine($" SilkMarshal.ThrowHResult"); sw.WriteLine($" ("); sw.WriteLine($" @this.QueryInterface"); sw.WriteLine($" ("); sw.WriteLine($" ref SilkMarshal.GuidOf<{@struct.Name}>(),"); sw.WriteLine($" (void**) &ret"); sw.WriteLine($" )"); sw.WriteLine($" );"); sw.WriteLine(); sw.WriteLine($" return ref *ret;"); sw.WriteLine(" }"); sw.WriteLine(); } } if (@struct.Fields.Any(x => x.Count is null)) { sw.WriteLine($" public {@struct.Name}"); sw.WriteLine(" ("); var first = true; foreach (var field in @struct.Fields) { if (!(field.Count is null)) { continue; // I've chosen not to initialize multi-count fields from ctors. } var argName = field.Name[0].ToString().ToLower() + field.Name.Substring(1); argName = Utilities.CSharpKeywords.Contains(argName) ? $"@{argName}" : argName; if (!first) { sw.WriteLine(","); } else { first = false; } var nullable = field.Type.ToString().Contains('*') ? null : "?"; sw.Write($" {field.Type}{nullable} {argName} = {field.DefaultAssignment ?? "null"}"); } sw.WriteLine(); sw.WriteLine(" ) : this()"); sw.WriteLine(" {"); first = true; foreach (var field in @struct.Fields) { if (!(field.Count is null)) { continue; // I've chosen not to initialize multi-count fields from ctors. } var argName = field.Name[0].ToString().ToLower() + field.Name.Substring(1); argName = Utilities.CSharpKeywords.Contains(argName) ? $"@{argName}" : argName; if (!first) { sw.WriteLine(); } else { first = false; } sw.WriteLine($" if ({argName} is not null)"); sw.WriteLine(" {"); var value = field.Type.ToString().Contains('*') ? null : ".Value"; sw.WriteLine($" {field.Name} = {argName}{value};"); sw.WriteLine(" }"); } sw.WriteLine(" }"); sw.WriteLine(); } foreach (var structField in @struct.Fields) { if (!(structField.Count is null)) { if (!Field.FixedCapableTypes.Contains(structField.Type.Name)) { var count = structField.Count.IsConstant ? int.Parse ( profile.Projects.SelectMany(x => x.Value.Classes.SelectMany(y => y.Constants)) .FirstOrDefault(x => x.NativeName == structField.Count.ConstantName) ? .Value ?? throw new InvalidDataException("Couldn't find constant referenced") ) : structField.Count.IsStatic ? structField.Count.StaticCount : 1; var typeFixup09072020 = new TypeSignatureBuilder(structField.Type).WithIndirectionLevel (structField.Type.IndirectionLevels - 1).Build(); sw.WriteLine($" {structField.Doc}"); foreach (var attr in structField.Attributes) { sw.WriteLine($" {attr}"); } sw.WriteLine($" [NativeName(\"Type\", \"{structField.NativeType}\")]"); sw.WriteLine($" [NativeName(\"Type.Name\", \"{structField.Type.OriginalName}\")]"); sw.WriteLine($" [NativeName(\"Name\", \"{structField.NativeName}\")]"); sw.WriteLine($" public {structField.Name}Buffer {structField.Name};"); sw.WriteLine(); sw.WriteLine($" public struct {structField.Name}Buffer"); sw.WriteLine(" {"); for (var i = 0; i < count; i++) { sw.WriteLine($" public {typeFixup09072020} Element{i};"); } sw.WriteLine($" public ref {typeFixup09072020} this[int index]"); sw.WriteLine(" {"); sw.WriteLine(" get"); sw.WriteLine(" {"); sw.WriteLine($" if (index > {count - 1} || index < 0)"); sw.WriteLine(" {"); sw.WriteLine(" throw new ArgumentOutOfRangeException(nameof(index));"); sw.WriteLine(" }"); sw.WriteLine(); sw.WriteLine($" fixed ({typeFixup09072020}* ptr = &Element0)"); sw.WriteLine(" {"); sw.WriteLine(" return ref ptr[index];"); sw.WriteLine(" }"); sw.WriteLine(" }"); sw.WriteLine(" }"); if (!typeFixup09072020.IsPointer) { sw.WriteLine(); sw.WriteLine("#if NETSTANDARD2_1"); sw.WriteLine($" public Span<{typeFixup09072020}> AsSpan()"); sw.WriteLine($" => MemoryMarshal.CreateSpan(ref Element0, {count});"); sw.WriteLine("#endif"); } sw.WriteLine(" }"); sw.WriteLine(); } else { if (!string.IsNullOrEmpty(structField.Doc)) { sw.WriteLine($" {structField.Doc}"); } var count = structField.Count.IsConstant ? Utilities.ParseInt ( profile.Projects.SelectMany(x => x.Value.Classes.SelectMany(y => y.Constants)) .FirstOrDefault(x => x.NativeName == structField.Count.ConstantName)? .Value ?? profile.Projects.SelectMany(x => x.Value.Enums.SelectMany(y => y.Tokens)) .FirstOrDefault(x => x.NativeName == structField.Count.ConstantName)? .Value ?? throw new InvalidDataException("Couldn't find constant referenced") ) : structField.Count.IsStatic ? structField.Count.StaticCount : 1; var typeFixup09072020 = new TypeSignatureBuilder(structField.Type).WithIndirectionLevel //(structField.Type.IndirectionLevels - 1).Build(); (0).Build(); foreach (var attr in structField.Attributes) { sw.WriteLine($" {attr}"); } sw.WriteLine($" [NativeName(\"Type\", \"{structField.NativeType}\")]"); sw.WriteLine($" [NativeName(\"Type.Name\", \"{structField.Type.OriginalName}\")]"); sw.WriteLine($" [NativeName(\"Name\", \"{structField.NativeName}\")]"); sw.WriteLine($" public fixed {typeFixup09072020} {structField.Name}[{count}];"); } }