コード例 #1
0
        /// <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);
        }