public static T Decode <T>(Unpacker unpacker, Func <string, Type> typeFinder, Func <Type, Unpacker, T> unpacking)
        {
            if (!unpacker.IsArrayHeader || UnpackHelpers.GetItemsCount(unpacker) != 2)
            {
                throw SerializationExceptions.NewUnknownTypeEmbedding();
            }

            using (var subTreeUnpacker = unpacker.ReadSubtree())
            {
                string typeCode;
                if (!subTreeUnpacker.ReadString(out typeCode))
                {
                    SerializationExceptions.ThrowUnexpectedEndOfStream(subTreeUnpacker);
                }

                var type = typeFinder(typeCode);

                if (!subTreeUnpacker.Read())
                {
                    SerializationExceptions.ThrowUnexpectedEndOfStream(subTreeUnpacker);
                }

                return(unpacking(type, subTreeUnpacker));
            }
        }
        public static async Task <T> DecodeAsync <T>(Unpacker unpacker, Func <string, Type> typeFinder, Func <Type, Unpacker, CancellationToken, Task <object> > unpackingAsync, CancellationToken cancellationToken)
        {
            if (!unpacker.IsArrayHeader || UnpackHelpers.GetItemsCount(unpacker) != 2)
            {
                throw SerializationExceptions.NewUnknownTypeEmbedding();
            }

            using (var subTreeUnpacker = unpacker.ReadSubtree())
            {
                var typeCode = await subTreeUnpacker.ReadStringAsync(cancellationToken).ConfigureAwait(false);

                if (!typeCode.Success)
                {
                    SerializationExceptions.ThrowUnexpectedEndOfStream(subTreeUnpacker);
                }

                var type = typeFinder(typeCode.Value);

                if (!await subTreeUnpacker.ReadAsync(cancellationToken).ConfigureAwait(false))
                {
                    SerializationExceptions.ThrowUnexpectedEndOfStream(subTreeUnpacker);
                }

                return((T) await unpackingAsync(type, subTreeUnpacker, cancellationToken).ConfigureAwait(false));
            }
        }
        protected internal override T UnpackFromCore(Unpacker unpacker)
        {
            // It is not reasonable to identify other forms.
            if (!unpacker.IsArrayHeader || UnpackHelpers.GetItemsCount(unpacker) != 3)
            {
                throw SerializationExceptions.NewUnknownTypeEmbedding();
            }

            using (var subTreeUnpacker = unpacker.ReadSubtree())
            {
                if (!subTreeUnpacker.Read())
                {
                    throw SerializationExceptions.NewUnexpectedEndOfStream();
                }
                var header = subTreeUnpacker.LastReadData.AsMessagePackExtendedTypeObject();
                if (header.TypeCode != this.OwnerContext.TypeEmbeddingSettings.TypeEmbeddingIdentifier)
                {
                    throw new SerializationException(
                              String.Format(CultureInfo.CurrentCulture, "Unknown extension type {0}.", header.TypeCode)
                              );
                }

                if (header.Body.Length != TypeInfoEncodingBytes.RawCompressed.Length ||
                    header.Body[0] != TypeInfoEncodingBytes.RawCompressed[0])
                {
                    throw new SerializationException("Unknown type info encoding type.");
                }

                if (!subTreeUnpacker.Read())
                {
                    throw SerializationExceptions.NewUnexpectedEndOfStream();
                }

                var objectType = TypeInfoEncoder.Decode(subTreeUnpacker);

                if (!subTreeUnpacker.Read())
                {
                    throw SerializationExceptions.NewUnexpectedEndOfStream();
                }

                return(( T )this.GetActualTypeSerializer(objectType).UnpackFrom(subTreeUnpacker));
            }
        }