Exemple #1
0
        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);
        }
Exemple #2
0
        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."));
                    }
                }
            }
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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
                });
            }
        }
Exemple #5
0
        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);
        }