using MessagePack.Internal;
using System;
using System.IO;
namespace MessagePack
{
///
/// High-Level API of MessagePack for C#.
///
public static partial class MessagePackSerializer
{
static IFormatterResolver defaultResolver;
///
/// FormatterResolver that used resolver less overloads. If does not set it, used StandardResolver.
///
public static IFormatterResolver DefaultResolver
{
get
{
if (defaultResolver == null)
{
defaultResolver = MessagePack.Resolvers.StandardResolver.Instance;
}
return defaultResolver;
}
}
///
/// Is resolver decided?
///
public static bool IsInitialized
{
get
{
return defaultResolver != null;
}
}
///
/// Set default resolver of MessagePackSerializer APIs.
///
///
public static void SetDefaultResolver(IFormatterResolver resolver)
{
defaultResolver = resolver;
}
///
/// Serialize to binary with default resolver.
///
public static byte[] Serialize(T obj)
{
return Serialize(obj, defaultResolver);
}
///
/// Serialize to binary with specified resolver.
///
public static byte[] Serialize(T obj, IFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
var formatter = resolver.GetFormatterWithVerify();
var buffer = InternalMemoryPool.GetBuffer();
var len = formatter.Serialize(ref buffer, 0, obj, resolver);
// do not return MemoryPool.Buffer.
return MessagePackBinary.FastCloneWithResize(buffer, len);
}
///
/// Serialize to binary. Get the raw memory pool byte[]. The result can not share across thread and can not hold, so use quickly.
///
public static ArraySegment SerializeUnsafe(T obj)
{
return SerializeUnsafe(obj, defaultResolver);
}
///
/// Serialize to binary with specified resolver. Get the raw memory pool byte[]. The result can not share across thread and can not hold, so use quickly.
///
public static ArraySegment SerializeUnsafe(T obj, IFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
var formatter = resolver.GetFormatterWithVerify();
var buffer = InternalMemoryPool.GetBuffer();
var len = formatter.Serialize(ref buffer, 0, obj, resolver);
// return raw memory pool, unsafe!
return new ArraySegment(buffer, 0, len);
}
///
/// Serialize to stream.
///
public static void Serialize(Stream stream, T obj)
{
Serialize(stream, obj, defaultResolver);
}
///
/// Serialize to stream with specified resolver.
///
public static void Serialize(Stream stream, T obj, IFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
var formatter = resolver.GetFormatterWithVerify();
var buffer = InternalMemoryPool.GetBuffer();
var len = formatter.Serialize(ref buffer, 0, obj, resolver);
// do not need resize.
stream.Write(buffer, 0, len);
}
///
/// Reflect of resolver.GetFormatterWithVerify[T].Serialize.
///
public static int Serialize(ref byte[] bytes, int offset, T value, IFormatterResolver resolver)
{
return resolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value, resolver);
}
#if NETSTANDARD
///
/// Serialize to stream(async).
///
public static System.Threading.Tasks.Task SerializeAsync(Stream stream, T obj)
{
return SerializeAsync(stream, obj, defaultResolver);
}
///
/// Serialize to stream(async) with specified resolver.
///
public static async System.Threading.Tasks.Task SerializeAsync(Stream stream, T obj, IFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
var formatter = resolver.GetFormatterWithVerify();
var rentBuffer = BufferPool.Default.Rent();
try
{
var buffer = rentBuffer;
var len = formatter.Serialize(ref buffer, 0, obj, resolver);
// do not need resize.
await stream.WriteAsync(buffer, 0, len).ConfigureAwait(false);
}
finally
{
BufferPool.Default.Return(rentBuffer);
}
}
#endif
public static T Deserialize(byte[] bytes)
{
return Deserialize(bytes, defaultResolver);
}
public static T Deserialize(byte[] bytes, IFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
var formatter = resolver.GetFormatterWithVerify();
int readSize;
return formatter.Deserialize(bytes, 0, resolver, out readSize);
}
public static T Deserialize(ArraySegment bytes)
{
return Deserialize(bytes, defaultResolver);
}
public static T Deserialize(ArraySegment bytes, IFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
var formatter = resolver.GetFormatterWithVerify();
int readSize;
return formatter.Deserialize(bytes.Array, bytes.Offset, resolver, out readSize);
}
public static T Deserialize(Stream stream)
{
return Deserialize(stream, defaultResolver);
}
public static T Deserialize(Stream stream, IFormatterResolver resolver)
{
return Deserialize(stream, resolver, false);
}
public static T Deserialize(Stream stream, bool readStrict)
{
return Deserialize(stream, defaultResolver, readStrict);
}
public static T Deserialize(Stream stream, IFormatterResolver resolver, bool readStrict)
{
if (resolver == null) resolver = DefaultResolver;
var formatter = resolver.GetFormatterWithVerify();
if (!readStrict)
{
#if NETSTANDARD && !NET45
var ms = stream as MemoryStream;
if (ms != null)
{
// optimize for MemoryStream
ArraySegment buffer;
if (ms.TryGetBuffer(out buffer))
{
int readSize;
return formatter.Deserialize(buffer.Array, buffer.Offset, resolver, out readSize);
}
}
#endif
// no else.
{
var buffer = InternalMemoryPool.GetBuffer();
FillFromStream(stream, ref buffer);
int readSize;
return formatter.Deserialize(buffer, 0, resolver, out readSize);
}
}
else
{
int _;
var bytes = MessagePackBinary.ReadMessageBlockFromStreamUnsafe(stream, false, out _);
int readSize;
return formatter.Deserialize(bytes, 0, resolver, out readSize);
}
}
///
/// Reflect of resolver.GetFormatterWithVerify[T].Deserialize.
///
public static T Deserialize(byte[] bytes, int offset, IFormatterResolver resolver, out int readSize)
{
return resolver.GetFormatterWithVerify().Deserialize(bytes, offset, resolver, out readSize);
}
#if NETSTANDARD
public static System.Threading.Tasks.Task DeserializeAsync(Stream stream)
{
return DeserializeAsync(stream, defaultResolver);
}
// readStrict async read is too slow(many Task garbage) so I don't provide async option.
public static async System.Threading.Tasks.Task DeserializeAsync(Stream stream, IFormatterResolver resolver)
{
var rentBuffer = BufferPool.Default.Rent();
var buf = rentBuffer;
try
{
int length = 0;
int read;
while ((read = await stream.ReadAsync(buf, length, buf.Length - length).ConfigureAwait(false)) > 0)
{
length += read;
if (length == buf.Length)
{
MessagePackBinary.FastResize(ref buf, length * 2);
}
}
return Deserialize(buf, resolver);
}
finally
{
BufferPool.Default.Return(rentBuffer);
}
}
#endif
static int FillFromStream(Stream input, ref byte[] buffer)
{
int length = 0;
int read;
while ((read = input.Read(buffer, length, buffer.Length - length)) > 0)
{
length += read;
if (length == buffer.Length)
{
MessagePackBinary.FastResize(ref buffer, length * 2);
}
}
return length;
}
}
}
namespace MessagePack.Internal
{
internal static class InternalMemoryPool
{
[ThreadStatic]
static byte[] buffer = null;
public static byte[] GetBuffer()
{
if (buffer == null)
{
buffer = new byte[65536];
}
return buffer;
}
}
}