329 lines
10 KiB
C#
329 lines
10 KiB
C#
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 ProtobufBinExportor : IDataActionVisitor<CodedOutputStream>
|
|
{
|
|
public static ProtobufBinExportor 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.WriteInt64(type.UnixTimeOfCurrentAssembly);
|
|
}
|
|
|
|
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格式是无法支持动态本土化的。
|
|
x.WriteString(type.TextOfCurrentAssembly);
|
|
}
|
|
|
|
private MemoryStream AllocMemoryStream()
|
|
{
|
|
// TODO 优化
|
|
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);
|
|
}
|
|
|
|
private void WriteRawMessageWithoutLength(DBean type, CodedOutputStream temp)
|
|
{
|
|
//var ms = AllocMemoryStream();
|
|
//var temp = new CodedOutputStream(ms);
|
|
//if (bean.IsAbstractType)
|
|
//{
|
|
// temp.WriteTag(type.ImplType.AutoId, WireFormat.WireType.LengthDelimited);
|
|
//}
|
|
|
|
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 EnterScope(CodedOutputStream x, Action<CodedOutputStream> action)
|
|
{
|
|
var ms = AllocMemoryStream();
|
|
var temp = new CodedOutputStream(ms);
|
|
action(temp);
|
|
temp.Flush();
|
|
ms.Seek(0, SeekOrigin.Begin);
|
|
var bs = ByteString.FromStream(ms);
|
|
x.WriteBytes(bs);
|
|
FreeMemoryStream(ms);
|
|
}
|
|
|
|
public void Accept(DBean type, CodedOutputStream x)
|
|
{
|
|
EnterScope(x, cos =>
|
|
{
|
|
var bean = type.Type;
|
|
|
|
if (bean.IsAbstractType)
|
|
{
|
|
cos.WriteTag(type.ImplType.AutoId, WireFormat.WireType.LengthDelimited);
|
|
EnterScope(cos, cos2 => WriteRawMessageWithoutLength(type, cos2));
|
|
}
|
|
else
|
|
{
|
|
WriteRawMessageWithoutLength(type, cos);
|
|
}
|
|
});
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
}
|