From c29c00bbe369995201e721afdf40376df57d7785 Mon Sep 17 00:00:00 2001 From: walon Date: Mon, 27 Sep 2021 12:52:09 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E7=89=B9=E6=80=A7=E3=80=91=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E7=94=9F=E6=88=90=E7=B1=BB=E5=9E=8B=20cfg=20code=5Fru?= =?UTF-8?q?st=5Fjson=EF=BC=88=E5=A4=9A=E6=80=81=E6=94=AF=E6=8C=81=E6=9C=89?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E9=97=AE=E9=A2=98=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +- src/Luban.Common/Source/Utils/TypeUtil.cs | 5 + src/Luban.Job.Cfg/Source/GenArgs.cs | 2 +- .../Source/Generate/RustCodeJsonRender.cs | 70 ++++++++++ .../RustJsonConstructorVisitor.cs | 27 ++++ .../RustJsonUnderingConstructorVisitor.cs | 131 ++++++++++++++++++ .../Source/Utils/TTypeTemplateExtends.cs | 5 + .../Source/Defs/DefFieldBase.cs | 2 + .../Source/Defs/DefTypeBase.cs | 2 + .../Source/Defs/TTypeTemplateCommonExtends.cs | 17 +++ src/Luban.Job.Common/Source/ELanguage.cs | 1 + .../TypeVisitors/RustTypeNameVisitor.cs | 35 +++++ .../RustTypeUnderlyingNameVisitor.cs | 124 +++++++++++++++++ .../Source/Utils/RenderFileUtil.cs | 2 + .../Source/Utils/RenderUtil.cs | 20 +++ src/Luban.Server/Luban.Server.csproj | 18 +++ .../Templates/common/rust/const.tpl | 18 +++ .../Templates/common/rust/enum.tpl | 18 +++ .../Templates/config/rust_json/bean.tpl | 31 +++++ .../Templates/config/rust_json/mod_header.tpl | 59 ++++++++ .../Templates/config/rust_json/table.tpl | 65 +++++++++ .../Templates/config/rust_json/tables.tpl | 32 +++++ 22 files changed, 685 insertions(+), 4 deletions(-) create mode 100644 src/Luban.Job.Cfg/Source/Generate/RustCodeJsonRender.cs create mode 100644 src/Luban.Job.Cfg/Source/TypeVisitors/RustJsonConstructorVisitor.cs create mode 100644 src/Luban.Job.Cfg/Source/TypeVisitors/RustJsonUnderingConstructorVisitor.cs create mode 100644 src/Luban.Job.Common/Source/TypeVisitors/RustTypeNameVisitor.cs create mode 100644 src/Luban.Job.Common/Source/TypeVisitors/RustTypeUnderlyingNameVisitor.cs create mode 100644 src/Luban.Server/Templates/common/rust/const.tpl create mode 100644 src/Luban.Server/Templates/common/rust/enum.tpl create mode 100644 src/Luban.Server/Templates/config/rust_json/bean.tpl create mode 100644 src/Luban.Server/Templates/config/rust_json/mod_header.tpl create mode 100644 src/Luban.Server/Templates/config/rust_json/table.tpl create mode 100644 src/Luban.Server/Templates/config/rust_json/tables.tpl diff --git a/README.md b/README.md index 9e8dc45..2306ca2 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ ## 介绍 -目前已经存在很多导表工具(如tabtoy、xls2json),它们功能多为excel文件到其他格式的转换工具及简单代码生成器,勉强满足中小类型项目的需求。 +目前存在的配置工具,它们功能多为excel文件到json之类格式的转换工具及简单代码生成器,勉强满足中小类型项目的需求。 在中大型游戏项目中,基本都会有技能、行为树之类的复杂功能。这些功能有非常复杂的数据结构,往往使用自定义编辑器制作,并以json、xml等文件格式保存。就算常规的excel表,也经常出现复杂的数据结构需求。这些简单工具面对此类需求要么无法支持,要么就强迫策划和程序使用拆表等奇技淫巧,严重影响开发效率。 luban相较于常规的excel导表工具有以下核心优势: @@ -77,6 +77,7 @@ luban相较于常规的excel导表工具有以下核心优势: - js 和 typescript (3.0+) - python (3.0+) - erlang (18+) + - rust (1.5+) - 支持主流引擎和平台 - unity + c# - unity + [tolua](https://github.com/topameng/tolua)、[xlua](https://github.com/Tencent/xLua) @@ -96,8 +97,6 @@ luban相较于常规的excel导表工具有以下核心优势: - 其他所有支持lua的引擎和平台 - 其他所有支持js的引擎和平台 ------ - ## 快速上手 以创建一个道具表为例 diff --git a/src/Luban.Common/Source/Utils/TypeUtil.cs b/src/Luban.Common/Source/Utils/TypeUtil.cs index 413b7fe..2f03708 100644 --- a/src/Luban.Common/Source/Utils/TypeUtil.cs +++ b/src/Luban.Common/Source/Utils/TypeUtil.cs @@ -121,6 +121,11 @@ namespace Luban.Common.Utils return module.Replace('.', '_') + "_" + name; } + public static string MakeRustFullName(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/GenArgs.cs b/src/Luban.Job.Cfg/Source/GenArgs.cs index fa1e96d..e408370 100644 --- a/src/Luban.Job.Cfg/Source/GenArgs.cs +++ b/src/Luban.Job.Cfg/Source/GenArgs.cs @@ -20,7 +20,7 @@ namespace Luban.Job.Cfg [Option("output_data_json_monolithic_file", Required = false, HelpText = "output monolithic json file")] public string OutputDataJsonMonolithicFile { 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,data_bin,data_lua,data_json,data_json2,data_json_monolithic,data_resources,data_template . 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,data_bin,data_lua,data_json,data_json2,data_json_monolithic,data_resources,data_template . can be multi")] public string GenType { get; set; } [Option("template_name", Required = false, HelpText = "template name. use with gen_types=data_template")] diff --git a/src/Luban.Job.Cfg/Source/Generate/RustCodeJsonRender.cs b/src/Luban.Job.Cfg/Source/Generate/RustCodeJsonRender.cs new file mode 100644 index 0000000..3aeb132 --- /dev/null +++ b/src/Luban.Job.Cfg/Source/Generate/RustCodeJsonRender.cs @@ -0,0 +1,70 @@ +using Luban.Job.Cfg.Defs; +using Luban.Job.Common.Defs; +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_rust_json")] + class RustCodeJsonRender : CodeRenderBase + { + public override void Render(GenContext ctx) + { + string genType = ctx.GenType; + var args = ctx.GenArgs; + ctx.Render = this; + ctx.Lan = RenderFileUtil.GetLanguage(genType); + + var lines = new List(); + GenerateCodeMonolithic(ctx, "mod.rs", lines, ls => + { + var template = StringTemplateUtil.GetTemplate("config/rust_json/mod_header"); + var result = template.RenderCode(ctx.ExportTypes); + ls.Add(result); + }, null); + } + + public override string Render(DefConst c) + { + return RenderUtil.RenderRustConstClass(c); + } + + public override string Render(DefEnum e) + { + return RenderUtil.RenderRustEnumClass(e); + } + + public override string Render(DefBean b) + { + var template = StringTemplateUtil.GetTemplate("config/rust_json/bean"); + var result = template.RenderCode(b); + + return result; + } + + public override string Render(DefTable p) + { + var template = StringTemplateUtil.GetTemplate("config/rust_json/table"); + var result = template.RenderCode(p); + + return result; + } + + public override string RenderService(string name, string module, List tables) + { + var template = StringTemplateUtil.GetTemplate("config/rust_json/tables"); + var result = template.RenderCode(new + { + Name = name, + Namespace = module, + Tables = tables, + }); + + return result; + } + } +} diff --git a/src/Luban.Job.Cfg/Source/TypeVisitors/RustJsonConstructorVisitor.cs b/src/Luban.Job.Cfg/Source/TypeVisitors/RustJsonConstructorVisitor.cs new file mode 100644 index 0000000..073a833 --- /dev/null +++ b/src/Luban.Job.Cfg/Source/TypeVisitors/RustJsonConstructorVisitor.cs @@ -0,0 +1,27 @@ +using Luban.Job.Common.Types; +using Luban.Job.Common.TypeVisitors; + +namespace Luban.Job.Cfg.TypeVisitors +{ + class RustJsonConstructorVisitor : DecoratorFuncVisitor + { + public static RustJsonConstructorVisitor Ins { get; } = new(); + + public override string DoAccept(TType type, string jsonFieldName) + { + if (type.IsNullable) + { + return $"if !{jsonFieldName}.is_null() {{ Some({type.Apply(RustJsonUnderingConstructorVisitor.Ins, jsonFieldName)}) }} else {{ None }}"; + } + else + { + return type.Apply(RustJsonUnderingConstructorVisitor.Ins, jsonFieldName); + } + } + + //public override string Accept(TBean type, string bytebufName, string fieldName) + //{ + // return type.Apply(TypescriptJsonUnderingConstructorVisitor.Ins, bytebufName, fieldName); + //} + } +} diff --git a/src/Luban.Job.Cfg/Source/TypeVisitors/RustJsonUnderingConstructorVisitor.cs b/src/Luban.Job.Cfg/Source/TypeVisitors/RustJsonUnderingConstructorVisitor.cs new file mode 100644 index 0000000..20bfbb1 --- /dev/null +++ b/src/Luban.Job.Cfg/Source/TypeVisitors/RustJsonUnderingConstructorVisitor.cs @@ -0,0 +1,131 @@ +using Luban.Job.Cfg.Datas; +using Luban.Job.Common.Types; +using Luban.Job.Common.TypeVisitors; + +namespace Luban.Job.Cfg.TypeVisitors +{ + class RustJsonUnderingConstructorVisitor : ITypeFuncVisitor + { + public static RustJsonUnderingConstructorVisitor Ins { get; } = new(); + + private static string AsType(string jsonVarName, string rawType) + { + return $"match {jsonVarName}.as_{rawType}() {{ Some(__x__) => __x__, None => return Err(LoadError{{}}) }}"; + } + + public string Accept(TBool type, string jsonVarName) + { + return AsType(jsonVarName, "bool"); + } + + public string Accept(TByte type, string jsonVarName) + { + return AsType(jsonVarName, "u8"); + } + + public string Accept(TShort type, string jsonVarName) + { + return AsType(jsonVarName, "i16"); + } + + public string Accept(TFshort type, string jsonVarName) + { + return AsType(jsonVarName, "i16"); + } + + public string Accept(TInt type, string jsonVarName) + { + return AsType(jsonVarName, "i32"); + } + + public string Accept(TFint type, string jsonVarName) + { + return AsType(jsonVarName, "i32"); + } + + public string Accept(TLong type, string jsonVarName) + { + return AsType(jsonVarName, "i64"); + } + + public string Accept(TFlong type, string jsonVarName) + { + return AsType(jsonVarName, "i64"); + } + + public string Accept(TFloat type, string jsonVarName) + { + return AsType(jsonVarName, "f32"); + } + + public string Accept(TDouble type, string jsonVarName) + { + return AsType(jsonVarName, "f64"); + } + + public string Accept(TEnum type, string jsonVarName) + { + return AsType(jsonVarName, "i32"); + } + + public string Accept(TString type, string jsonVarName) + { + return $"match {jsonVarName}.as_str() {{ Some(__x__) => __x__.to_string(), None => return Err(LoadError{{}}) }}"; + } + + public string Accept(TBytes type, string jsonVarName) + { + throw new System.NotSupportedException(); + } + + public string Accept(TText type, string jsonVarName) + { + return $"{{ if !{jsonVarName}[\"{DText.KEY_NAME}\"].is_string() {{ return Err(LoadError{{}}); }} match {jsonVarName}[\"{DText.TEXT_NAME}\"].as_str() {{ Some(__x__) => __x__.to_string(), None => return Err(LoadError{{}}) }} }}"; + } + + public string Accept(TBean type, string jsonVarName) + { + return $"{type.Bean.RustFullName}::new(&{jsonVarName})?"; + } + + public string Accept(TArray type, string jsonVarName) + { + return $"{{ if !{jsonVarName}.is_array() {{ return Err(LoadError{{}}); }} let mut __list__ = vec![]; for __e in {jsonVarName}.members() {{ __list__.push({type.ElementType.Apply(this, "__e")}); }} __list__}}"; + } + + public string Accept(TList type, string jsonVarName) + { + return $"{{ if !{jsonVarName}.is_array() {{ return Err(LoadError{{}}); }} let mut __list__ = vec![]; for __e in {jsonVarName}.members() {{ __list__.push({type.ElementType.Apply(this, "__e")}); }} __list__}}"; + } + + public string Accept(TSet type, string jsonVarName) + { + return $"{{ if !{jsonVarName}.is_array() {{ return Err(LoadError{{}}); }} let mut __set__ = std::collections::HashSet::new(); for __e in {jsonVarName}.members() {{ __set__.insert({type.ElementType.Apply(this, "__e")}); }} __set__}}"; + } + + public string Accept(TMap type, string jsonVarName) + { + return $"{{ if !{jsonVarName}.is_array() {{ return Err(LoadError{{}}); }} let mut __map__ = std::collections::HashMap::new(); for __e in {jsonVarName}.members() {{ __map__.insert({type.KeyType.Apply(this, "__e[0]")}, {type.ValueType.Apply(this, "__e[1]")}); }} __map__}}"; + } + + public string Accept(TVector2 type, string jsonVarName) + { + return $"Vector2::new(&{jsonVarName})?"; + } + + public string Accept(TVector3 type, string jsonVarName) + { + return $"Vector3::new(&{jsonVarName})?"; + } + + public string Accept(TVector4 type, string jsonVarName) + { + return $"Vector4::new(&{jsonVarName})?"; + } + + public string Accept(TDateTime type, string jsonVarName) + { + return AsType(jsonVarName, "i32"); + } + } +} diff --git a/src/Luban.Job.Cfg/Source/Utils/TTypeTemplateExtends.cs b/src/Luban.Job.Cfg/Source/Utils/TTypeTemplateExtends.cs index b465773..26f18f4 100644 --- a/src/Luban.Job.Cfg/Source/Utils/TTypeTemplateExtends.cs +++ b/src/Luban.Job.Cfg/Source/Utils/TTypeTemplateExtends.cs @@ -217,6 +217,11 @@ namespace Luban.Job.Cfg.Utils } } + public static string RustJsonConstructor(string jsonFieldName, TType type) + { + return type.Apply(RustJsonConstructorVisitor.Ins, jsonFieldName); + } + //public static string DeserializeTextKeyField(DefField field, string lan, string bufName) //{ // switch (lan) diff --git a/src/Luban.Job.Common/Source/Defs/DefFieldBase.cs b/src/Luban.Job.Common/Source/Defs/DefFieldBase.cs index e04b322..7b3491f 100644 --- a/src/Luban.Job.Common/Source/Defs/DefFieldBase.cs +++ b/src/Luban.Job.Common/Source/Defs/DefFieldBase.cs @@ -60,6 +60,8 @@ namespace Luban.Job.Common.Defs public string GoStyleName => CsStyleName; + public string RustStyleName => Name != "type" ? Name : "r#" + Name; + //public string GoStyleAssignName => CType.IsNullable ? "*" + CsStyleName : CsStyleName; public string Type { get; } diff --git a/src/Luban.Job.Common/Source/Defs/DefTypeBase.cs b/src/Luban.Job.Common/Source/Defs/DefTypeBase.cs index 3e53d4e..7f7dbe2 100644 --- a/src/Luban.Job.Common/Source/Defs/DefTypeBase.cs +++ b/src/Luban.Job.Common/Source/Defs/DefTypeBase.cs @@ -44,6 +44,8 @@ namespace Luban.Job.Common.Defs public string PyFullName => TypeUtil.MakePyFullName(Namespace, Name); + public string RustFullName => TypeUtil.MakeRustFullName(Namespace, Name); + public string Comment { get; protected set; } public Dictionary Tags { get; protected set; } diff --git a/src/Luban.Job.Common/Source/Defs/TTypeTemplateCommonExtends.cs b/src/Luban.Job.Common/Source/Defs/TTypeTemplateCommonExtends.cs index 7842fd0..5778b4c 100644 --- a/src/Luban.Job.Common/Source/Defs/TTypeTemplateCommonExtends.cs +++ b/src/Luban.Job.Common/Source/Defs/TTypeTemplateCommonExtends.cs @@ -163,6 +163,23 @@ namespace Luban.Job.Common.Defs return type.Apply(LuaConstValueVisitor.Ins, value); } + + public static string RustClassName(TBean type) + { + return type.Bean.RustFullName; + } + + public static string RustDefineType(TType type) + { + return type.Apply(RustTypeNameVisitor.Ins); + } + + + public static string RustConstValue(TType type, string value) + { + return type.Apply(LuaConstValueVisitor.Ins, value); + } + 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 13725cf..6bd7456 100644 --- a/src/Luban.Job.Common/Source/ELanguage.cs +++ b/src/Luban.Job.Common/Source/ELanguage.cs @@ -11,5 +11,6 @@ namespace Luban.Job.Common TYPESCRIPT, PYTHON, ERLANG, + RUST, } } diff --git a/src/Luban.Job.Common/Source/TypeVisitors/RustTypeNameVisitor.cs b/src/Luban.Job.Common/Source/TypeVisitors/RustTypeNameVisitor.cs new file mode 100644 index 0000000..548bc17 --- /dev/null +++ b/src/Luban.Job.Common/Source/TypeVisitors/RustTypeNameVisitor.cs @@ -0,0 +1,35 @@ +using Luban.Job.Common.Types; + +namespace Luban.Job.Common.TypeVisitors +{ + public class RustTypeNameVisitor : DecoratorFuncVisitor + { + public static RustTypeNameVisitor Ins { get; } = new(); + + public override string DoAccept(TType type) + { + if (type.IsNullable) + { + if (type.IsBean) + { + return $"std::option::Option>"; + } + else + { + return $"std::option::Option<{type.Apply(RustTypeUnderlyingNameVisitor.Ins)}>"; + } + } + else + { + if (type.IsBean) + { + return $"std::rc::Rc<{type.Apply(RustTypeUnderlyingNameVisitor.Ins)}>"; + } + else + { + return type.Apply(RustTypeUnderlyingNameVisitor.Ins); + } + } + } + } +} diff --git a/src/Luban.Job.Common/Source/TypeVisitors/RustTypeUnderlyingNameVisitor.cs b/src/Luban.Job.Common/Source/TypeVisitors/RustTypeUnderlyingNameVisitor.cs new file mode 100644 index 0000000..f30c60c --- /dev/null +++ b/src/Luban.Job.Common/Source/TypeVisitors/RustTypeUnderlyingNameVisitor.cs @@ -0,0 +1,124 @@ +using Luban.Job.Common.Types; + +namespace Luban.Job.Common.TypeVisitors +{ + public class RustTypeUnderlyingNameVisitor : ITypeFuncVisitor + { + public static RustTypeUnderlyingNameVisitor Ins { get; } = new(); + + public string Accept(TBool type) + { + return "bool"; + } + + public string Accept(TByte type) + { + return "u8"; + } + + public string Accept(TShort type) + { + return "i16"; + } + + public string Accept(TFshort type) + { + return "i16"; + } + + public string Accept(TInt type) + { + return "i32"; + } + + public string Accept(TFint type) + { + return "i32"; + } + + public string Accept(TLong type) + { + return "i64"; + } + + public string Accept(TFlong type) + { + return "i64"; + } + + public string Accept(TFloat type) + { + return "f32"; + } + + public string Accept(TDouble type) + { + return "f64"; + } + + public string Accept(TEnum type) + { + return "i32"; + } + + public string Accept(TString type) + { + return "String"; + } + + public string Accept(TBytes type) + { + throw new System.NotSupportedException(); + } + + public string Accept(TText type) + { + return "String"; + } + + public string Accept(TBean type) + { + return type.Bean.RustFullName; + } + + public string Accept(TArray type) + { + return $"Vec<{type.ElementType.Apply(RustTypeNameVisitor.Ins)}>"; + } + + public string Accept(TList type) + { + return $"Vec<{type.ElementType.Apply(RustTypeNameVisitor.Ins)}>"; + } + + public string Accept(TSet type) + { + return $"std::collections::HashSet<{type.ElementType.Apply(RustTypeNameVisitor.Ins)}>"; + } + + public string Accept(TMap type) + { + return $"std::collections::HashMap<{type.KeyType.Apply(RustTypeNameVisitor.Ins)}, {type.ValueType.Apply(RustTypeNameVisitor.Ins)}>"; + } + + 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 "i32"; + } + } +} diff --git a/src/Luban.Job.Common/Source/Utils/RenderFileUtil.cs b/src/Luban.Job.Common/Source/Utils/RenderFileUtil.cs index ef0d84b..1d52e36 100644 --- a/src/Luban.Job.Common/Source/Utils/RenderFileUtil.cs +++ b/src/Luban.Job.Common/Source/Utils/RenderFileUtil.cs @@ -17,6 +17,7 @@ namespace Luban.Job.Common.Utils case ELanguage.LUA: return fullName.Replace('.', '_') + ".lua"; case ELanguage.JS: return fullName + ".js"; case ELanguage.TYPESCRIPT: return fullName.Replace('.', '/') + ".ts"; + case ELanguage.RUST: return fullName.Replace('.', '_') + ".rs"; default: throw new NotSupportedException(); } @@ -97,6 +98,7 @@ namespace Luban.Job.Common.Utils { "typescript", ELanguage.TYPESCRIPT }, { "javascript", ELanguage.JS }, { "erlang", ELanguage.ERLANG }, + { "rust", ELanguage.RUST }, }; public static ELanguage GetLanguage(string genType) diff --git a/src/Luban.Job.Common/Source/Utils/RenderUtil.cs b/src/Luban.Job.Common/Source/Utils/RenderUtil.cs index 84b5bfd..52884ef 100644 --- a/src/Luban.Job.Common/Source/Utils/RenderUtil.cs +++ b/src/Luban.Job.Common/Source/Utils/RenderUtil.cs @@ -118,6 +118,26 @@ namespace Luban.Job.Common.Utils { var template = StringTemplateUtil.GetTemplate("common/typescript/enum"); var result = template.Render(e); + return result; + } + + public static string RenderRustConstClass(DefConst c) + { + var ctx = new TemplateContext(); + var env = new TTypeTemplateCommonExtends + { + ["x"] = c + }; + ctx.PushGlobal(env); + var template = StringTemplateUtil.GetTemplate("common/rust/const"); + var result = template.Render(ctx); + return result; + } + + public static string RenderRustEnumClass(DefEnum e) + { + var template = StringTemplateUtil.GetTemplate("common/rust/enum"); + var result = template.Render(e); return result; } diff --git a/src/Luban.Server/Luban.Server.csproj b/src/Luban.Server/Luban.Server.csproj index 3348f16..8dcaa5d 100644 --- a/src/Luban.Server/Luban.Server.csproj +++ b/src/Luban.Server/Luban.Server.csproj @@ -67,6 +67,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -175,6 +181,18 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest diff --git a/src/Luban.Server/Templates/common/rust/const.tpl b/src/Luban.Server/Templates/common/rust/const.tpl new file mode 100644 index 0000000..8260828 --- /dev/null +++ b/src/Luban.Server/Templates/common/rust/const.tpl @@ -0,0 +1,18 @@ +{{~if x.comment != '' ~}} +/** + * {{x.comment}} + */ +{{~end~}} + +#[allow(non_snake_case)] +pub mod {{x.rust_full_name}} { + {{~ for item in x.items ~}} +{{~if item.comment != '' ~}} + /** + * {{item.comment}} + */ +{{~end~}} + #[allow(dead_code)] + pub const {{string.upcase item.name}}: {{rust_define_type item.ctype}} = {{rust_const_value item.ctype item.value}}; + {{~end~}} +} diff --git a/src/Luban.Server/Templates/common/rust/enum.tpl b/src/Luban.Server/Templates/common/rust/enum.tpl new file mode 100644 index 0000000..2c700f2 --- /dev/null +++ b/src/Luban.Server/Templates/common/rust/enum.tpl @@ -0,0 +1,18 @@ +{{~if comment != '' ~}} +/** + * {{comment}} + */ +{{~end~}} +#[allow(dead_code)] +#[allow(non_camel_case_types)] +pub enum {{rust_full_name}} { + {{~for item in items ~}} +{{~if item.comment != '' ~}} + /** + * {{item.comment}} + */ +{{~end~}} + {{item.name}} = {{item.int_value}}, + {{~end~}} +} + diff --git a/src/Luban.Server/Templates/config/rust_json/bean.tpl b/src/Luban.Server/Templates/config/rust_json/bean.tpl new file mode 100644 index 0000000..96ea41f --- /dev/null +++ b/src/Luban.Server/Templates/config/rust_json/bean.tpl @@ -0,0 +1,31 @@ + +{{ + name = x.rust_full_name + parent_def_type = x.parent_def_type + export_fields = x.export_fields + hierarchy_export_fields = x.hierarchy_export_fields +}} + +{{~if x.comment != '' ~}} +/** + * {{x.comment}} + */ +{{~end~}} +#[allow(non_camel_case_types)] +pub struct {{name}} { +{{~for field in hierarchy_export_fields~}} +pub {{field.rust_style_name}}: {{rust_define_type field.ctype}}, +{{~end~}} +} + +impl {{name}} { + #[allow(dead_code)] + pub fn new(__js: &json::JsonValue) -> Result, LoadError> { + let __b = {{name}} { +{{~for field in hierarchy_export_fields~}} + {{field.rust_style_name}}: {{rust_json_constructor ('__js["' + field.name + '"]') field.ctype}}, +{{~end~}} + }; + Ok(std::rc::Rc::new(__b)) + } +} diff --git a/src/Luban.Server/Templates/config/rust_json/mod_header.tpl b/src/Luban.Server/Templates/config/rust_json/mod_header.tpl new file mode 100644 index 0000000..d7959d3 --- /dev/null +++ b/src/Luban.Server/Templates/config/rust_json/mod_header.tpl @@ -0,0 +1,59 @@ +pub struct LoadError { + +} + +impl std::fmt::Debug for LoadError { + fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { Ok(()) } +} + +#[allow(dead_code)] +pub struct Vector2 { + pub x:f32, + pub y:f32, +} + +impl Vector2 { + pub fn new(__js:&json::JsonValue) -> Result { + Ok(Vector2{ + x: match __js["x"].as_f32() { Some(__x__) => __x__, None => return Err(LoadError{})}, + y: match __js["y"].as_f32() { Some(__x__) => __x__, None => return Err(LoadError{})}, + }) + } +} + +#[allow(dead_code)] +pub struct Vector3 { + pub x:f32, + pub y:f32, + pub z:f32, +} + +impl Vector3 { + pub fn new(__js:&json::JsonValue) -> Result { + Ok(Vector3{ + x: match __js["x"].as_f32() { Some(__x__) => __x__, None => return Err(LoadError{})}, + y: match __js["y"].as_f32() { Some(__x__) => __x__, None => return Err(LoadError{})}, + z: match __js["z"].as_f32() { Some(__x__) => __x__, None => return Err(LoadError{})}, + }) + } +} + +#[allow(dead_code)] +pub struct Vector4 { + pub x:f32, + pub y:f32, + pub z:f32, + pub w:f32, +} + + +impl Vector4 { + pub fn new(__js:&json::JsonValue) -> Result { + Ok(Vector4{ + x: match __js["x"].as_f32() { Some(__x__) => __x__, None => return Err(LoadError{})}, + y: match __js["y"].as_f32() { Some(__x__) => __x__, None => return Err(LoadError{})}, + z: match __js["z"].as_f32() { Some(__x__) => __x__, None => return Err(LoadError{})}, + w: match __js["w"].as_f32() { Some(__x__) => __x__, None => return Err(LoadError{})}, + }) + } +} \ No newline at end of file diff --git a/src/Luban.Server/Templates/config/rust_json/table.tpl b/src/Luban.Server/Templates/config/rust_json/table.tpl new file mode 100644 index 0000000..7f19be1 --- /dev/null +++ b/src/Luban.Server/Templates/config/rust_json/table.tpl @@ -0,0 +1,65 @@ +{{ + name = x.rust_full_name + key_type = x.key_ttype + value_type = x.value_ttype +}} +{{~if x.comment != '' ~}} +/** + * {{x.comment}} + */ +{{~end~}} +#[allow(non_camel_case_types)] +pub struct {{name}} { + {{~if x.is_map_table ~}} + data_list: Vec<{{rust_define_type value_type}}>, + data_map: std::collections::HashMap<{{rust_define_type key_type}}, {{rust_define_type value_type}}>, + {{~else~}} + data: {{rust_define_type value_type}}, + {{~end~}} +} + +impl {{name}}{ + pub fn new(__js: &json::JsonValue) -> Result, LoadError> { + {{~if x.is_map_table ~}} + if !__js.is_array() { + return Err(LoadError{}); + } + let mut t = {{name}} { + data_list : Vec::new(), + data_map: std::collections::HashMap::new(), + }; + + for __e in __js.members() { + let __v = match {{rust_class_name value_type}}::new(__e) { + Ok(x) => x, + Err(err) => return Err(err), + }; + let __v2 = std::rc::Rc::clone(&__v); + t.data_list.push(__v); + t.data_map.insert(__v2.{{x.index_field.rust_style_name}}.clone(), __v2); + } + Ok(std::rc::Rc::new(t)) + } + #[allow(dead_code)] + pub fn get_data_map(self:&{{name}}) -> &std::collections::HashMap<{{rust_define_type key_type}}, {{rust_define_type value_type}}> { &self.data_map } + #[allow(dead_code)] + pub fn get_data_list(self:&{{name}}) -> &Vec<{{rust_define_type value_type}}> { &self.data_list } + #[allow(dead_code)] + pub fn get(self:&{{name}}, key: {{rust_define_type key_type}}) -> std::option::Option<&{{rust_define_type value_type}}> { self.data_map.get(&key) } + {{~else~}} + if !__js.is_array() || __js.len() != 1 { + return Err(LoadError{}); + } + let __v = match {{rust_class_name value_type}}::new(&__js[0]) { + Ok(x) => x, + Err(err) => return Err(err), + }; + let t = {{name}} { + data: __v, + }; + Ok(std::rc::Rc::new(t)) + } + #[allow(dead_code)] + pub fn get_data(self:&{{name}}) -> &{{rust_define_type value_type}} { &self.data } + {{~end~}} +} \ No newline at end of file diff --git a/src/Luban.Server/Templates/config/rust_json/tables.tpl b/src/Luban.Server/Templates/config/rust_json/tables.tpl new file mode 100644 index 0000000..aac8dc5 --- /dev/null +++ b/src/Luban.Server/Templates/config/rust_json/tables.tpl @@ -0,0 +1,32 @@ +{{ + name = x.name + namespace = x.namespace + tables = x.tables +}} + +type JsonLoader = fn(&str) -> Result; + +#[allow(non_camel_case_types)] +pub struct {{name}} { + {{~ for table in tables ~}} + +{{~if table.comment != '' ~}} + /** + * {{table.comment}} + */ +{{~end~}} + pub {{string.downcase table.name}}: std::rc::Rc<{{table.rust_full_name}}>, + {{~end~}} +} + +impl {{name}} { + #[allow(dead_code)] + pub fn new(loader: JsonLoader) -> std::result::Result, LoadError> { + let tables = Tables { + {{~for table in tables ~}} + {{string.downcase table.name}}: {{table.rust_full_name}}::new(&loader("{{table.output_data_file}}")?)?, + {{~end~}} + }; + return Ok(std::rc::Rc::new(tables)); + } +}