/// <summary> /// Utility method to unpack from msgpack. /// </summary> /// <remarks>Will be used recursively to parse nested messages</remarks> /// <param name="unpacker"></param> /// <returns></returns> /// <exception cref="TypeNotSupportedException">Thrown, when a datatype of msgpack is not supported, e.g. enums</exception> /// <exception cref="ParseMessageException">Generic exception </exception> /// <exception cref="OverflowException" >Thrown from msgpack, if a received long does not fit into an int.</exception> protected override Message UnpackFromCore(Unpacker unpacker) { var message = new Message(); if (!unpacker.IsMapHeader) { throw new ParseMessageException("Incoming msgpack stream does not seem to be a Map, only Maps can be transcoded to Message. Did you rewind Position?"); } var count = unpacker.ItemsCount; while (count > 0 && AssertSuccess(unpacker.Read())) { count--; if (!unpacker.LastReadData.IsRaw) { throw new ParseMessageException("Only strings can be keys of supported dictionaries. Sorry, only Json style here"); } string fieldName = unpacker.LastReadData.AsString(); if (fieldName == "Topic") { string topic; unpacker.ReadString(out topic); message.Topic = topic; continue; } if (fieldName == "Stamp") { MessagePackExtendedTypeObject ext; unpacker.ReadMessagePackExtendedTypeObject(out ext); message.TimeStamp = TimeSerializer.UnpackSingleObject(ext.GetBody()); continue; } Bin bin; AssertSuccess(unpacker.Read()); if (unpacker.IsMapHeader) // single Message { bin = BinFactory.New(UnpackFromCore(unpacker)); } else if (unpacker.IsArrayHeader) // multiples! { long binCount = unpacker.LastReadData.AsInt64(); if (binCount <= 0) { continue; // cannot infer type, so skip } AssertSuccess(unpacker.Read()); // populates a new MessagePackObject, GC ahoy if (unpacker.IsMapHeader) // multiple nested messages { bin = BinFactory.New <Message>(UnpackFromCore(unpacker)); for (int i = 1; i < binCount; i++) { AssertSuccess(unpacker.Read()); bin.Add(UnpackFromCore(unpacker)); } } else // multiple slices { bin = BinFromCurrent(unpacker); var alias = TypeIdentity.Instance[bin.GetInnerType()].Alias; for (int i = 1; i < binCount; i++) { AssertSuccess(unpacker.Read()); var item = FromCurrent(unpacker, alias); bin.Add(item); } } } else // single slice of non-Message { bin = BinFromCurrent(unpacker); } message[fieldName] = bin; } return(message); }