【特性】支持生成 proto定义文件和proto二进制数据

main
walon 2021-11-30 01:52:47 +08:00
parent b8e794d528
commit 66ba09e8a0
32 changed files with 930 additions and 25 deletions

View File

@ -126,6 +126,11 @@ namespace Luban.Common.Utils
return MakeGoNamespace(module) + name; return MakeGoNamespace(module) + name;
} }
public static string MakePbFullName(string module, string name)
{
return MakeGoNamespace(module) + name;
}
public static string MakeNamespace(string module, string subModule) public static string MakeNamespace(string module, string subModule)
{ {
if (module.Length == 0) if (module.Length == 0)

View File

@ -0,0 +1,300 @@
using Google.Protobuf;
using Luban.Job.Cfg.Datas;
using Luban.Job.Cfg.DataSources;
using Luban.Job.Cfg.DataVisitors;
using Luban.Job.Cfg.Defs;
using Luban.Job.Common.Generate;
using Luban.Job.Common.Types;
using Luban.Job.Common.TypeVisitors;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Luban.Job.Cfg.DataExporters
{
class ProtobufExportor : IDataActionVisitor<CodedOutputStream>
{
public static ProtobufExportor Ins { get; } = new();
public void WriteList(DefTable table, List<Record> datas, MemoryStream x)
{
var cos = new CodedOutputStream(x);
foreach (var d in datas)
{
cos.WriteTag(1, WireFormat.WireType.LengthDelimited);
d.Data.Apply(this, cos);
}
cos.Flush();
}
public void Accept(DBool type, CodedOutputStream x)
{
x.WriteBool(type.Value);
}
public void Accept(DByte type, CodedOutputStream x)
{
x.WriteInt32(type.Value);
}
public void Accept(DShort type, CodedOutputStream x)
{
x.WriteInt32(type.Value);
}
public void Accept(DFshort type, CodedOutputStream x)
{
x.WriteInt32(type.Value);
}
public void Accept(DInt type, CodedOutputStream x)
{
x.WriteInt32(type.Value);
}
public void Accept(DFint type, CodedOutputStream x)
{
x.WriteSFixed32(type.Value);
}
public void Accept(DLong type, CodedOutputStream x)
{
x.WriteInt64(type.Value);
}
public void Accept(DFlong type, CodedOutputStream x)
{
x.WriteSFixed64(type.Value);
}
public void Accept(DFloat type, CodedOutputStream x)
{
x.WriteFloat(type.Value);
}
public void Accept(DDouble type, CodedOutputStream x)
{
x.WriteDouble(type.Value);
}
public void Accept(DEnum type, CodedOutputStream x)
{
x.WriteInt32(type.Value);
}
public void Accept(DDateTime type, CodedOutputStream x)
{
x.WriteInt32(type.GetUnixTime(DefAssembly.LocalAssebmly.TimeZone));
}
public void Accept(DString type, CodedOutputStream x)
{
x.WriteString(type.Value);
}
public void Accept(DBytes type, CodedOutputStream x)
{
x.WriteBytes(ByteString.CopyFrom(type.Value));
}
public void Accept(DText type, CodedOutputStream x)
{
// 此处与 binary格式不同. binary格式还包含了key
// 意味pb格式是无法支持动态本土化的。
var ass = DefAssembly.LocalAssebmly;
x.WriteString(type.GetText(ass.ExportTextTable, ass.NotConvertTextSet));
}
private MemoryStream AllocMemoryStream()
{
return new MemoryStream();
}
private void FreeMemoryStream(MemoryStream cos)
{
cos.Seek(0, SeekOrigin.Begin);
}
public void Accept(DVector2 type, CodedOutputStream x)
{
var ms = AllocMemoryStream();
var temp = new CodedOutputStream(ms);
temp.WriteTag(1, WireFormat.WireType.Fixed32);
temp.WriteFloat(type.Value.X);
temp.WriteTag(2, WireFormat.WireType.Fixed32);
temp.WriteFloat(type.Value.Y);
temp.Flush();
ms.Seek(0, SeekOrigin.Begin);
x.WriteBytes(ByteString.FromStream(ms));
FreeMemoryStream(ms);
}
public void Accept(DVector3 type, CodedOutputStream x)
{
var ms = AllocMemoryStream();
var temp = new CodedOutputStream(ms);
temp.WriteTag(1, WireFormat.WireType.Fixed32);
temp.WriteFloat(type.Value.X);
temp.WriteTag(2, WireFormat.WireType.Fixed32);
temp.WriteFloat(type.Value.Y);
temp.WriteTag(3, WireFormat.WireType.Fixed32);
temp.WriteFloat(type.Value.Z);
temp.Flush();
ms.Seek(0, SeekOrigin.Begin);
x.WriteBytes(ByteString.FromStream(ms));
FreeMemoryStream(ms);
}
public void Accept(DVector4 type, CodedOutputStream x)
{
var ms = AllocMemoryStream();
var temp = new CodedOutputStream(ms);
temp.WriteTag(1, WireFormat.WireType.Fixed32);
temp.WriteFloat(type.Value.X);
temp.WriteTag(2, WireFormat.WireType.Fixed32);
temp.WriteFloat(type.Value.Y);
temp.WriteTag(3, WireFormat.WireType.Fixed32);
temp.WriteFloat(type.Value.Z);
temp.WriteTag(4, WireFormat.WireType.Fixed32);
temp.WriteFloat(type.Value.W);
temp.Flush();
ms.Seek(0, SeekOrigin.Begin);
x.WriteBytes(ByteString.FromStream(ms));
FreeMemoryStream(ms);
}
public void Accept(DBean type, CodedOutputStream x)
{
var bean = type.Type;
if (bean.IsAbstractType)
{
x.WriteTag(type.ImplType.AutoId, WireFormat.WireType.LengthDelimited);
}
var ms = AllocMemoryStream();
var temp = new CodedOutputStream(ms);
var defFields = type.ImplType.HierarchyFields;
int index = 0;
foreach (var field in type.Fields)
{
var defField = (DefField)defFields[index++];
if (!defField.NeedExport)
{
continue;
}
var fieldType = defField.CType;
if (field == null)
{
continue;
}
switch (field)
{
case DArray arr:
{
WriteList(fieldType.ElementType, defField.AutoId, arr.Datas, temp);
break;
}
case DList list:
{
WriteList(fieldType.ElementType, defField.AutoId, list.Datas, temp);
break;
}
case DSet set:
{
WriteList(fieldType.ElementType, defField.AutoId, set.Datas, temp);
break;
}
case DMap map:
{
WriteMap(map, defField.AutoId, temp);
break;
}
default:
{
temp.WriteTag(defField.AutoId, defField.CType.Apply(ProtobufWireTypeVisitor.Ins));
field.Apply(this, temp);
break;
}
}
}
temp.Flush();
ms.Seek(0, SeekOrigin.Begin);
var bs = ByteString.FromStream(ms);
x.WriteBytes(bs);
FreeMemoryStream(ms);
}
private void WriteList(TType elementType, int fieldId, List<DType> datas, CodedOutputStream x)
{
if (elementType.Apply(IsProtobufPackedType.Ins))
{
x.WriteTag(fieldId, WireFormat.WireType.LengthDelimited);
var ms = AllocMemoryStream();
var temp = new CodedOutputStream(ms);
foreach (var data in datas)
{
data.Apply(this, temp);
}
temp.Flush();
ms.Seek(0, SeekOrigin.Begin);
x.WriteBytes(ByteString.FromStream(ms));
FreeMemoryStream(ms);
}
else
{
var eleWireType = elementType.Apply(ProtobufWireTypeVisitor.Ins);
foreach (var data in datas)
{
x.WriteTag(fieldId, eleWireType);
data.Apply(this, x);
}
}
}
public void Accept(DArray type, CodedOutputStream x)
{
throw new NotImplementedException();
}
public void Accept(DList type, CodedOutputStream x)
{
throw new NotImplementedException();
}
public void Accept(DSet type, CodedOutputStream x)
{
throw new NotImplementedException();
}
private void WriteMap(DMap type, int fieldId, CodedOutputStream x)
{
var keyType = type.Type.KeyType;
var valueType = type.Type.ValueType;
var ms = AllocMemoryStream();
foreach (var e in type.Datas)
{
x.WriteTag(fieldId, WireFormat.WireType.LengthDelimited);
ms.Seek(0, SeekOrigin.Begin);
var temp = new CodedOutputStream(ms);
temp.WriteTag(1, keyType.Apply(ProtobufWireTypeVisitor.Ins));
e.Key.Apply(this, temp);
temp.WriteTag(2, valueType.Apply(ProtobufWireTypeVisitor.Ins));
e.Value.Apply(this, temp);
temp.Flush();
ms.Seek(0, SeekOrigin.Begin);
x.WriteBytes(ByteString.FromStream(ms));
}
FreeMemoryStream(ms);
}
public void Accept(DMap type, CodedOutputStream x)
{
throw new NotSupportedException();
}
}
}

View File

@ -28,9 +28,17 @@ namespace Luban.Job.Cfg.DataVisitors
void Accept(DString type, T x); void Accept(DString type, T x);
void Accept(DText type, T x);
void Accept(DBytes type, T x); void Accept(DBytes type, T x);
void Accept(DText type, T x); void Accept(DVector2 type, T x);
void Accept(DVector3 type, T x);
void Accept(DVector4 type, T x);
void Accept(DDateTime type, T x);
void Accept(DBean type, T x); void Accept(DBean type, T x);
@ -41,14 +49,6 @@ namespace Luban.Job.Cfg.DataVisitors
void Accept(DSet type, T x); void Accept(DSet type, T x);
void Accept(DMap type, T x); void Accept(DMap type, T x);
void Accept(DVector2 type, T x);
void Accept(DVector3 type, T x);
void Accept(DVector4 type, T x);
void Accept(DDateTime type, T x);
} }
public interface IDataActionVisitor<T1, T2> public interface IDataActionVisitor<T1, T2>
@ -75,11 +75,19 @@ namespace Luban.Job.Cfg.DataVisitors
void Accept(DEnum type, T1 x, T2 y); void Accept(DEnum type, T1 x, T2 y);
void Accept(DDateTime type, T1 x, T2 y);
void Accept(DString type, T1 x, T2 y); void Accept(DString type, T1 x, T2 y);
void Accept(DText type, T1 x, T2 y);
void Accept(DBytes type, T1 x, T2 y); void Accept(DBytes type, T1 x, T2 y);
void Accept(DText type, T1 x, T2 y); void Accept(DVector2 type, T1 x, T2 y);
void Accept(DVector3 type, T1 x, T2 y);
void Accept(DVector4 type, T1 x, T2 y);
void Accept(DBean type, T1 x, T2 y); void Accept(DBean type, T1 x, T2 y);
@ -90,13 +98,5 @@ namespace Luban.Job.Cfg.DataVisitors
void Accept(DSet type, T1 x, T2 y); void Accept(DSet type, T1 x, T2 y);
void Accept(DMap type, T1 x, T2 y); void Accept(DMap type, T1 x, T2 y);
void Accept(DVector2 type, T1 x, T2 y);
void Accept(DVector3 type, T1 x, T2 y);
void Accept(DVector4 type, T1 x, T2 y);
void Accept(DDateTime type, T1 x, T2 y);
} }
} }

