diff --git a/src/Luban.Common/Source/Utils/TypeUtil.cs b/src/Luban.Common/Source/Utils/TypeUtil.cs index 28f9bc9..908c39f 100644 --- a/src/Luban.Common/Source/Utils/TypeUtil.cs +++ b/src/Luban.Common/Source/Utils/TypeUtil.cs @@ -131,6 +131,11 @@ namespace Luban.Common.Utils return MakeGoNamespace(module) + name; } + public static string MakeFlatBuffersFullName(string module, string name) + { + return MakeGoNamespace(module) + name; + } + public static string MakeNamespace(string module, string subModule) { if (module.Length == 0) diff --git a/src/Luban.Job.Cfg/Source/DataExporters/FlatBuffersJsonExportor.cs b/src/Luban.Job.Cfg/Source/DataExporters/FlatBuffersJsonExportor.cs new file mode 100644 index 0000000..1806b3e --- /dev/null +++ b/src/Luban.Job.Cfg/Source/DataExporters/FlatBuffersJsonExportor.cs @@ -0,0 +1,82 @@ +using Luban.Job.Cfg.Datas; +using Luban.Job.Cfg.DataSources; +using Luban.Job.Cfg.DataVisitors; +using Luban.Job.Cfg.Defs; +using Luban.Job.Common.Types; +using Luban.Job.Common.TypeVisitors; +using System; +using System.Collections.Generic; +using System.Text.Json; + +namespace Luban.Job.Cfg.DataExporters +{ + class FlatBuffersJsonExportor : JsonExportor + { + public static new FlatBuffersJsonExportor Ins { get; } = new(); + + public void WriteAsTable(List datas, Utf8JsonWriter x) + { + x.WriteStartObject(); + // 如果修改了这个名字,请同时修改table.tpl + x.WritePropertyName("data_list"); + x.WriteStartArray(); + foreach (var d in datas) + { + d.Data.Apply(this, x); + } + x.WriteEndArray(); + x.WriteEndObject(); + } + + public override void Accept(DText type, Utf8JsonWriter x) + { + // 不支持本地化。只能简单起见这么做了 + //x.WriteStartObject(); + //x.WritePropertyName(DText.KEY_NAME); + //x.WriteStringValue(type.Key); + //x.WritePropertyName(DText.TEXT_NAME); + x.WriteStringValue(type.TextOfCurrentAssembly); + //x.WriteEndObject(); + } + + public override void Accept(DBean type, Utf8JsonWriter x) + { + x.WriteStartObject(); + + // flatc 不允许有多余字段 + //if (type.Type.IsAbstractType) + //{ + // x.WritePropertyName(DefBean.TYPE_NAME_KEY); + // x.WriteStringValue(type.ImplType.Name); + //} + + var defFields = type.ImplType.HierarchyFields; + int index = 0; + foreach (var d in type.Fields) + { + var defField = (DefField)defFields[index++]; + + // 特殊处理 bean 多态类型 + // 另外,不生成 xxx:null 这样 + if (d == null || !defField.NeedExport) + { + //x.WriteNullValue(); + } + else + { + // flatbuffers的union类型的json格式,会额外产生一个 xx_type字段。 + // 另外,json格式不支持union出现在容器类型上。 + if (d is DBean beanField && beanField.Type.IsAbstractType) + { + x.WritePropertyName($"{defField.Name}_type"); + x.WriteStringValue(TBean.Create(defField.CType.IsNullable, beanField.ImplType, null).Apply(FlatBuffersTypeNameVisitor.Ins)); + } + + x.WritePropertyName(defField.Name); + d.Apply(this, x); + } + } + x.WriteEndObject(); + } + } +} diff --git a/src/Luban.Job.Cfg/Source/GenArgs.cs b/src/Luban.Job.Cfg/Source/GenArgs.cs index f18cd84..036e79a 100644 --- a/src/Luban.Job.Cfg/Source/GenArgs.cs +++ b/src/Luban.Job.Cfg/Source/GenArgs.cs @@ -8,7 +8,7 @@ namespace Luban.Job.Cfg [Option('s', "service", Required = true, HelpText = "service")] public string Service { get; set; } - [Option("gen_types", Required = true, HelpText = "code_cs_bin,code_cs_json,code_cs_unity_json,code_lua_bin,code_java_bin,code_java_json,code_go_bin,code_go_json,code_cpp_bin,code_python3_json,code_typescript_bin,code_typescript_json,code_rust_json,code_protobuf,code_template,data_bin,data_lua,data_json,data_json2,data_json_monolithic,data_resources,data_template,data_protobuf,convert_json,convert_lua,convert_xlsx . can be multi")] + [Option("gen_types", Required = true, HelpText = "code_cs_bin,code_cs_json,code_cs_unity_json,code_lua_bin,code_java_bin,code_java_json,code_go_bin,code_go_json,code_cpp_bin,code_python3_json,code_typescript_bin,code_typescript_json,code_rust_json,code_protobuf,code_template,code_flatbuffers,data_bin,data_lua,data_json,data_json2,data_json_monolithic,data_resources,data_template,data_protobuf,data_flatbuffers_json,convert_json,convert_lua,convert_xlsx . can be multi")] public string GenType { get; set; } [Option("input_data_dir", Required = true, HelpText = "input data dir")] diff --git a/src/Luban.Job.Cfg/Source/Generate/DataScatterRender.cs b/src/Luban.Job.Cfg/Source/Generate/DataScatterRender.cs index c43df0d..87293b7 100644 --- a/src/Luban.Job.Cfg/Source/Generate/DataScatterRender.cs +++ b/src/Luban.Job.Cfg/Source/Generate/DataScatterRender.cs @@ -15,7 +15,7 @@ namespace Luban.Job.Cfg.Generate [Render("data_yaml")] [Render("data_protobuf")] [Render("data_msgpack")] - [Render("data_flatbuffers")] + [Render("data_flatbuffers_json")] class DataScatterRender : DataRenderBase { public override void Render(GenContext ctx) diff --git a/src/Luban.Job.Cfg/Source/Generate/FlatBuffersSchemaRender.cs b/src/Luban.Job.Cfg/Source/Generate/FlatBuffersSchemaRender.cs new file mode 100644 index 0000000..096e920 --- /dev/null +++ b/src/Luban.Job.Cfg/Source/Generate/FlatBuffersSchemaRender.cs @@ -0,0 +1,106 @@ +using Luban.Common.Protos; +using Luban.Job.Cfg.Defs; +using Luban.Job.Common.Defs; +using Luban.Job.Common.Generate; +using Luban.Job.Common.Tpl; +using Luban.Job.Common.TypeVisitors; +using Luban.Job.Common.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Luban.Job.Cfg.Generate +{ + [Render("code_flatbuffers")] + class FlatBuffersSchemaRender : TemplateCodeRenderBase + { + protected override string RenderTemplateDir => "flatbuffers"; + + public override void Render(GenContext ctx) + { + { + DefAssembly.LocalAssebmly.CurrentLanguage = Common.ELanguage.FLATBUFFERS; + var file = RenderFileUtil.GetFileOrDefault(ctx.GenArgs.OutputCodeMonolithicFile, "schema.fbs"); + var content = this.RenderAll(ctx.ExportTypes); + var md5 = CacheFileUtil.GenMd5AndAddCache(file, string.Join('\n', content)); + ctx.GenCodeFilesInOutputCodeDir.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + } + + { + DefAssembly.LocalAssebmly.CurrentLanguage = Common.ELanguage.FLATBUFFERS; + var file = "convert_json_to_binary.bat"; + var content = this.RenderConvertJson2BinaryBat(ctx.Assembly.TableManagerName, ctx.TopModule, ctx.ExportTables); + var md5 = CacheFileUtil.GenMd5AndAddCache(file, string.Join('\n', content)); + ctx.GenCodeFilesInOutputCodeDir.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + } + { + DefAssembly.LocalAssebmly.CurrentLanguage = Common.ELanguage.FLATBUFFERS; + var file = "convert_json_to_binary.sh"; + var content = this.RenderConvertJson2BinarySh(ctx.Assembly.TableManagerName, ctx.TopModule, ctx.ExportTables); + var md5 = CacheFileUtil.GenMd5AndAddCache(file, string.Join('\n', content)); + ctx.GenCodeFilesInOutputCodeDir.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + } + } + + private string RenderConvertJson2BinaryBat(string name, string module, List tables) + { + var template = StringTemplateManager.Ins.GetTemplate($"config/{RenderTemplateDir}/convert_json_to_binary_bat"); + var result = template.RenderCode(new { + Name = name, + Namespace = module, + Tables = tables, + }); + return result; + } + + private string RenderConvertJson2BinarySh(string name, string module, List tables) + { + var template = StringTemplateManager.Ins.GetTemplate($"config/{RenderTemplateDir}/convert_json_to_binary_sh"); + var result = template.RenderCode(new { + Name = name, + Namespace = module, + Tables = tables, + }); + return result; + } + + private MapKeyValueEntryCollection CollectKeyValueEntry(List beans) + { + var c = new MapKeyValueEntryCollection(); + + foreach (DefBean bean in beans) + { + CollectMapKeyValueEntrysVisitor.Ins.Accept(bean, c); + } + + return c; + } + + public override string RenderAll(List types) + { + var ass = DefAssembly.LocalAssebmly; + var enums = types.Where(t => t is DefEnum).ToList(); + var beans = types.Where(t => t is DefBean).Cast().ToList(); + var tables = types.Where(t => t is DefTable).ToList(); + + var maps = CollectKeyValueEntry(beans).KeyValueEntries.Values; + + // 多态在flatbuffers中为union类型。 + // flatbuffers要求union必须在使用前定义 + // 所以排到前面生成 + beans.Sort((a, b) => (a.IsAbstractType ? 0 : 1) - (b.IsAbstractType ? 0 : 1)); + + var template = StringTemplateManager.Ins.GetTemplate($"config/{RenderTemplateDir}/all"); + var result = template.RenderCode(new { + Namespace = ass.TopModule, + Enums = enums.Select(e => Render((DefEnum)e)).ToList(), + Beans = beans.Select(b => Render(b)).ToList(), + Tables = tables.Select(t => Render((DefTable)t)).ToList(), + Maps = maps, + }); + return result; + } + } +} diff --git a/src/Luban.Job.Cfg/Source/Generate/ProtobufSchemaRenderBase.cs b/src/Luban.Job.Cfg/Source/Generate/ProtobufSchemaRenderBase.cs index 4ea74c0..d6976ad 100644 --- a/src/Luban.Job.Cfg/Source/Generate/ProtobufSchemaRenderBase.cs +++ b/src/Luban.Job.Cfg/Source/Generate/ProtobufSchemaRenderBase.cs @@ -16,7 +16,7 @@ namespace Luban.Job.Cfg.Generate public override void Render(GenContext ctx) { DefAssembly.LocalAssebmly.CurrentLanguage = Common.ELanguage.PROTOBUF; - var file = RenderFileUtil.GetFileOrDefault(ctx.GenArgs.OutputCodeMonolithicFile, "config.proto"); + var file = RenderFileUtil.GetFileOrDefault(ctx.GenArgs.OutputCodeMonolithicFile, "schema.proto"); var content = this.RenderAll(ctx.ExportTypes); var md5 = CacheFileUtil.GenMd5AndAddCache(file, string.Join('\n', content)); ctx.GenCodeFilesInOutputCodeDir.Add(new FileInfo() { FilePath = file, MD5 = md5 }); diff --git a/src/Luban.Job.Cfg/Source/TypeVisitors/IsMultiData.cs b/src/Luban.Job.Cfg/Source/TypeVisitors/IsMultiData.cs index df842ef..9bc1e19 100644 --- a/src/Luban.Job.Cfg/Source/TypeVisitors/IsMultiData.cs +++ b/src/Luban.Job.Cfg/Source/TypeVisitors/IsMultiData.cs @@ -37,20 +37,5 @@ namespace Luban.Job.Cfg.TypeVisitors { return true; } - - public override bool Accept(TVector2 type) - { - return false; - } - - public override bool Accept(TVector3 type) - { - return false; - } - - public override bool Accept(TVector4 type) - { - return false; - } } } diff --git a/src/Luban.Job.Cfg/Source/Utils/DataExporterUtil.cs b/src/Luban.Job.Cfg/Source/Utils/DataExporterUtil.cs index 7f35f8d..f7d7b91 100644 --- a/src/Luban.Job.Cfg/Source/Utils/DataExporterUtil.cs +++ b/src/Luban.Job.Cfg/Source/Utils/DataExporterUtil.cs @@ -63,7 +63,7 @@ namespace Luban.Job.Cfg.Utils Json2Exportor.Ins.WriteAsObject(table, records, jsonWriter); } jsonWriter.Flush(); - return System.Text.Encoding.UTF8.GetString(DataUtil.StreamToBytes(ss)); + return DataUtil.StreamToBytes(ss); } case "data_lua": { @@ -107,6 +107,19 @@ namespace Luban.Job.Cfg.Utils writer.Flush(); return ms.WrittenSpan.ToArray(); } + case "data_flatbuffers_json": + { + var ss = new MemoryStream(); + var jsonWriter = new Utf8JsonWriter(ss, new JsonWriterOptions() + { + Indented = !table.Assembly.OutputCompactJson, + SkipValidation = false, + Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All), + }); + FlatBuffersJsonExportor.Ins.WriteAsTable(records, jsonWriter); + jsonWriter.Flush(); + return DataUtil.StreamToBytes(ss); + } //case "data_erlang": //{ // var content = new StringBuilder(); diff --git a/src/Luban.Job.Common/Source/Defs/DefEnum.cs b/src/Luban.Job.Common/Source/Defs/DefEnum.cs index edbc035..0d4fcac 100644 --- a/src/Luban.Job.Common/Source/Defs/DefEnum.cs +++ b/src/Luban.Job.Common/Source/Defs/DefEnum.cs @@ -49,6 +49,8 @@ namespace Luban.Job.Common.Defs private readonly Dictionary _vaule2Name = new(); + public bool HasZeroValueItem => this.Items.Any(item => item.IntValue == 0); + public bool TryValueByNameOrAlias(string name, out int value) { return _nameOrAlias2Value.TryGetValue(name, out value); diff --git a/src/Luban.Job.Common/Source/Defs/DefTypeBase.cs b/src/Luban.Job.Common/Source/Defs/DefTypeBase.cs index 8703be8..d7dad10 100644 --- a/src/Luban.Job.Common/Source/Defs/DefTypeBase.cs +++ b/src/Luban.Job.Common/Source/Defs/DefTypeBase.cs @@ -57,6 +57,8 @@ namespace Luban.Job.Common.Defs public string PbFullName => TypeUtil.MakePbFullName(Namespace, Name); + public string FlatBuffersFullName => TypeUtil.MakeFlatBuffersFullName(Namespace, Name); + public string Comment { get; protected set; } public string EscapeComment => DefUtil.EscapeCommentByCurrentLanguage(Comment); diff --git a/src/Luban.Job.Common/Source/Defs/TTypeTemplateCommonExtends.cs b/src/Luban.Job.Common/Source/Defs/TTypeTemplateCommonExtends.cs index eacddf2..0db7ab6 100644 --- a/src/Luban.Job.Common/Source/Defs/TTypeTemplateCommonExtends.cs +++ b/src/Luban.Job.Common/Source/Defs/TTypeTemplateCommonExtends.cs @@ -245,6 +245,17 @@ namespace Luban.Job.Common.Defs } } + public static string FlatBuffersDefineType(TType type) + { + return type.Apply(FlatBuffersTypeNameVisitor.Ins); + } + + public static string FlatBuffersTypeMetadata(TType type) + { + string metadata = type.IsNullable || type.Apply(IsFlatBuffersScalarTypeVisitor.Ins) ? "" : $"(required)"; + return metadata; + } + public static bool HasTag(dynamic obj, string attrName) { return obj.HasTag(attrName); diff --git a/src/Luban.Job.Common/Source/ELanguage.cs b/src/Luban.Job.Common/Source/ELanguage.cs index 054604d..e04fbf3 100644 --- a/src/Luban.Job.Common/Source/ELanguage.cs +++ b/src/Luban.Job.Common/Source/ELanguage.cs @@ -14,5 +14,6 @@ namespace Luban.Job.Common ERLANG, RUST, PROTOBUF, + FLATBUFFERS, } } diff --git a/src/Luban.Job.Common/Source/GenArgsBase.cs b/src/Luban.Job.Common/Source/GenArgsBase.cs index aa9cb2a..5d779fb 100644 --- a/src/Luban.Job.Common/Source/GenArgsBase.cs +++ b/src/Luban.Job.Common/Source/GenArgsBase.cs @@ -10,7 +10,7 @@ namespace Luban.Job.Common [Option('c', "output_code_dir", Required = false, HelpText = "output code directory")] public string OutputCodeDir { get; set; } - [Option("output_code_monolithic_file", Required = false, HelpText = "output monolithic code file. only effect when lan=rust,python,typescript,lua")] + [Option("output:code:monolithic_file", Required = false, HelpText = "output monolithic code file. only effect when lan=rust,python,typescript,lua,protobuf,flatbuffers")] public string OutputCodeMonolithicFile { get; set; } [Option("naming_convention:module", Required = false, HelpText = "naming convention of module. can be language_recommend,none,camelCase,PascalCase,under_scores")] diff --git a/src/Luban.Job.Common/Source/TypeVisitors/CollectMapKeyValueEntrysVisitor.cs b/src/Luban.Job.Common/Source/TypeVisitors/CollectMapKeyValueEntrysVisitor.cs new file mode 100644 index 0000000..b35a5bc --- /dev/null +++ b/src/Luban.Job.Common/Source/TypeVisitors/CollectMapKeyValueEntrysVisitor.cs @@ -0,0 +1,85 @@ +using Luban.Job.Common.Defs; +using Luban.Job.Common.Types; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Luban.Job.Common.TypeVisitors +{ + public class MapKeyValueEntryCollection + { + public Dictionary KeyValueEntries { get; } = new(); + + public HashSet VisitedTypes { get; } = new(); + } + + public class CollectMapKeyValueEntrysVisitor : DecoratorActionVisitor + { + public static CollectMapKeyValueEntrysVisitor Ins { get; } = new(); + + + public override void DoAccept(TType type, MapKeyValueEntryCollection x) + { + + } + + public void Accept(DefBeanBase bean, MapKeyValueEntryCollection x) + { + if (!x.VisitedTypes.Add(bean.FullName)) + { + return; + } + if (bean.IsAbstractType) + { + foreach (var c in bean.HierarchyNotAbstractChildren) + { + Accept(c, x); + } + } + else + { + foreach (var field in bean.HierarchyFields) + { + field.CType.Apply(this, x); + } + } + } + + private static string MakeKeyValueType(TMap type) + { + return $"{type.KeyType.Apply(FlatBuffersTypeNameVisitor.Ins)}_{type.ValueType.Apply(FlatBuffersTypeNameVisitor.Ins)}"; + } + + public override void Accept(TBean type, MapKeyValueEntryCollection x) + { + Accept(type.Bean, x); + } + + public override void Accept(TArray type, MapKeyValueEntryCollection x) + { + if (type.ElementType is TBean tbean) + { + tbean.Apply(this, x); + } + } + + public override void Accept(TList type, MapKeyValueEntryCollection x) + { + if (type.ElementType is TBean tbean) + { + tbean.Apply(this, x); + } + } + + public override void Accept(TMap type, MapKeyValueEntryCollection x) + { + x.KeyValueEntries[MakeKeyValueType(type)] = type; + if (type.ElementType is TBean tbean) + { + tbean.Apply(this, x); + } + } + } +} diff --git a/src/Luban.Job.Common/Source/TypeVisitors/DecoratorActionVisitor.cs b/src/Luban.Job.Common/Source/TypeVisitors/DecoratorActionVisitor.cs index fc67d1b..504d387 100644 --- a/src/Luban.Job.Common/Source/TypeVisitors/DecoratorActionVisitor.cs +++ b/src/Luban.Job.Common/Source/TypeVisitors/DecoratorActionVisitor.cs @@ -66,12 +66,31 @@ namespace Luban.Job.Common.TypeVisitors DoAccept(type, x); } + public virtual void Accept(TText type, T x) + { + DoAccept(type, x); + } + public virtual void Accept(TBytes type, T x) { DoAccept(type, x); } - public virtual void Accept(TText type, T x) + public virtual void Accept(TDateTime type, T x) + { + DoAccept(type, x); + } + public virtual void Accept(TVector2 type, T x) + { + DoAccept(type, x); + } + + public virtual void Accept(TVector3 type, T x) + { + DoAccept(type, x); + } + + public virtual void Accept(TVector4 type, T x) { DoAccept(type, x); } @@ -101,26 +120,6 @@ namespace Luban.Job.Common.TypeVisitors DoAccept(type, x); } - public virtual void Accept(TVector2 type, T x) - { - DoAccept(type, x); - } - - public virtual void Accept(TVector3 type, T x) - { - DoAccept(type, x); - } - - public virtual void Accept(TVector4 type, T x) - { - DoAccept(type, x); - } - - public virtual void Accept(TDateTime type, T x) - { - DoAccept(type, x); - } - } public abstract class DecoratorActionVisitor : ITypeActionVisitor @@ -188,12 +187,32 @@ namespace Luban.Job.Common.TypeVisitors DoAccept(type, x, y); } + public virtual void Accept(TText type, T1 x, T2 y) + { + DoAccept(type, x, y); + } + public virtual void Accept(TBytes type, T1 x, T2 y) { DoAccept(type, x, y); } - public virtual void Accept(TText type, T1 x, T2 y) + public virtual void Accept(TDateTime type, T1 x, T2 y) + { + DoAccept(type, x, y); + } + + public virtual void Accept(TVector2 type, T1 x, T2 y) + { + DoAccept(type, x, y); + } + + public virtual void Accept(TVector3 type, T1 x, T2 y) + { + DoAccept(type, x, y); + } + + public virtual void Accept(TVector4 type, T1 x, T2 y) { DoAccept(type, x, y); } @@ -222,28 +241,5 @@ namespace Luban.Job.Common.TypeVisitors { DoAccept(type, x, y); } - - public virtual void Accept(TVector2 type, T1 x, T2 y) - { - DoAccept(type, x, y); - } - - public virtual void Accept(TVector3 type, T1 x, T2 y) - { - DoAccept(type, x, y); - } - - public virtual void Accept(TVector4 type, T1 x, T2 y) - { - DoAccept(type, x, y); - } - - public virtual void Accept(TDateTime type, T1 x, T2 y) - { - DoAccept(type, x, y); - } - - - } } diff --git a/src/Luban.Job.Common/Source/TypeVisitors/FlatBuffersTypeNameVisitor.cs b/src/Luban.Job.Common/Source/TypeVisitors/FlatBuffersTypeNameVisitor.cs new file mode 100644 index 0000000..d9df4ca --- /dev/null +++ b/src/Luban.Job.Common/Source/TypeVisitors/FlatBuffersTypeNameVisitor.cs @@ -0,0 +1,129 @@ +using Luban.Job.Common.Types; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Luban.Job.Common.TypeVisitors +{ + public class FlatBuffersTypeNameVisitor : ITypeFuncVisitor + { + public static FlatBuffersTypeNameVisitor Ins { get; } = new(); + + public string Accept(TBool type) + { + return "bool"; + } + + public string Accept(TByte type) + { + return "ubyte"; + } + + public string Accept(TShort type) + { + return "int16"; + } + + public string Accept(TFshort type) + { + return "int16"; + } + + public string Accept(TInt type) + { + return "int32"; + } + + public string Accept(TFint type) + { + return "int32"; + } + + public string Accept(TLong type) + { + return "int64"; + } + + public string Accept(TFlong type) + { + return "int64"; + } + + public string Accept(TFloat type) + { + return "float32"; + } + + public string Accept(TDouble type) + { + return "float64"; + } + + public string Accept(TEnum type) + { + return type.DefineEnum.FlatBuffersFullName; + } + + public string Accept(TString type) + { + return "string"; + } + + public string Accept(TText type) + { + return "string"; + } + + public string Accept(TBytes type) + { + return "[ubyte]"; + } + + public string Accept(TVector2 type) + { + return "Vector2"; + } + + public string Accept(TVector3 type) + { + return "Vector3"; + } + + public string Accept(TVector4 type) + { + return "Vector4"; + } + + public string Accept(TDateTime type) + { + return "int32"; + } + + public string Accept(TBean type) + { + return type.Bean.FlatBuffersFullName; + } + + public string Accept(TArray type) + { + return $"[{type.ElementType.Apply(this)}]"; + } + + public string Accept(TList type) + { + return $"[{type.ElementType.Apply(this)}]"; + } + + public string Accept(TSet type) + { + return $"[{type.ElementType.Apply(this)}]"; + } + + public string Accept(TMap type) + { + return $"[KeyValue_{type.KeyType.Apply(this)}_{type.ValueType.Apply(this)}]"; + } + } +} diff --git a/src/Luban.Job.Common/Source/TypeVisitors/IsFlatBuffersScalarTypeVisitor.cs b/src/Luban.Job.Common/Source/TypeVisitors/IsFlatBuffersScalarTypeVisitor.cs new file mode 100644 index 0000000..2f32c38 --- /dev/null +++ b/src/Luban.Job.Common/Source/TypeVisitors/IsFlatBuffersScalarTypeVisitor.cs @@ -0,0 +1,59 @@ +using Luban.Job.Common.Types; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Luban.Job.Common.TypeVisitors +{ + public class IsFlatBuffersScalarTypeVisitor : AllTrueVisitor + { + public static IsFlatBuffersScalarTypeVisitor Ins { get; } = new(); + + public override bool Accept(TBytes type) + { + return false; + } + + public override bool Accept(TBean type) + { + return false; + } + + public override bool Accept(TArray type) + { + return false; + } + + public override bool Accept(TList type) + { + return false; + } + + public override bool Accept(TSet type) + { + return false; + } + + public override bool Accept(TMap type) + { + return false; + } + + public override bool Accept(TVector2 type) + { + return false; + } + + public override bool Accept(TVector3 type) + { + return false; + } + + public override bool Accept(TVector4 type) + { + return false; + } + } +} diff --git a/src/Luban.Job.Common/Source/TypeVisitors/ProtobufTypeNameVisitor.cs b/src/Luban.Job.Common/Source/TypeVisitors/ProtobufTypeNameVisitor.cs index e862423..d46c1ea 100644 --- a/src/Luban.Job.Common/Source/TypeVisitors/ProtobufTypeNameVisitor.cs +++ b/src/Luban.Job.Common/Source/TypeVisitors/ProtobufTypeNameVisitor.cs @@ -103,7 +103,7 @@ namespace Luban.Job.Common.TypeVisitors public string Accept(TBean type) { - return type.Bean.GoFullName; + return type.Bean.PbFullName; } public string Accept(TArray type) diff --git a/src/Luban.Job.Common/Source/Utils/RenderFileUtil.cs b/src/Luban.Job.Common/Source/Utils/RenderFileUtil.cs index 9820cf8..3cd155d 100644 --- a/src/Luban.Job.Common/Source/Utils/RenderFileUtil.cs +++ b/src/Luban.Job.Common/Source/Utils/RenderFileUtil.cs @@ -102,6 +102,7 @@ namespace Luban.Job.Common.Utils ELanguage.ERLANG => "erlang", ELanguage.RUST => "rust", ELanguage.PROTOBUF => "protobuf", + ELanguage.FLATBUFFERS => "flatbuffers", _ => throw new Exception($"not support common template dir for lan:{lan}"), }; } diff --git a/src/Luban.Server/Luban.Server.csproj b/src/Luban.Server/Luban.Server.csproj index 41bbd0f..eefed7c 100644 --- a/src/Luban.Server/Luban.Server.csproj +++ b/src/Luban.Server/Luban.Server.csproj @@ -52,6 +52,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -121,6 +124,24 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest diff --git a/src/Luban.Server/Templates/common/flatbuffers/enum.tpl b/src/Luban.Server/Templates/common/flatbuffers/enum.tpl new file mode 100644 index 0000000..7a135cc --- /dev/null +++ b/src/Luban.Server/Templates/common/flatbuffers/enum.tpl @@ -0,0 +1,15 @@ +{{~ + name = x.name + namespace_with_top_module = x.namespace_with_top_module + comment = x.comment + items = x.items +~}} + +enum {{x.flat_buffers_full_name}}:int { + {{~if !x.has_zero_value_item~}} + __GENERATE_DEFAULT_VALUE = 0, + {{~end~}} + {{~for item in items ~}} + {{x.pb_full_name}}_{{item.name}} = {{item.int_value}}, + {{~end~}} +} \ No newline at end of file diff --git a/src/Luban.Server/Templates/config/flatbuffers/all.tpl b/src/Luban.Server/Templates/config/flatbuffers/all.tpl new file mode 100644 index 0000000..0eedad0 --- /dev/null +++ b/src/Luban.Server/Templates/config/flatbuffers/all.tpl @@ -0,0 +1,41 @@ +namespace {{x.namespace}}; + +// luban internal types begin +struct Vector2 { + x:float; + y:float; +} + +struct Vector3 { + x:float; + y:float; + z:float; +} + +struct Vector4 { + x:float; + y:float; + z:float; + w:float; +} +// luban internal types end + +{{~for enum in x.enums ~}} +{{enum}} +{{~end~}} + +{{~for bean in x.beans~}} +{{bean}} +{{~end~}} + +{{~for map in x.maps~}} +table KeyValue_{{flat_buffers_define_type map.key_type}}_{{flat_buffers_define_type map.value_type}} { + key: {{flat_buffers_define_type map.key_type}}{{flat_buffers_type_metadata map.key_type}}; + value: {{flat_buffers_define_type map.value_type}}{{flat_buffers_type_metadata map.value_type}}; +} +{{~end~}} + +{{~for table in x.tables~}} +{{table}} +{{~end~}} + diff --git a/src/Luban.Server/Templates/config/flatbuffers/bean.tpl b/src/Luban.Server/Templates/config/flatbuffers/bean.tpl new file mode 100644 index 0000000..146f78b --- /dev/null +++ b/src/Luban.Server/Templates/config/flatbuffers/bean.tpl @@ -0,0 +1,20 @@ +{{~ + name = x.name + parent_def_type = x.parent_def_type + export_fields = x.export_fields + hierarchy_export_fields = x.hierarchy_export_fields +~}} + +{{~if x.is_abstract_type ~}} +union {{x.flat_buffers_full_name}} { + {{~for c in x.hierarchy_not_abstract_children~}} + {{c.flat_buffers_full_name}}, + {{~end~}} +} +{{~else~}} +table {{x.flat_buffers_full_name}} { + {{~for f in hierarchy_export_fields ~}} + {{f.name}}:{{flat_buffers_define_type f.ctype}}{{flat_buffers_type_metadata f.ctype}}; + {{~end~}} +} +{{~end~}} diff --git a/src/Luban.Server/Templates/config/flatbuffers/convert_json_to_binary_bat.tpl b/src/Luban.Server/Templates/config/flatbuffers/convert_json_to_binary_bat.tpl new file mode 100644 index 0000000..0c4fc24 --- /dev/null +++ b/src/Luban.Server/Templates/config/flatbuffers/convert_json_to_binary_bat.tpl @@ -0,0 +1,16 @@ +{{~ + name = x.name + namespace = x.namespace + tables = x.tables +~}} + +echo off + +set FLATC=%1 +set SCHEMA_FILE=%2 +set DATA_DIR=%3 +set OUTPUT_DIR=%4 + +{{~for table in tables~}} +%FLATC% -o %OUTPUT_DIR% -b %SCHEMA_FILE% --root-type {{if namespace != ''}}{{namespace}}.{{end}}{{table.flat_buffers_full_name}} %DATA_DIR%\{{table.output_data_file}}.json +{{~end~}} \ No newline at end of file diff --git a/src/Luban.Server/Templates/config/flatbuffers/convert_json_to_binary_sh.tpl b/src/Luban.Server/Templates/config/flatbuffers/convert_json_to_binary_sh.tpl new file mode 100644 index 0000000..28a882b --- /dev/null +++ b/src/Luban.Server/Templates/config/flatbuffers/convert_json_to_binary_sh.tpl @@ -0,0 +1,16 @@ +{{~ + name = x.name + namespace = x.namespace + tables = x.tables +~}} + +@echo off + +FLATC=$1 +SCHEMA_FILE=$2 +DATA_DIR=$3 +OUTPUT_DIR=$4 + +{{~for table in tables~}} +$FLATC -o $OUTPUT_DIR -b $SCHEMA_FILE --root-type {{if namespace != ''}}{{namespace}}.{{end}}{{table.flat_buffers_full_name}} $DATA_DIR/{{table.output_data_file}}.json +{{~end~}} \ No newline at end of file diff --git a/src/Luban.Server/Templates/config/flatbuffers/table.tpl b/src/Luban.Server/Templates/config/flatbuffers/table.tpl new file mode 100644 index 0000000..78aa1be --- /dev/null +++ b/src/Luban.Server/Templates/config/flatbuffers/table.tpl @@ -0,0 +1,12 @@ +{{~ + name = x.name + key_type = x.key_ttype + value_type = x.value_ttype +~}} + +table {{x.flat_buffers_full_name}} { + // WARN! The name 'data_list' is used by FlatBuffersJsonExporter. don't modify it! + data_list:[{{flat_buffers_define_type value_type}}](required); +} + +root_type {{x.flat_buffers_full_name}}; \ No newline at end of file diff --git a/src/Luban.Server/Templates/config/flatbuffers/tables.tpl b/src/Luban.Server/Templates/config/flatbuffers/tables.tpl new file mode 100644 index 0000000..827db8e --- /dev/null +++ b/src/Luban.Server/Templates/config/flatbuffers/tables.tpl @@ -0,0 +1,5 @@ +{{~ + name = x.name + namespace = x.namespace + tables = x.tables +~}} \ No newline at end of file diff --git a/src/Luban.Server/Templates/config/protobuf2/tables.tpl b/src/Luban.Server/Templates/config/protobuf2/tables.tpl index 8fd56d8..827db8e 100644 --- a/src/Luban.Server/Templates/config/protobuf2/tables.tpl +++ b/src/Luban.Server/Templates/config/protobuf2/tables.tpl @@ -2,12 +2,4 @@ name = x.name namespace = x.namespace tables = x.tables -~}} - -message {{name}} { -{{~index = 0~}} -{{~for table in tables~}} - {{~index = index + 1~}} - {{table.pb_full_name}} {{name}} = {{index}}; -{{~end~}} -} +~}} \ No newline at end of file