public override MsgPackItem Read(MsgPackTypeId typeId, Stream data) { long len; if (!IsMasked(MsgPackTypeId.MpArray4, typeId, 0x0F, out len)) { switch (typeId) { case MsgPackTypeId.MpArray16: len = ReadLen(data, 2); break; case MsgPackTypeId.MpArray32: len = ReadLen(data, 4); break; default: throw new MsgPackException(string.Concat("MpArray does not support a type ID of ", GetOfficialTypeName(typeId), "."), data.Position - 1, typeId); } } value = new object[len]; for (int t = 0; t < len; t++) { MsgPackItem item = Unpack(data); value[t] = item.Value; } return(this); }
internal MpError(MsgPackSettings settings, MsgPackItem partialItemWithNestedError) : this(settings, partialItemWithNestedError.StoredOffset, partialItemWithNestedError.TypeId, string.Concat("A nested item contains an error. ", settings.ContinueProcessingOnBreakingError ? "Inspect the PartialItem to view the part of the message that could be read. Since the option 'ContinueProcessingOnBreakingError' is used, the 'IsBestGuess' property of each subitem will indicate if it was read before or after the error." : "Inspect the PartialItem to view the part of the message that could be read.")) { PartialItem = partialItemWithNestedError; }
public override MsgPackItem Read(MsgPackTypeId typeId, Stream data) { long len; if (!IsMasked(MsgPackTypeId.MpMap4, typeId, 0x0F, out len)) { switch (typeId) { case MsgPackTypeId.MpMap16: len = ReadLen(data, 2); break; case MsgPackTypeId.MpMap32: len = ReadLen(data, 4); break; default: throw new MsgPackException(string.Concat("MpMap does not support a type ID of ", GetOfficialTypeName(typeId), "."), data.Position - 1, typeId); } } value = new KeyValuePair <object, object> [len]; for (int t = 0; t < len; t++) { MsgPackItem key = MsgPackItem.Unpack(data); MsgPackItem val = MsgPackItem.Unpack(data); value[t] = new KeyValuePair <object, object>(key.Value, val.Value); } return(this); }
public static ValidationItem[] ValidateItem(MsgPackItem item) { List <ValidationItem> issues = new List <ValidationItem>(); if (item is MpInt) { ValidateInt(item, issues); } else if (item is MpError) { ValidateError((MpError)item, issues); } else if (item is MsgPackVarLen) { if (ValidateVarLength((MsgPackVarLen)item, issues)) { return(issues.ToArray()); // no use validating child aspects } if (item is MpMap) { ValidateMap(item, issues); } } return(issues.ToArray()); }
public static MsgPackItem SerializeObject(object item) { if (ReferenceEquals(item, null)) { return(new MpNull()); } Type tType = item.GetType(); if (MsgPackSerializer.NativelySupportedTypes.Contains(tType)) { return(MsgPackItem.Pack(item)); // Maybe we should rather throw an exception here } PropertyInfo[] props = GetSerializedProps(tType); Dictionary <string, object> propVals = new Dictionary <string, object>(props.Length); for (int t = props.Length - 1; t >= 0; t--) { propVals.Add(props[t].Name, props[t].GetValue(item, null)); } return(new MpMap() { Value = propVals }); }
private static void ValidateInt(MsgPackItem item, List <ValidationItem> issues) { try { MpInt intItem = (MpInt)item; item.Settings.DynamicallyCompact = true; MsgPackTypeId calcType = intItem.TypeId; if (calcType != intItem.PreservedType) { int used = MpInt.GetByteLengthForType(intItem.PreservedType); int potential = MpInt.GetByteLengthForType(calcType); if (potential < used) { issues.Add(new ValidationItem(item, ValidationSeverity.Warning, (used - potential), "This integer should have been stored in a smaller container (", MsgPackItem.GetOfficialTypeName(calcType), " instead of ", MsgPackItem.GetOfficialTypeName(intItem.PreservedType), "). This would have saved ", (used - potential), " bytes.")); } else if (MpInt.SignedTypeIds.Contains(intItem.PreservedType) && !MpInt.SignedTypeIds.Contains(calcType)) { issues.Add(new ValidationItem(item, ValidationSeverity.Comment, 0, "A positive integer has no need of a signing bit and can potentially be stored in a smaller container (in this case it did not matter).")); } } } finally { item.Settings.DynamicallyCompact = false; } }
public static void Serialize <T>(T item, Stream target) { MsgPackItem packed = SerializeObject(item); packed.ToStream(target); return; }
public static void Serialize <T>(T item, Stream target) { MsgPackItem packed = SerializeObject(item); byte[] buffer = packed.ToBytes(); target.Write(buffer, 0, buffer.Length); return; }
public static byte[] Serialize <T>(T item) { if (MsgPackSerializer.NativelySupportedTypes.Contains(typeof(T))) { return(MsgPackItem.Pack(item).ToBytes()); } MemoryStream ms = new MemoryStream(); Serialize(item, ms); return(ms.ToArray()); }
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); }
public override MsgPackItem Read(MsgPackTypeId typeId, Stream data) { long len; if (!IsMasked(MsgPackTypeId.MpArray4, typeId, 0x0F, out len)) { switch (typeId) { case MsgPackTypeId.MpArray16: len = ReadLen(data, 2); break; case MsgPackTypeId.MpArray32: len = ReadLen(data, 4); break; default: throw new MsgPackException(string.Concat("MpArray does not support a type ID of ", GetOfficialTypeName(typeId), "."), data.Position - 1, typeId); } } value = new object[len]; packedItems = new MsgPackItem[len]; bool errorOccurred = false; // keep a local copy in order not to wrap all items after an error in error nodes (just the one the error occurred in, and all parents) for (int t = 0; t < len; t++) { MsgPackItem item = Unpack(data, _settings); if (_settings._preservePackages) { packedItems[t] = item; } value[t] = item.Value; if (item is MpError) { if (_settings.ContinueProcessingOnBreakingError) { _settings.FileContainsErrors = true; errorOccurred = true; if (data.Position >= data.Length) { return(new MpError(_settings, this)); } } else { return(new MpError(_settings, this)); } } } if (errorOccurred) { return(new MpError(_settings, this)); } return(this); }
public override object GetValue(object component) { MsgPackTypeId item; if (component is MsgPackTypeId) { item = (MsgPackTypeId)component; } else { return(null); } return(MsgPackItem.GetTypeDescriptor(item).Description); }
public override long CalcBytesSize() { long retVal; MsgPackTypeId typeId = GetTypeId(value.LongLength); if (typeId == MsgPackTypeId.MpArray4) { retVal = 1; } else { retVal = 1 + GetLengthBytesSize(value.LongLength, SupportedLengths.FromShortUpward); } for (int t = 0; t < value.Length; t++) { MsgPackItem item = MsgPackItem.Pack(value[t]); retVal += item.CalcBytesSize(); } return(retVal); }
public override byte[] ToBytes() { List <byte> bytes = new List <byte>();// cannot estimate this one MsgPackTypeId typeId = GetTypeId(value.LongLength); if (typeId == MsgPackTypeId.MpArray4) { bytes.Add(GetLengthBytes(typeId, value.Length)); } else { bytes.Add((byte)typeId); bytes.AddRange(GetLengthBytes(value.LongLength, SupportedLengths.FromShortUpward)); } for (int t = 0; t < value.Length; t++) { MsgPackItem item = MsgPackItem.Pack(value[t], _settings); bytes.AddRange(item.ToBytes()); } return(bytes.ToArray()); }
public override void ToStream(Stream stream) { MsgPackTypeId typeId = GetTypeId(value.LongLength); if (typeId == MsgPackTypeId.MpArray4) { stream.WriteByte(GetLengthBytes(typeId, value.Length)); } else { stream.WriteByte((byte)typeId); var lenBytes = GetLengthBytes(value.LongLength, SupportedLengths.FromShortUpward); stream.Write(lenBytes, 0, lenBytes.Length); } for (int t = 0; t < value.Length; t++) { MsgPackItem item = MsgPackItem.Pack(value[t]); item.ToStream(stream); } }
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 bool ValidateVarLength(MsgPackVarLen item, List <ValidationItem> issues) { if (item.Count == 0) { int waisted; switch (item.TypeId) { case MsgPackTypeId.MpMap16: waisted = 2; break; case MsgPackTypeId.MpMap32: waisted = 4; break; case MsgPackTypeId.MpArray16: waisted = 2; break; case MsgPackTypeId.MpArray32: waisted = 4; break; case MsgPackTypeId.MpBin8: waisted = 1; break; case MsgPackTypeId.MpBin16: waisted = 2; break; case MsgPackTypeId.MpBin32: waisted = 4; break; case MsgPackTypeId.MpExt8: waisted = 1; break; case MsgPackTypeId.MpExt16: waisted = 2; break; case MsgPackTypeId.MpExt32: waisted = 4; break; case MsgPackTypeId.MpStr8: waisted = 1; break; case MsgPackTypeId.MpStr16: waisted = 2; break; case MsgPackTypeId.MpStr32: waisted = 4; break; default: waisted = 0; break; } issues.Add(new ValidationItem(item, ValidationSeverity.Warning, waisted, "Consider using a null (nil) value instead of an empty ", MsgPackItem.GetOfficialTypeName(item.TypeId), " instance.")); return(true); } return(false); }
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 Pack(object value, MsgPackSettings settings) { if (ReferenceEquals(value, null)) { return(new MpNull(settings)); } if (value is bool) { return new MpBool(settings) { Value = value } } ; if (value is sbyte || value is short || value is int || value is long || value is byte || value is ushort || value is uint || value is ulong) { return new MpInt(settings) { Value = value } } ; if (value is float || value is double) { return new MpFloat(settings) { Value = value } } ; if (value is string) { return new MpString(settings) { Value = value } } ; if (value is byte[]) { return new MpBin(settings) { Value = value } } ; if (value is object[]) { return new MpArray(settings) { Value = value } } ; Type valuesType = value.GetType(); if (valuesType.IsEnum) { return(new MpInt(settings).SetEnumVal(value)); } if (IsSubclassOfArrayOfRawGeneric(typeof(KeyValuePair <,>), valuesType)) { return new MpMap(settings) { Value = value } } ; if (IsSubclassOfRawGeneric(typeof(Dictionary <,>), valuesType)) { return new MpMap(settings) { Value = value } } ; if (valuesType.IsArray) { return new MpArray(settings) { Value = ((IEnumerable)value).Cast <Object>().ToArray() } } ; if (typeof(IEnumerable).IsAssignableFrom(valuesType)) { return new MpArray(settings) { Value = ((IEnumerable)value).Cast <Object>().ToArray() } } ; // Extension types will come in like this most of the time: MsgPackItem val = value as MsgPackItem; if (!ReferenceEquals(val, null)) { val._settings = settings; return(val); } return(MsgPackSerializer.SerializeObject(value, settings)); }
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; } } }
public override MsgPackItem Read(MsgPackTypeId typeId, Stream data) { long len; if (!IsMasked(MsgPackTypeId.MpMap4, typeId, 0x0F, out len)) { switch (typeId) { case MsgPackTypeId.MpMap16: len = ReadLen(data, 2); break; case MsgPackTypeId.MpMap32: len = ReadLen(data, 4); break; default: throw new MsgPackException(string.Concat("MpMap does not support a type ID of ", GetOfficialTypeName(typeId), "."), data.Position - 1, typeId); } } value = new KeyValuePair <object, object> [len]; packedItems = new KeyValuePair <MsgPackItem, MsgPackItem> [len]; bool errorOccurred = false; for (int t = 0; t < len; t++) { MsgPackItem key = MsgPackItem.Unpack(data, _settings); MsgPackItem val; if (key is MpError) { if (_settings.ContinueProcessingOnBreakingError) { _settings.FileContainsErrors = true; errorOccurred = true; if (data.Position >= data.Length) { val = new MpNull(_settings); } else { val = MsgPackItem.Unpack(data, _settings); } } else { val = new MpNull(_settings); } } else { val = MsgPackItem.Unpack(data, _settings); } if (_settings._preservePackages) { packedItems[t] = new KeyValuePair <MsgPackItem, MsgPackItem>(key, val); } value[t] = new KeyValuePair <object, object>(key.Value, val.Value); if (!_settings.ContinueProcessingOnBreakingError && (key is MpError || val is MpError)) { return(new MpError(_settings, this)); } if (val is MpError) { _settings.FileContainsErrors = true; errorOccurred = true; if (data.Position >= data.Length) { return(new MpError(_settings, this)); } } } if (errorOccurred) { return(new MpError(_settings, this)); } return(this); }
public static MsgPackItem Pack(object value) { if (ReferenceEquals(value, null)) { return(new MpNull()); } var typeCode = Type.GetTypeCode(value.GetType()); switch (typeCode) { case TypeCode.Boolean: return(new MpBool() { Value = value }); case TypeCode.SByte: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.Byte: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: return(new MpInt() { Value = value }); case TypeCode.Single: case TypeCode.Double: return(new MpFloat() { Value = value }); case TypeCode.String: return(new MpString() { Value = value }); case TypeCode.DateTime: return(new MpDateTime() { Value = value }); default: if (value is byte[]) { return new MpBin() { Value = value } } ; if (value is object[]) { return new MpArray() { Value = value } } ; if (value is DateTimeOffset) { return new MpDateTime() { Value = value } } ; break; } Type valuesType = value.GetType(); //if (valuesType.IsEnum) return new MpInt().SetEnumVal(value); if (valuesType.IsEnum) { return new MpInt() { Value = value } } ; if (IsSubclassOfArrayOfRawGeneric(typeof(KeyValuePair <,>), valuesType)) { return new MpMap() { Value = value } } ; if (IsSubclassOfRawGeneric(typeof(Dictionary <,>), valuesType)) { return new MpMap() { Value = value } } ; if (valuesType.IsArray) { return new MpArray() { Value = ((IEnumerable)value).Cast <Object>().ToArray() } } ; if (typeof(IEnumerable).IsAssignableFrom(valuesType)) { return new MpArray() { Value = ((IEnumerable)value).Cast <Object>().ToArray() } } ; // Extension types will come in like this most of the time: MsgPackItem val = value as MsgPackItem; if (!ReferenceEquals(val, null)) { return(val); } return(MsgPackSerializer.SerializeObject(value)); }
public ValidationItem(MsgPackItem item, ValidationSeverity severity, int waistedBytes, params object[] message) { Severity = severity; WaistedBytes = waistedBytes; Message = string.Concat(message); }