public static T Deserialize <T>(Stream stream) { Type tType = typeof(T); if (MsgPackSerializer.NativelySupportedTypes.Contains(tType)) { return(MsgPackItem.Unpack(stream).GetTypedValue <T>()); } MpMap map = (MpMap)MsgPackItem.Unpack(stream); T result = (T)Materialize(tType, map); return(result); }
private static void ValidateMap(MsgPackItem item, List <ValidationItem> issues) { MpMap map = (MpMap)item; MsgPackTypeId firstKeyType = map.PackedValues[0].Key.TypeId; if (!MsgPackMeta.StrTypeFamily.Contains(firstKeyType) && !MsgPackMeta.IntTypeFamily.Contains(firstKeyType) && firstKeyType != MsgPackTypeId.MpNull) { issues.Add(new ValidationItem(item, ValidationSeverity.Comment, 0, "A key of type ", MsgPackItem.GetOfficialTypeName(firstKeyType), " is rather unusual in a map. Some implementations might only support string or integer types as keys.")); } for (int t = map.PackedValues.Length - 1; t >= 0; t--) { if (ReferenceEquals(map.PackedValues[t].Key, null)) { continue; } if (map.PackedValues[t].Key.TypeId != firstKeyType && !MsgPackMeta.AreInSameFamily(map.PackedValues[t].Key.TypeId, firstKeyType)) { issues.Add(new ValidationItem(item, ValidationSeverity.Warning, 0, "The types of keys in this map do not appear to be consistent. Item 0 has a key of type ", MsgPackItem.GetOfficialTypeName(firstKeyType), " while item ", t, " has a key of type ", MsgPackItem.GetOfficialTypeName(map.PackedValues[t].Key.TypeId), ". Allthough the specs do not demand that keys are of the same type, it is likely that many implementations will assume that keys in a map are all of the same family.")); } for (int i = t - 1; i >= 0; i--) { if (ReferenceEquals(map.PackedValues[t].Key, null) || ReferenceEquals(map.PackedValues[i].Key, null) || ReferenceEquals(map.PackedValues[t].Key.Value, null)) { continue; } if (map.PackedValues[t].Key.Value.Equals(map.PackedValues[i].Key.Value)) { issues.Add(new ValidationItem(item, ValidationSeverity.Warning, 0, "This map has multiple entries with identical keys (items ", i, "='", map.PackedValues[i].Key.ToString(), "' and ", t, "='", map.PackedValues[t].Key.ToString(), "'). Allthough the specs do not demand unique keys, it is likely that many implementations will assume that keys in a map are unique.")); } } } }
private static object Materialize(Type tType, MpMap map) { PropertyInfo[] props = GetSerializedProps(tType); Dictionary <string, object> propVals = map.GetTypedValue <Dictionary <string, object> >(); object result = Activator.CreateInstance(tType); for (int t = props.Length - 1; t >= 0; t--) { object val; if (propVals.TryGetValue(props[t].Name, out val)) { Type propType = props[t].PropertyType; if (!ReferenceEquals(val, null)) { if (!MsgPackSerializer.NativelySupportedTypes.Contains(propType) && val is KeyValuePair <object, object>[]) { val = Materialize(propType, new MpMap((KeyValuePair <object, object>[])val)); } if (propType.IsArray && !(propType == typeof(object))) { // Need to cast object[] to whatever[] object[] valAsArr = (object[])val; propType = propType.GetElementType(); Array newInstance = Array.CreateInstance(propType, valAsArr.Length); // Part of the check for complex types can be done outside the loop bool complexTypes = !MsgPackSerializer.NativelySupportedTypes.Contains(propType); for (int i = valAsArr.Length - 1; i >= 0; i--) { if (complexTypes && !ReferenceEquals(valAsArr[i], null) && valAsArr[i] is KeyValuePair <object, object>[]) { valAsArr[i] = Materialize(propType, new MpMap((KeyValuePair <object, object>[])valAsArr[i])); } newInstance.SetValue(valAsArr[i], i); } props[t].SetValue(result, newInstance, null); continue; } if (typeof(IList).IsAssignableFrom(propType)) { IList newInstance = (IList)Activator.CreateInstance(propType); object[] valAsArr = (object[])val; // Part of the check for complex types can be done outside the loop bool complexTypes = !MsgPackSerializer.NativelySupportedTypes.Contains(propType); for (int i = 0; i < valAsArr.Length; i++) { if (complexTypes && !ReferenceEquals(valAsArr[i], null) && valAsArr[i] is KeyValuePair <object, object>[]) { valAsArr[i] = Materialize(propType, new MpMap((KeyValuePair <object, object>[])valAsArr[i])); } newInstance.Add(valAsArr[i]); } props[t].SetValue(result, newInstance, null); continue; } } // Fix ArgumentException like "System.Byte cannot be converted to System.Nullable`1[System.Int32]" Type nullableType = Nullable.GetUnderlyingType(props[t].PropertyType); if (!(nullableType is null) && !(val is null)) { if (val.GetType() != nullableType) { val = Convert.ChangeType(val, nullableType); } } props[t].SetValue(result, val, null); } } return(result); }
public static MsgPackItem Unpack(Stream stream, MsgPackSettings settings) { int typeByte = stream.ReadByte(); if (typeByte < 0) { return(new MpError(settings, stream.Position, MsgPackTypeId.NeverUsed, "Unexpected end of data.")); } MsgPackItem item = null; try { MsgPackTypeId type = (MsgPackTypeId)typeByte; switch (type) { case MsgPackTypeId.MpNull: item = new MpNull(settings); break; case MsgPackTypeId.MpBoolFalse: case MsgPackTypeId.MpBoolTrue: item = new MpBool(settings); break; //case MsgPackTypes.MpBytePart: //case MsgPackTypes.MpSBytePart: case MsgPackTypeId.MpSByte: case MsgPackTypeId.MpShort: case MsgPackTypeId.MpInt: case MsgPackTypeId.MpLong: case MsgPackTypeId.MpUByte: case MsgPackTypeId.MpUShort: case MsgPackTypeId.MpUInt: case MsgPackTypeId.MpULong: item = new MpInt(settings); break; case MsgPackTypeId.MpFloat: case MsgPackTypeId.MpDouble: item = new MpFloat(settings); break; //case MsgPackTypeId.MpStr5: case MsgPackTypeId.MpStr8: case MsgPackTypeId.MpStr16: case MsgPackTypeId.MpStr32: item = new MpString(settings); break; case MsgPackTypeId.MpBin8: case MsgPackTypeId.MpBin16: case MsgPackTypeId.MpBin32: item = new MpBin(settings); break; //case MsgPackTypeId.MpArray4: case MsgPackTypeId.MpArray16: case MsgPackTypeId.MpArray32: item = new MpArray(settings); break; //case MsgPackTypeId.MpMap4: case MsgPackTypeId.MpMap16: case MsgPackTypeId.MpMap32: item = new MpMap(settings); break; case MsgPackTypeId.MpFExt1: case MsgPackTypeId.MpFExt2: case MsgPackTypeId.MpFExt4: case MsgPackTypeId.MpFExt8: case MsgPackTypeId.MpFExt16: case MsgPackTypeId.MpExt8: case MsgPackTypeId.MpExt16: case MsgPackTypeId.MpExt32: item = new MpExt(settings); break; case MsgPackTypeId.NeverUsed: { long pos = stream.Position - 1; if (settings.ContinueProcessingOnBreakingError) { FindNextValidTypeId(stream); } return(new MpError(settings, pos, MsgPackTypeId.NeverUsed, "The specification specifically states that the value 0xC1 should never be used.") { storedLength = (stream.Position - pos) }); } } if (ReferenceEquals(item, null)) { if (((byte)type & 0xE0) == 0xE0 || (((byte)type & 0x80) == 0)) { item = new MpInt(settings); } else if (((byte)type & 0xA0) == 0xA0) { item = new MpString(settings); } else if (((byte)type & 0x90) == 0x90) { item = new MpArray(settings); } else if (((byte)type & 0x80) == 0x80) { item = new MpMap(settings); } } if (!ReferenceEquals(item, null)) { item.storedOffset = stream.Position - 1; item._settings = settings; // maybe redundent, but want to be sure MsgPackItem ret = item.Read(type, stream); item.storedLength = stream.Position - item.storedOffset; if (!ReferenceEquals(item, ret)) { ret.storedLength = item.storedLength; } return(ret); } else { long pos = stream.Position - 1; if (settings.ContinueProcessingOnBreakingError) { FindNextValidTypeId(stream); } return(new MpError(settings, pos, type, "The type identifier with value 0x", BitConverter.ToString(new byte[] { (byte)type }), " is either new or invalid. It is not (yet) implemented in this version of LsMsgPack.") { storedLength = (stream.Position - pos) }); } }catch (Exception ex) { long pos = stream.Position - 1; if (settings.ContinueProcessingOnBreakingError) { FindNextValidTypeId(stream); } return(new MpError(settings, new MsgPackException("Error while reading data.", ex, stream.Position, (MsgPackTypeId)typeByte)) { storedOffset = pos, storedLength = (stream.Position - pos), PartialItem = item }); } }
public static MsgPackItem Unpack(Stream stream) { int typeByte = stream.ReadByte(); if (typeByte < 0) { throw new MsgPackException("Unexpected end of data.", stream.Position); } MsgPackItem item = null; try { MsgPackTypeId type = (MsgPackTypeId)typeByte; switch (type) { case MsgPackTypeId.MpNull: item = new MpNull(); break; case MsgPackTypeId.MpBoolFalse: case MsgPackTypeId.MpBoolTrue: item = new MpBool(); break; //case MsgPackTypes.MpBytePart: //case MsgPackTypes.MpSBytePart: case MsgPackTypeId.MpSByte: case MsgPackTypeId.MpShort: case MsgPackTypeId.MpInt: case MsgPackTypeId.MpLong: case MsgPackTypeId.MpUByte: case MsgPackTypeId.MpUShort: case MsgPackTypeId.MpUInt: case MsgPackTypeId.MpULong: item = new MpInt(); break; case MsgPackTypeId.MpFloat: case MsgPackTypeId.MpDouble: item = new MpFloat(); break; //case MsgPackTypeId.MpStr5: case MsgPackTypeId.MpStr8: case MsgPackTypeId.MpStr16: case MsgPackTypeId.MpStr32: item = new MpString(); break; case MsgPackTypeId.MpBin8: case MsgPackTypeId.MpBin16: case MsgPackTypeId.MpBin32: item = new MpBin(); break; //case MsgPackTypeId.MpArray4: case MsgPackTypeId.MpArray16: case MsgPackTypeId.MpArray32: item = new MpArray(); break; //case MsgPackTypeId.MpMap4: case MsgPackTypeId.MpMap16: case MsgPackTypeId.MpMap32: item = new MpMap(); break; case MsgPackTypeId.MpFExt1: case MsgPackTypeId.MpFExt2: case MsgPackTypeId.MpFExt4: case MsgPackTypeId.MpFExt8: case MsgPackTypeId.MpFExt16: case MsgPackTypeId.MpExt8: case MsgPackTypeId.MpExt16: case MsgPackTypeId.MpExt32: item = new MpExt(); break; case MsgPackTypeId.NeverUsed: throw new MsgPackException("The specification specifically states that the value 0xC1 should never be used.", stream.Position - 1, MsgPackTypeId.NeverUsed); } if (ReferenceEquals(item, null)) { if (((byte)type & 0xE0) == 0xE0 || (((byte)type & 0x80) == 0)) { item = new MpInt(); } else if (((byte)type & 0xA0) == 0xA0) { item = new MpString(); } else if (((byte)type & 0x90) == 0x90) { item = new MpArray(); } else if (((byte)type & 0x80) == 0x80) { item = new MpMap(); } } if (!ReferenceEquals(item, null)) { return(item.Read(type, stream)); } else { throw new MsgPackException(string.Concat("The type identifier with value 0x", BitConverter.ToString(new byte[] { (byte)type }), " is either new or invalid. It is not (yet) implemented in this version of LsMsgPack."), stream.Position, type); } }catch (Exception ex) { if (!(ex is MsgPackException)) { MsgPackException mpex = new MsgPackException("Error while reading data.", ex, stream.Position, (MsgPackTypeId)typeByte); if (!ReferenceEquals(item, null)) { mpex.Data.Add("PartialMessage", item); } throw mpex; } else { throw; } } }
private static object Materialize(Type tType, MpMap map) { PropertyInfo[] props = GetSerializedProps(tType); Dictionary <string, object> propVals = map.GetTypedValue <Dictionary <string, object> >(); //object result = FormatterServices.GetUninitializedObject(tType); object result = Activator.CreateInstance(tType); for (int t = props.Length - 1; t >= 0; t--) { object val; if (propVals.TryGetValue(props[t].Name, out val)) { Type propType = props[t].PropertyType; if (!ReferenceEquals(val, null)) { if (!MsgPackSerializer.NativelySupportedTypes.Contains(propType) && val is KeyValuePair <object, object>[]) { val = Materialize(propType, new MpMap((KeyValuePair <object, object>[])val, map.Settings)); } if (propType.IsArray && !(propType == typeof(object))) { // Need to cast object[] to whatever[] object[] valAsArr = (object[])val; propType = propType.GetElementType(); Array newInstance = Array.CreateInstance(propType, valAsArr.Length); // Part of the check for complex types can be done outside the loop bool complexTypes = !MsgPackSerializer.NativelySupportedTypes.Contains(propType); for (int i = valAsArr.Length - 1; i >= 0; i--) { if (complexTypes && !ReferenceEquals(valAsArr[i], null) && valAsArr[i] is KeyValuePair <object, object>[]) { valAsArr[i] = Materialize(propType, new MpMap((KeyValuePair <object, object>[])valAsArr[i], map.Settings)); } newInstance.SetValue(valAsArr[i], i); } props[t].SetValue(result, newInstance, null); continue; } if (typeof(IList).IsAssignableFrom(propType)) { //IList newInstance = (IList)FormatterServices.GetUninitializedObject(propType); //ConstructorInfo constructor = propType.GetConstructor(Type.EmptyTypes); //constructor.Invoke(newInstance, null); IList newInstance = (IList)Activator.CreateInstance(propType); object[] valAsArr = (object[])val; // Part of the check for complex types can be done outside the loop bool complexTypes = !MsgPackSerializer.NativelySupportedTypes.Contains(propType); for (int i = 0; i < valAsArr.Length; i++) { if (complexTypes && !ReferenceEquals(valAsArr[i], null) && valAsArr[i] is KeyValuePair <object, object>[]) { valAsArr[i] = Materialize(propType, new MpMap((KeyValuePair <object, object>[])valAsArr[i], map.Settings)); } newInstance.Add(valAsArr[i]); } props[t].SetValue(result, newInstance, null); continue; } } props[t].SetValue(result, val, null); } } return(result); }