View File

@ -26,6 +26,8 @@ namespace Luban.Job.Cfg.Defs
public List<DefField> ExportFields { get; private set; } public List<DefField> ExportFields { get; private set; }
public int AutoId { get; set; }
public bool IsDefineEquals(DefBean b) public bool IsDefineEquals(DefBean b)
{ {
return DeepCompareTypeDefine.Ins.Compare(this, b, new Dictionary<DefTypeBase, bool>(), new HashSet<DefTypeBase>()); return DeepCompareTypeDefine.Ins.Compare(this, b, new Dictionary<DefTypeBase, bool>(), new HashSet<DefTypeBase>());
@ -196,6 +198,18 @@ namespace Luban.Job.Cfg.Defs
} }
} }
DefField.CompileFields(this, HierarchyFields, false); DefField.CompileFields(this, HierarchyFields, false);
var allocAutoIds = this.HierarchyFields.Select(f => f.Id).ToHashSet();
int nextAutoId = 1;
foreach (var f in this.HierarchyFields)
{
while (!allocAutoIds.Add(nextAutoId))
{
++nextAutoId;
}
f.AutoId = nextAutoId;
}
} }
public override void PostCompile() public override void PostCompile()
@ -204,6 +218,14 @@ namespace Luban.Job.Cfg.Defs
{ {
field.PostCompile(); field.PostCompile();
} }
if (this.IsAbstractType && this.ParentDefType == null)
{
int nextAutoId = 0;
foreach (DefBean c in this.HierarchyNotAbstractChildren)
{
c.AutoId = ++nextAutoId;
}
}
} }
} }
} }

