Skip to content

Instantly share code, notes, and snippets.

@neuecc
Created October 3, 2017 10:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neuecc/fae0f9975d90f2e99b1d6cd41b56e733 to your computer and use it in GitHub Desktop.
Save neuecc/fae0f9975d90f2e99b1d6cd41b56e733 to your computer and use it in GitHub Desktop.
using CloudStructures;
using MessagePack;
using MessagePack.Formatters;
using MessagePack.Resolvers;
using System;
using StackExchange.Redis;
using System.Text;
// Ivory is our project name:)
namespace Ivory.Redis
{
public class IvoryMessagePackResolver : IFormatterResolver
{
public static readonly IFormatterResolver Instance = new IvoryMessagePackResolver();
static readonly IFormatterResolver[] resolvers = new[]
{
// NativeDateTimeResolver keep Kind.
NativeDateTimeResolver.Instance,
MessagePack.Resolvers.StandardResolver.Instance,
};
IvoryMessagePackResolver()
{
}
public IMessagePackFormatter<T> GetFormatter<T>()
{
return FormatterCache<T>.formatter;
}
static class FormatterCache<T>
{
public static readonly IMessagePackFormatter<T> formatter;
static FormatterCache()
{
foreach (var item in resolvers)
{
var f = item.GetFormatter<T>();
if (f != null)
{
formatter = f;
return;
}
}
}
}
}
public class MessagePackRedisValueConverter : IRedisValueConverter
{
readonly byte[] nilBytes;
public MessagePackRedisValueConverter()
{
nilBytes = new byte[1];
MessagePackBinary.WriteNil(ref nilBytes, 0);
}
static TypeCode GetNonNullableTypeCode(Type type)
{
return Type.GetTypeCode(Nullable.GetUnderlyingType(type) ?? type);
}
public RedisValue Serialize(object value, out long resultSize)
{
// RedisValue.Null should serialize MessagePack(store "null" is important)
if (value == null)
{
resultSize = 1;
return nilBytes;
}
var code = Type.GetTypeCode(value.GetType());
switch (code)
{
case TypeCode.Empty:
case TypeCode.DBNull:
resultSize = 0;
return RedisValue.Null;
case TypeCode.SByte:
resultSize = sizeof(SByte);
return (sbyte)value;
case TypeCode.Byte:
resultSize = sizeof(byte);
return (byte)value;
case TypeCode.Int16:
resultSize = sizeof(Int16);
return (Int16)value;
case TypeCode.Int32:
resultSize = sizeof(Int32);
return (Int32)value;
case TypeCode.Int64:
resultSize = sizeof(Int64);
return (Int64)value;
case TypeCode.UInt16:
resultSize = sizeof(UInt16);
return (UInt16)value;
case TypeCode.UInt32:
resultSize = sizeof(UInt32);
return (UInt32)value;
case TypeCode.UInt64:
resultSize = sizeof(UInt64);
return (UInt64)value;
case TypeCode.Single:
resultSize = sizeof(Single);
return (Single)value;
case TypeCode.Double:
resultSize = sizeof(Double);
return (Double)value;
case TypeCode.Boolean:
resultSize = sizeof(Boolean);
return (Boolean)value;
case TypeCode.Char:
resultSize = sizeof(Char);
return (Char)value;
case TypeCode.String:
var strByte = Encoding.UTF8.GetBytes((string)value);
resultSize = strByte.Length;
return strByte;
default:
var result = LZ4MessagePackSerializer.NonGeneric.Serialize(value.GetType(), value, IvoryMessagePackResolver.Instance);
resultSize = result.Length;
return result;
}
}
public object Deserialize(Type type, RedisValue value, out long valueSize)
{
if (value.IsNull)
{
valueSize = 0;
return null;
}
var code = GetNonNullableTypeCode(type);
switch (code)
{
case TypeCode.Empty:
case TypeCode.DBNull:
valueSize = 0;
return null;
case TypeCode.SByte:
valueSize = sizeof(SByte);
return (SByte)value;
case TypeCode.Byte:
valueSize = sizeof(Byte);
return (Byte)value;
case TypeCode.Int16:
valueSize = sizeof(Int16);
return (Int16)value;
case TypeCode.Int32:
valueSize = sizeof(Int32);
return (Int32)value;
case TypeCode.Int64:
valueSize = sizeof(Int64);
return (Int64)value;
case TypeCode.UInt16:
valueSize = sizeof(UInt16);
return (UInt16)value;
case TypeCode.UInt32:
valueSize = sizeof(UInt32);
return (UInt32)value;
case TypeCode.UInt64:
valueSize = sizeof(UInt64);
return (UInt64)value;
case TypeCode.Single:
valueSize = sizeof(Single);
return (Single)value;
case TypeCode.Double:
valueSize = sizeof(Double);
return (Double)value;
case TypeCode.Boolean:
valueSize = sizeof(Boolean);
return (Boolean)value;
case TypeCode.Char:
valueSize = sizeof(Char);
return (Char)value;
case TypeCode.String:
byte[] strByte = value;
valueSize = strByte.Length;
return Encoding.UTF8.GetString(strByte);
default:
byte[] buf = value;
valueSize = buf.Length;
return LZ4MessagePackSerializer.NonGeneric.Deserialize(type, buf, IvoryMessagePackResolver.Instance);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment