using System; using System.Collections.Generic; using System.IO; using System.Linq; struct Arg { public string Name { get; set; } public string Type { get; set; } } struct Function { public string Name { get; set; } public int NumArgs { get; set; } public Arg[] Args { get; set; } public string ReturnType { get; set; } } struct Module { public string Name { get; set; } public Function[] Functions { get; set; } } struct Bindings { public Module[] Modules { get; set; } } class Generator { static string ConvertTypes(string type) { return type switch { "float" => "float", "int" => "int", "bool" => "bool", "void" => "void", "char" => "byte", "string" => "NativeString" }; } static string GenerateInternals(Bindings bindings) { string generatedInternals = string.Empty; generatedInternals += "using Coral.Managed.Interop;\n"; generatedInternals += "namespace Nuake.Net\r\n{\n"; generatedInternals += "public class Internals\n"; generatedInternals += "{\n"; foreach (var module in bindings.Modules) { generatedInternals += $" // {module.Name}\n"; if(module.Functions != null) { foreach (var function in module.Functions) { generatedInternals += $" internal static unsafe delegate*<"; if (function.NumArgs > 0) { generatedInternals += $"{string.Join(", ", function.Args.Select(a => ConvertTypes(a.Type)))},"; } generatedInternals += $"{function.ReturnType}>{module.Name}{function.Name}ICall;\n"; } } generatedInternals += "\n"; } generatedInternals += "}\n"; generatedInternals += "}\n"; return generatedInternals; } static string GenerateModuleAPI(Module module) { string moduleApi = string.Empty; moduleApi += "using System;\n"; moduleApi += "namespace Nuake.Net\n"; moduleApi += "{\n"; moduleApi += " public class " + module.Name + "\n"; moduleApi += " {\n"; if(module.Functions != null) { foreach (Function func in module.Functions) { moduleApi += " public static " + func.ReturnType + " " + func.Name + "("; if (func.NumArgs > 0) { moduleApi += string.Join(", ", func.Args.Select(a => a.Type + " " + a.Name)); } moduleApi += ")\n"; moduleApi += " {\n"; moduleApi += " unsafe\n"; moduleApi += " {\n"; if (func.ReturnType != "void") { moduleApi += $" return "; } moduleApi += $" Internals.{module.Name}{func.Name}ICall("; if (func.NumArgs > 0) { moduleApi += string.Join(", ", func.Args.Select(a => a.Name)); } moduleApi += ");\n"; moduleApi += " }\n"; moduleApi += " }\n"; } } moduleApi += " }\n"; moduleApi += "}\n"; return moduleApi; } struct FileToWrite { public string FileName { get; set; } public string Content { get; set; } } static void Main() { // Read file bindings.json string fullPath = Path.Combine(AppContext.BaseDirectory, "../../../../Editor/Build/Debug/Binaries/bindings.json"); Console.WriteLine(fullPath); string json = File.ReadAllText(fullPath); // parse the json Bindings bindings = System.Text.Json.JsonSerializer.Deserialize(json); List filesToWrite = new List(); string internals = GenerateInternals(bindings); filesToWrite.Add(new FileToWrite { FileName = "Internals.cs", Content = internals }); Console.WriteLine("Generated Internals:\n"); Console.WriteLine(internals); foreach (var module in bindings.Modules) { string fileName = module.Name + ".cs"; Console.WriteLine("Generated " + fileName); string api = GenerateModuleAPI(module); Console.WriteLine(api); filesToWrite.Add(new FileToWrite { FileName = fileName, Content = api }); } // WriteFiles foreach (var module in filesToWrite) { string fullfilePath = Path.Combine(AppContext.BaseDirectory, "../../../../NuakeNet/Source/Generated"); string filePath = Path.Combine(fullfilePath, module.FileName); File.WriteAllText(filePath, module.Content); Console.WriteLine($"Wrote {module.FileName} to {filePath}"); } } }