View File

@ -49,6 +49,8 @@ namespace Luban.Job.Cfg.Defs
public TBean ValueTType { get; private set; } public TBean ValueTType { get; private set; }
public TType Type { get; private set; }
public DefField IndexField { get; private set; } public DefField IndexField { get; private set; }
public int IndexFieldIdIndex { get; private set; } public int IndexFieldIdIndex { get; private set; }
@ -86,6 +88,7 @@ namespace Luban.Job.Cfg.Defs
case ETableMode.ONE: case ETableMode.ONE:
{ {
KeyTType = null; KeyTType = null;
Type = ValueTType;
break; break;
} }
case ETableMode.MAP: case ETableMode.MAP:
@ -113,6 +116,7 @@ namespace Luban.Job.Cfg.Defs
IndexFieldIdIndex = 0; IndexFieldIdIndex = 0;
} }
KeyTType = IndexField.CType; KeyTType = IndexField.CType;
Type = TMap.Create(false, null, KeyTType, ValueTType, false);
break; break;
} }
default: throw new Exception($"unknown mode:'{Mode}'"); default: throw new Exception($"unknown mode:'{Mode}'");

View File

@ -13,6 +13,7 @@ namespace Luban.Job.Cfg.Generate
[Render("data_lua")] [Render("data_lua")]
[Render("data_xml")] [Render("data_xml")]
[Render("data_yaml")] [Render("data_yaml")]
[Render("data_protobuf")]
class DataScatterRender : DataRenderBase class DataScatterRender : DataRenderBase
{ {
public override void Render(GenContext ctx) public override void Render(GenContext ctx)

View File

@ -19,7 +19,5 @@ namespace Luban.Job.Cfg.Generate
var md5 = CacheFileUtil.GenMd5AndAddCache(file, string.Join('\n', content)); var md5 = CacheFileUtil.GenMd5AndAddCache(file, string.Join('\n', content));
ctx.GenCodeFilesInOutputCodeDir.Add(new FileInfo() { FilePath = file, MD5 = md5 }); ctx.GenCodeFilesInOutputCodeDir.Add(new FileInfo() { FilePath = file, MD5 = md5 });
} }
public abstract string RenderAll(List<DefTypeBase> types);
} }
} }

View File

@ -0,0 +1,20 @@
using Luban.Common.Protos;
using Luban.Job.Cfg.Defs;
using Luban.Job.Common.Defs;
using Luban.Job.Common.Generate;
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_protobuf")]
[Render("code_protobuf2")]
class Protobuf2SchemaRender : ProtobufSchemaRenderBase
{
protected override string RenderTemplateDir => "pb2";
}
}

View File

@ -0,0 +1,15 @@
using Luban.Job.Common.Generate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Luban.Job.Cfg.Generate
{
[Render("code_protobuf3")]
class Protobuf3SchemaRender : ProtobufSchemaRenderBase
{
protected override string RenderTemplateDir => "pb3";
}
}

View File

@ -0,0 +1,27 @@
using Luban.Common.Protos;
using Luban.Job.Cfg.Defs;
using Luban.Job.Common.Defs;
using Luban.Job.Common.Generate;
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
{
abstract class ProtobufSchemaRenderBase : TemplateCodeRenderBase
{
protected override string CommonRenderTemplateDir => "pb";
public override void Render(GenContext ctx)
{
DefAssembly.LocalAssebmly.CurrentLanguage = Common.ELanguage.LUA;
var file = RenderFileUtil.GetFileOrDefault(ctx.GenArgs.OutputCodeMonolithicFile, "config.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 });
}
}
}

View File

@ -52,5 +52,21 @@ namespace Luban.Job.Cfg.Generate
}); });
return result; return result;
} }
public virtual string RenderAll(List<DefTypeBase> types)
{
var enums = types.Where(t => t is DefEnum).ToList();
var beans = types.Where(t => t is DefBean).ToList();
var tables = types.Where(t => t is DefTable).ToList();
var template = StringTemplateUtil.GetTemplate($"config/{RenderTemplateDir}/all");
var result = template.RenderCode(new {
Namespace = DefAssembly.LocalAssebmly.TopModule,
Enums = enums.Select(e => Render((DefEnum)e)).ToList(),
Beans = beans.Select(b => Render((DefBean)b)).ToList(),
Tables = tables.Select(t => Render((DefTable)t)).ToList(),
});
return result;
}
} }
} }

