Created
October 3, 2017 10:34
-
-
Save neuecc/fae0f9975d90f2e99b1d6cd41b56e733 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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