using System;
using System.Collections;
using System.Globalization;
using System.IO;
namespace TBL.CSharp.Serialization.Marshal.Serializer
{
public unsafe partial class BinarySerializer : IMarshalSerializer
{
///
/// 使用指定上下文序列化一个可链接符号
///
private void SerializeLinkableSymbol(string symbol, BinaryWriter stream, IMarshalContext context)
{
// 在上下文中已链接的符号
if (context.FindLinkableSymbol(symbol, out var linkedId))
{
stream.Write(Marshal.TypeId.SymbolLink);
stream.Write(linkedId);
return;
}
// 序列化符号
context.AddLinkableSymbol(symbol);
stream.Write(Marshal.TypeId.Symbol);
stream.Write(symbol);
}
///
/// 使用指定上下文序列化一个可链接对象
///
private void SerializeLinkableObject(object self, BinaryWriter stream, IMarshalContext context)
{
// 在上下文中已链接的对象
if (context.FindLinkableObject(self, out var linkedId))
{
stream.Write(Marshal.TypeId.ObjectLink);
stream.Write(linkedId);
return;
}
// 未链接对象的原始处理
var type = self.GetType();
context.AddLinkableObject(self);
switch (self)
{
// 字符串对象
case string stringValue:
stream.Write(Marshal.TypeId.String);
stream.Write(stringValue);
break;
// 可使用流序列化的对象
case IStreamSerializable streamSerializable:
stream.Write(streamSerializable.IsShouldInitializeWhenDeserialize() ? Marshal.TypeId.SpecialStreamFull : Marshal.TypeId.SpecialStream);
SerializeLinkableSymbol(type.AssemblyQualifiedName, stream, context);
streamSerializable.Serialize(stream.BaseStream, _isNeedEndianConversion);
break;
// 可使用代理序列化的对象
case IProxiedSerializable proxiedSerializable:
stream.Write(proxiedSerializable.IsShouldInitializeWhenDeserialize() ? Marshal.TypeId.SpecialProxiedFull : Marshal.TypeId.SpecialProxied);
SerializeLinkableSymbol(type.AssemblyQualifiedName, stream, context);
Serialize(proxiedSerializable.ProxiedSerialize(), stream, context);
break;
// 可非安全序列化的对象
case IUnsafeSerializable unsafeSerializable:
stream.Write(unsafeSerializable.IsShouldInitializeWhenDeserialize() ? Marshal.TypeId.SpecialUnsafeFull : Marshal.TypeId.SpecialUnsafe);
SerializeLinkableSymbol(type.AssemblyQualifiedName, stream, context);
var size = unsafeSerializable.CalcSerializationSize();
var buffer = stackalloc byte[size];
stream.Write(size);
var realSize = _isNeedEndianConversion
? unsafeSerializable.SerializeWithEndianConversion(buffer)
: unsafeSerializable.Serialize(buffer);
for (var i = 0; i < size; i++)
stream.Write(buffer[i]);
break;
// 其它情况
default:
// 元组
if (type.IsSerializableTuple())
{
var rt = type.GetGenericArguments();
stream.Write(Marshal.TypeId.Tuple);
stream.Write((byte)rt.Length);
for (int i = 0, len = rt.Length; i < len; i++)
{
Serialize(type.GetField($"Item{i}").GetValue(self), stream, context);
}
}
// 一般多字段对象
else
{
stream.Write(Marshal.TypeId.Object);
SerializeLinkableSymbol(type.AssemblyQualifiedName, stream, context);
var fieldInfos = Marshal.GetTypeFields(type);
// 序列化列表接口部分
if (self is IList list)
{
stream.Write(Marshal.TypeId.List);
stream.Write(list.Count);
foreach (var element in list)
{
Serialize(element, stream, context);
}
}
// 存储目录部分
if (self is IDictionary dictionary)
{
stream.Write(Marshal.TypeId.Dictionary);
stream.Write(dictionary.Count);
foreach (var key in dictionary.Keys)
{
Serialize(key, stream, context);
Serialize(dictionary[key], stream, context);
}
}
// 存储字段部分
if (fieldInfos.Length > 0)
{
stream.Write(Marshal.TypeId.ObjectFields);
stream.Write(fieldInfos.Length);
foreach (var fieldInfo in fieldInfos)
{
SerializeLinkableSymbol(fieldInfo.Name, stream, context);
Serialize(fieldInfo.GetValue(self), stream, context);
}
}
// 对象尾标记
stream.Write(Marshal.TypeId.ObjectEnd);
}
break;
}
}
///
/// 使用指定上下文序列化对象
///
private void Serialize(object self, BinaryWriter stream, IMarshalContext context)
{
switch (self)
{
case null:
stream.Write(Marshal.TypeId.Null);
break;
case bool boolValue:
stream.Write(boolValue ? Marshal.TypeId.True : Marshal.TypeId.False);
break;
case sbyte int8Value:
stream.Write(Marshal.TypeId.Int8);
stream.Write(int8Value);
break;
case byte uint8Value:
stream.Write(Marshal.TypeId.Int8Unsigned);
stream.Write(uint8Value);
break;
case Int16 int16Value:
stream.Write(Marshal.TypeId.Int16);
stream.Write(int16Value);
break;
case UInt16 uint16Value:
stream.Write(Marshal.TypeId.Int16Unsigned);
stream.Write(uint16Value);
break;
case Int32 int32Value:
stream.Write(Marshal.TypeId.Int32);
stream.Write(int32Value);
break;
case UInt32 uint32Value:
stream.Write(Marshal.TypeId.Int32Unsigned);
stream.Write(uint32Value);
break;
case Int64 int64Value:
stream.Write(Marshal.TypeId.Int64);
stream.Write(int64Value);
break;
case UInt64 uint64Value:
stream.Write(Marshal.TypeId.Int64Unsigned);
stream.Write(uint64Value);
break;
case Single floatValue:
stream.Write(Marshal.TypeId.Single);
if (float.IsNaN(floatValue))
stream.Write(nameof(float.NaN));
else if (float.IsPositiveInfinity(floatValue))
stream.Write(nameof(float.PositiveInfinity));
else if (float.IsNegativeInfinity(floatValue))
stream.Write(nameof(float.NegativeInfinity));
else
stream.Write(Convert.ToString(floatValue, CultureInfo.InvariantCulture));
break;
case Double doubleValue:
stream.Write(Marshal.TypeId.Double);
if (double.IsNaN(doubleValue))
stream.Write(nameof(double.NaN));
else if (double.IsPositiveInfinity(doubleValue))
stream.Write(nameof(double.PositiveInfinity));
else if (double.IsNegativeInfinity(doubleValue))
stream.Write(nameof(double.NegativeInfinity));
else
stream.Write(Convert.ToString(doubleValue, CultureInfo.InvariantCulture));
break;
default:
SerializeLinkableObject(self, stream, context);
break;
}
}
///
/// 使用指定上下文序列化对象
///
/// 要序列化的对象
/// 序列化目标流
/// 指定的序列化上下文
public void Serialize(object self, Stream stream, IMarshalContext context)
{
using var writer = CreateBinaryWriter(stream);
Serialize(self, writer, context);
}
}
}