View File

@ -86,6 +86,12 @@ namespace Luban.Job.Cfg.Utils
} }
return string.Join('\n', content); return string.Join('\n', content);
} }
case "data_protobuf":
{
var ms = new MemoryStream();
ProtobufExportor.Ins.WriteList(table, records, ms);
return DataUtil.StreamToBytes(ms);
}
//case "data_erlang": //case "data_erlang":
//{ //{
// var content = new StringBuilder(); // var content = new StringBuilder();

View File

@ -22,6 +22,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.8.0" /> <PackageReference Include="CommandLineParser" Version="2.8.0" />
<PackageReference Include="Google.Protobuf" Version="3.19.1" />
<PackageReference Include="Scriban" Version="4.1.0" /> <PackageReference Include="Scriban" Version="4.1.0" />
</ItemGroup> </ItemGroup>

View File

@ -13,9 +13,11 @@ namespace Luban.Job.Common.Defs
public DefTypeBase HostType { get; set; } public DefTypeBase HostType { get; set; }
public int Id { get; set; } public int Id { get; protected set; }
public string Name { get; set; } public string Name { get; protected set; }
public int AutoId { get; set; }
public string ConventionName public string ConventionName
{ {
@ -44,6 +46,7 @@ namespace Luban.Job.Common.Defs
case ELanguage.TYPESCRIPT: cn = TypeUtil.ToCamelCase(Name); break; case ELanguage.TYPESCRIPT: cn = TypeUtil.ToCamelCase(Name); break;
case ELanguage.PYTHON: cn = TypeUtil.ToUnderScores(Name); break; case ELanguage.PYTHON: cn = TypeUtil.ToUnderScores(Name); break;
case ELanguage.RUST: cn = TypeUtil.ToUnderScores(Name); break; case ELanguage.RUST: cn = TypeUtil.ToUnderScores(Name); break;
case ELanguage.PROTOBUF: cn = Name; break;
default: throw new Exception($"unknown language:{curLan}"); default: throw new Exception($"unknown language:{curLan}");
} }
break; break;
@ -91,6 +94,7 @@ namespace Luban.Job.Common.Defs
{ {
HostType = host; HostType = host;
Id = f.Id + idOffset; Id = f.Id + idOffset;
AutoId = Id;
Name = f.Name; Name = f.Name;
Type = f.Type; Type = f.Type;
Comment = f.Comment; Comment = f.Comment;

View File

@ -47,6 +47,8 @@ namespace Luban.Job.Common.Defs
public string RustFullName => TypeUtil.MakeRustFullName(Namespace, Name); public string RustFullName => TypeUtil.MakeRustFullName(Namespace, Name);
public string PbFullName => TypeUtil.MakePbFullName(Namespace, Name);
public string Comment { get; protected set; } public string Comment { get; protected set; }
public string EscapeComment => DefUtil.EscapeCommentByCurrentLanguage(Comment); public string EscapeComment => DefUtil.EscapeCommentByCurrentLanguage(Comment);

View File

@ -205,6 +205,46 @@ namespace Luban.Job.Common.Defs
return type.Apply(GoDeserializeBinVisitor.Ins, name, bufName, err); return type.Apply(GoDeserializeBinVisitor.Ins, name, bufName, err);
} }
public static string ProtobufDefineType(TType type)
{
return type.Apply(ProtobufTypeNameVisitor.Ins);
}
public static string ProtobufPreDecorator(TType type)
{
if (type.IsNullable)
{
return "optional";
}
else if (type.IsCollection)
{
if (type is TMap)
{
return "";
}
else
{
return "repeated";
}
}
else
{
return "required";
}
}
public static string ProtobufSuffixOptions(TType type)
{
if (type.IsCollection && !(type is TMap))
{
return $"[packed = {(type.ElementType.Apply(IsProtobufPackedType.Ins) ? "true" : "false")}]";
}
else
{
return "";
}
}
public static bool HasTag(dynamic obj, string attrName) public static bool HasTag(dynamic obj, string attrName)
{ {
return obj.HasTag(attrName); return obj.HasTag(attrName);

View File

@ -13,5 +13,6 @@ namespace Luban.Job.Common
PYTHON, PYTHON,
ERLANG, ERLANG,
RUST, RUST,
PROTOBUF,
} }
} }

View File

@ -0,0 +1,71 @@
using Luban.Job.Common.Types;
using Luban.Job.Common.TypeVisitors;
namespace Luban.Job.Common.TypeVisitors
{
public class IsProtobufPackedType : AllTrueVisitor
{
public static IsProtobufPackedType Ins { get; } = new();
public override bool Accept(TString type)
{
return false;
}
public override bool Accept(TText type)
{
return false;
}
public override bool Accept(TBytes 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;
}
public override bool Accept(TEnum 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;
}
}
}

View File

@ -0,0 +1,130 @@
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 ProtobufTypeNameVisitor : ITypeFuncVisitor<string>
{
public static ProtobufTypeNameVisitor Ins { get; } = new();
public string Accept(TBool type)
{
return "bool";
}
public string Accept(TByte type)
{
return "int32";
}
public string Accept(TShort type)
{
return "int32";
}
public string Accept(TFshort type)
{
return "int32";
}
public string Accept(TInt type)
{
return "int32";
}
public string Accept(TFint type)
{
return "sfixed32";
}
public string Accept(TLong type)
{
return "int64";
}
public string Accept(TFlong type)
{
return "sfixed64";
}
public string Accept(TFloat type)
{
return "float";
}
public string Accept(TDouble type)
{
return "double";
}
public string Accept(TEnum type)
{
return type.DefineEnum.PbFullName;
}
public string Accept(TString type)
{
return "string";
}
public string Accept(TText type)
{
return "string";
}
public string Accept(TBytes type)
{
return "bytes";
}
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.GoFullName;
}
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)
{
string key = type.KeyType is TEnum ? "int32" : (type.KeyType.Apply(this));
return $"map<{key}, {type.ValueType.Apply(this)}>";
}
}
}

View File

@ -0,0 +1,131 @@
using Google.Protobuf;
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 ProtobufWireTypeVisitor : ITypeFuncVisitor<WireFormat.WireType>
{
public static ProtobufWireTypeVisitor Ins { get; } = new();
public WireFormat.WireType Accept(TBool type)
{
return WireFormat.WireType.Varint;
}
public WireFormat.WireType Accept(TByte type)
{
return WireFormat.WireType.Varint;
}
public WireFormat.WireType Accept(TShort type)
{
return WireFormat.WireType.Varint;
}
public WireFormat.WireType Accept(TFshort type)
{
return WireFormat.WireType.Varint;
}
public WireFormat.WireType Accept(TInt type)
{
return WireFormat.WireType.Varint;
}
public WireFormat.WireType Accept(TFint type)
{
return WireFormat.WireType.Fixed32;
}
public WireFormat.WireType Accept(TLong type)
{
return WireFormat.WireType.Varint;
}
public WireFormat.WireType Accept(TFlong type)
{
return WireFormat.WireType.Fixed64;
}
public WireFormat.WireType Accept(TFloat type)
{
return WireFormat.WireType.Fixed32;
}
public WireFormat.WireType Accept(TDouble type)
{
return WireFormat.WireType.Fixed64;
}
public WireFormat.WireType Accept(TEnum type)
{
return WireFormat.WireType.Varint;
}
public WireFormat.WireType Accept(TString type)
{
return WireFormat.WireType.LengthDelimited;
}
public WireFormat.WireType Accept(TText type)
{
return WireFormat.WireType.LengthDelimited;
}
public WireFormat.WireType Accept(TBytes type)
{
return WireFormat.WireType.LengthDelimited;
}
public WireFormat.WireType Accept(TVector2 type)
{
return WireFormat.WireType.LengthDelimited;
}
public WireFormat.WireType Accept(TVector3 type)
{
return WireFormat.WireType.LengthDelimited;
}
public WireFormat.WireType Accept(TVector4 type)
{
return WireFormat.WireType.LengthDelimited;
}
public WireFormat.WireType Accept(TDateTime type)
{
return WireFormat.WireType.Varint;
}
public WireFormat.WireType Accept(TBean type)
{
return WireFormat.WireType.LengthDelimited;
}
public WireFormat.WireType Accept(TArray type)
{
//return WireFormat.WireType.LengthDelimited;
throw new System.NotSupportedException();
}
public WireFormat.WireType Accept(TList type)
{
throw new System.NotSupportedException();
}
public WireFormat.WireType Accept(TSet type)
{
throw new System.NotSupportedException();
}
public WireFormat.WireType Accept(TMap type)
{
return WireFormat.WireType.LengthDelimited;
}
}
}

View File

@ -12,7 +12,7 @@ namespace Luban.Job.Common.Types
return new TArray(isNullable, tags, elementType); return new TArray(isNullable, tags, elementType);
} }
public TType ElementType { get; } public override TType ElementType { get; }
private TArray(bool isNullable, Dictionary<string, string> tags, TType elementType) : base(isNullable, tags) private TArray(bool isNullable, Dictionary<string, string> tags, TType elementType) : base(isNullable, tags)
{ {

View File

@ -12,7 +12,7 @@ namespace Luban.Job.Common.Types
return new TList(isNullable, tags, elementType, isArrayList); return new TList(isNullable, tags, elementType, isArrayList);
} }
public TType ElementType { get; } public override TType ElementType { get; }
public bool IsArrayList { get; } public bool IsArrayList { get; }

View File

@ -12,7 +12,7 @@ namespace Luban.Job.Common.Types
return new TSet(isNullable, tags, elementType, isOrdered); return new TSet(isNullable, tags, elementType, isOrdered);
} }
public TType ElementType { get; } public override TType ElementType { get; }
public bool IsOrderSet { get; } public bool IsOrderSet { get; }

View File

@ -42,6 +42,8 @@ namespace Luban.Job.Common.Types
public virtual bool IsBean => false; public virtual bool IsBean => false;
public virtual TType ElementType => null;
public abstract void Apply<T>(ITypeActionVisitor<T> visitor, T x); public abstract void Apply<T>(ITypeActionVisitor<T> visitor, T x);
public abstract void Apply<T1, T2>(ITypeActionVisitor<T1, T2> visitor, T1 x, T2 y); public abstract void Apply<T1, T2>(ITypeActionVisitor<T1, T2> visitor, T1 x, T2 y);
public abstract TR Apply<TR>(ITypeFuncVisitor<TR> visitor); public abstract TR Apply<TR>(ITypeFuncVisitor<TR> visitor);

View File

@ -173,6 +173,7 @@ namespace Luban.Job.Common.Utils
case ELanguage.TYPESCRIPT: case ELanguage.TYPESCRIPT:
case ELanguage.PYTHON: case ELanguage.PYTHON:
case ELanguage.RUST: case ELanguage.RUST:
case ELanguage.PROTOBUF:
#if !LUBAN_LITE #if !LUBAN_LITE
return System.Web.HttpUtility.HtmlEncode(comment).Replace("\n", "<br/>"); return System.Web.HttpUtility.HtmlEncode(comment).Replace("\n", "<br/>");
#else #else

View File

@ -18,6 +18,7 @@ namespace Luban.Job.Common.Utils
case ELanguage.JS: return fullName + ".js"; case ELanguage.JS: return fullName + ".js";
case ELanguage.TYPESCRIPT: return fullName.Replace('.', '/') + ".ts"; case ELanguage.TYPESCRIPT: return fullName.Replace('.', '/') + ".ts";
case ELanguage.RUST: return fullName.Replace('.', '_') + ".rs"; case ELanguage.RUST: return fullName.Replace('.', '_') + ".rs";
case ELanguage.PROTOBUF: return fullName.Replace('.', '_') + ".pb";
default: throw new NotSupportedException(); default: throw new NotSupportedException();
} }
@ -71,6 +72,7 @@ namespace Luban.Job.Common.Utils
{ "javascript", ELanguage.JS }, { "javascript", ELanguage.JS },
{ "erlang", ELanguage.ERLANG }, { "erlang", ELanguage.ERLANG },
{ "rust", ELanguage.RUST }, { "rust", ELanguage.RUST },
{ "pb", ELanguage.PROTOBUF },
}; };
public static ELanguage GetLanguage(string genType) public static ELanguage GetLanguage(string genType)
@ -96,6 +98,7 @@ namespace Luban.Job.Common.Utils
{ "erlang", "erl" }, { "erlang", "erl" },
{ "erl", "erl" }, { "erl", "erl" },
{ "xlsx", "xlsx" }, { "xlsx", "xlsx" },
{ "protobuf", "pb" },
}; };
public static string GetOutputFileSuffix(string genType) public static string GetOutputFileSuffix(string genType)

View File

@ -61,6 +61,9 @@
<None Update="Templates\common\lua\base.tpl"> <None Update="Templates\common\lua\base.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Update="Templates\common\pb\enum.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Templates\common\python\enum.tpl"> <None Update="Templates\common\python\enum.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
@ -163,6 +166,18 @@
<None Update="Templates\config\lua_lua\all.tpl"> <None Update="Templates\config\lua_lua\all.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Update="Templates\config\pb2\bean.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Templates\config\pb2\all.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Templates\config\pb2\table.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Templates\config\pb2\tables.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Templates\config\python_json\bean.tpl"> <None Update="Templates\config\python_json\bean.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>

View File

@ -0,0 +1,15 @@
{{~
name = x.name
namespace_with_top_module = x.namespace_with_top_module
comment = x.comment
items = x.items
~}}
enum {{x.pb_full_name}} {
{{~for item in items ~}}
{{x.pb_full_name}}_{{item.name}} = {{item.int_value}};
{{~end~}}
{{~if items.empty?~}}
{{x.pb_full_name}}_EMPTY_PLACEHOLDER = 0;
{{~end~}}
}

View File

@ -0,0 +1,33 @@
syntax = "proto2";
// luban internal types begin
message Vector2 {
required float x = 1;
required float y = 2;
}
message Vector3 {
required float x = 1;
required float y = 2;
required float z = 3;
}
message Vector4 {
required float x = 1;
required float y = 2;
required float z = 3;
required float w = 4;
}
// luban internal types end
{{~for enum in x.enums ~}}
{{enum}}
{{~end~}}
{{~for bean in x.beans~}}
{{bean}}
{{~end~}}
{{~for table in x.tables~}}
{{table}}
{{~end~}}

View File

@ -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
~}}
message {{x.pb_full_name}} {
{{~if x.is_abstract_type ~}}
oneof value {
{{~for c in x.hierarchy_not_abstract_children~}}
{{c.pb_full_name}} {{c.name}} = {{c.auto_id}};
{{~end~}}
}
{{~else~}}
{{~for f in hierarchy_export_fields ~}}
{{protobuf_pre_decorator f.ctype}} {{protobuf_define_type f.ctype}} {{f.name}} = {{f.auto_id}} {{protobuf_suffix_options f.ctype}};
{{~end~}}
{{~end~}}
}

View File

@ -0,0 +1,9 @@
{{~
name = x.name
key_type = x.key_ttype
value_type = x.value_ttype
~}}
message {{x.pb_full_name}} {
repeated {{protobuf_define_type value_type}} data_list = 1 [packed = false];
}

View File

@ -0,0 +1,13 @@
{{~
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~}}
}