示例#1
0
    public ActionRequest <TReqParams, TRespData> Deserialize(ref MessagePackReader reader,
                                                             MessagePackSerializerOptions options)
    {
        if (!reader.TryReadMapHeader(out var elementCount))
        {
            throw new MessagePackSerializationException();
        }

        var actionSeq = ReadOnlySequence <byte> .Empty;
        var paramsSeq = ReadOnlySequence <byte> .Empty;
        var echo      = string.Empty;

        // `elementCount` shall be 2 or 3.
        for (var i = 0; i < elementCount; i++)
        {
            if (reader.TryReadStringSpan(out var propertyName))
            {
                if (propertyName.SequenceEqual(ConstantsOfAction.sActionPropertyName))
                {
                    actionSeq = reader.ReadRaw();
                }
                else if (propertyName.SequenceEqual(ConstantsOfAction.sParamsPropertyName))
                {
                    paramsSeq = reader.ReadRaw();
                }
                else if (propertyName.SequenceEqual(ConstantsOfAction.sEchoPropertyName))
                {
                    echo = reader.ReadString();
                }
            }
        }

        var action = MessagePackSerializer.Deserialize <ActionType>(actionSeq, options) ?? ActionType.Unknown with
        {
            Key = MessagePackSerializer.Deserialize <string>(actionSeq, options)
        };

        var param = MessagePackSerializer.Deserialize(typeof(TReqParams), paramsSeq, options);

        // Full-trust `ActionType`, so `GetUninitializedObject` is safe, but it is f**king SLOW.
        // var zeroObj = FormatterServices.GetUninitializedObject(action.ClassType);
        // `Activator` is much (4x-6x) faster, but it depends on the constructor.
        var zeroObj = Activator.CreateInstance(action.ClassType, param, echo);

        if (zeroObj is ActionRequest <TReqParams, TRespData> req && param is TReqParams reqParam)
        {
            return(req with {
                Action = action, Params = reqParam, Echo = echo
            });
        }

        // Failed in deserialize.
        throw new NotSupportedException(
                  $"{nameof(ActionType)} {Encoding.UTF8.GetString(actionSeq)} is not supported by {nameof(MsgPackActionRequestFormatter<TReqParams, TRespData>)}.");
    }
}
示例#2
0
        public ReadOnlySequence <T> Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
        {
            if (reader.TryReadNil())
            {
                return(ReadOnlySequence <T> .Empty);
            }

            var header = reader.ReadExtensionFormatHeader();

            if (header.TypeCode != TypeCode)
            {
                throw new MessagePackSerializationException("Extension TypeCode is invalid. typeCode: " + header.TypeCode);
            }

            if (header.Length == 0)
            {
                return(ReadOnlySequence <T> .Empty);
            }

            var elementCount = header.Length / sizeof(T);

            if (elementCount * sizeof(T) != header.Length)
            {
                throw new MessagePackSerializationException("Extension Length is invalid. actual: " + header.Length + ", element size: " + sizeof(T));
            }

            var answer = new T[elementCount];

            reader.ReadRaw(header.Length).CopyTo(MemoryMarshal.AsBytes(answer.AsSpan()));
            return(new ReadOnlySequence <T>(answer));
        }
        public T Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
        {
            var header = reader.ReadExtensionFormatHeader();

            if (header.TypeCode != TypeCode)
            {
                throw new MessagePackSerializationException("Extension TypeCode is invalid. typeCode: " + header.TypeCode);
            }

            if (header.Length != sizeof(T))
            {
                throw new MessagePackSerializationException("Extension Length is invalid. actual: " + header.Length + ", expected: " + sizeof(T));
            }

            var sequence = reader.ReadRaw(sizeof(T));

            if (sequence.IsSingleSegment)
            {
                return(Unsafe.As <byte, T>(ref Unsafe.AsRef(sequence.FirstSpan[0])));
            }

            T answer;

            sequence.CopyTo(new Span <byte>(&answer, sizeof(T)));
            return(answer);
        }
示例#4
0
    public Segment Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
    {
        if (!reader.TryReadMapHeader(out var elementCount))
        {
            throw new MessagePackSerializationException();
        }

        var typeSeq = ReadOnlySequence <byte> .Empty;
        var dataSeq = ReadOnlySequence <byte> .Empty;

        // `elementCount` shall be 2.
        for (var i = 0; i < elementCount; i++)
        {
            if (reader.TryReadStringSpan(out var propertyName))
            {
                if (propertyName.SequenceEqual(sTypePropertyName))
                {
                    typeSeq = reader.ReadRaw();
                }
                else if (propertyName.SequenceEqual(sDataPropertyName))
                {
                    dataSeq = reader.ReadRaw();
                }
            }
        }

        var type = MessagePackSerializer.Deserialize <SegmentType>(typeSeq, options) ?? SegmentType.Unknown with
        {
            Key = MessagePackSerializer.Deserialize <string>(typeSeq, options)
        };
        var data = MessagePackSerializer.Deserialize(type.ClassType, dataSeq, options);

        if (data is SegmentData d)
        {
            // BUG: `SegmentData` ignores `ExtensionData`.
            return(new Segment(type, d));
        }

        // Failed in deserialize `data`, not supported `Segment` yet.
        throw new NotSupportedException(
                  $"{nameof(SegmentType)} {Encoding.UTF8.GetString(typeSeq)} is not supported by {nameof(MsgPackSegmentFormatter)}.");
    }
}
        private object ReadItem(ref MessagePackReader reader, string invocationId)
        {
            long longId = 0;

            if (long.TryParse(invocationId, out longId))
            {
                Type itemType = this.Connection.GetItemType(longId);

                return(MessagePackSerializer.Deserialize(itemType, reader.ReadRaw()));
                //return MessagePackSerializer.Deserialize(itemType, ref reader);
            }
            else
            {
                reader.Skip();
                return(null);
            }
        }
示例#6
0
        public UInt160 Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
        {
            // post RC3 serialization format of UInt160
            if (reader.NextMessagePackType == MessagePackType.Binary)
            {
                var value = options.Resolver.GetFormatter <byte[]>().Deserialize(ref reader, options);
                return(new UInt160(value));
            }

            // pre RC3 serialization format of UInt160
            if (reader.NextMessagePackType == MessagePackType.Integer)
            {
                var seq = reader.ReadRaw(UInt160.Length);
                return(new UInt160(seq.IsSingleSegment ? seq.FirstSpan : seq.ToArray()));
            }

            throw new MessagePackSerializationException($"Unexpected UInt160 MessagePack type {reader.NextMessagePackType}");
        }
    private CompletionMessage CreateCompletionMessage(ref MessagePackReader reader, IInvocationBinder binder)
    {
        var headers      = ReadHeaders(ref reader);
        var invocationId = ReadInvocationId(ref reader);
        var resultKind   = ReadInt32(ref reader, "resultKind");

        string?error     = null;
        object?result    = null;
        var    hasResult = false;

        switch (resultKind)
        {
        case ErrorResult:
            error = ReadString(ref reader, "error");
            break;

        case NonVoidResult:
            var itemType = binder.GetReturnType(invocationId);
            if (itemType == typeof(RawResult))
            {
                result = new RawResult(reader.ReadRaw());
            }
            else
            {
                result = DeserializeObject(ref reader, itemType, "argument");
            }
            hasResult = true;
            break;

        case VoidResult:
            hasResult = false;
            break;

        default:
            throw new InvalidDataException("Invalid invocation result kind.");
        }

        return(ApplyHeaders(headers, new CompletionMessage(invocationId, error, result, hasResult)));
    }
示例#8
0
        public T[] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
        {
            if (reader.TryReadNil())
            {
                return(null);
            }

            ExtensionHeader header = reader.ReadExtensionFormatHeader();

            if (header.TypeCode != this.TypeCode)
            {
                throw new InvalidOperationException("Invalid typeCode.");
            }

            var byteLength     = reader.ReadInt32();
            var isLittleEndian = reader.ReadBoolean();

            // Allocate a T[] that we will return. We'll then cast the T[] as byte[] so we can copy the byte sequence directly into it.
            var         result        = new T[byteLength / Marshal.SizeOf <T>()];
            Span <byte> resultAsBytes = MemoryMarshal.Cast <T, byte>(result);

            reader.ReadRaw(byteLength).CopyTo(resultAsBytes);

            // Reverse the byte order if necessary.
            if (isLittleEndian != BitConverter.IsLittleEndian)
            {
                for (int i = 0, j = resultAsBytes.Length - 1; i < j; i++, j--)
                {
                    byte tmp = resultAsBytes[i];
                    resultAsBytes[i] = resultAsBytes[j];
                    resultAsBytes[j] = tmp;
                }
            }

            return(result);
        }
示例#9
0
        public TFrameList Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
        {
            if (reader.TryReadNil())
            {
                return((TFrameList)(IList <T>)null);
            }

            Interlocked.Increment(ref ParallelGatekeeperSingleton.wrapperDepth);
            try
            {
                options.Security.DepthStep(ref reader);
                try
                {
                    FrameFormatterSerializationOptions frameOptions = options.GetOptionParams();
                    if (frameOptions.MthWorkerConfig.MaxConcurrentTasks == 1 || ParallelGatekeeperSingleton.wrapperDepth > 1)
                    {
                        return(DeserializeSynchronous(ref reader, options));
                    }

                    var readerBackup = reader.CreatePeekReader();
                    int count        = reader.ReadArrayHeader();
                    if (count == 0)
                    {
                        reader = readerBackup;
                        return(DeserializeSynchronous(ref reader, options));
                    }
                    var peekreader = reader.CreatePeekReader();
                    if (FrameItemFormatter <T> .ReadElementHeader(ref peekreader) == Frame <T> .unassigned)
                    {
                        if (frameOptions.ThrowOnUnnasignedFrameDeserialization)
                        {
                            throw new StreamSerializationException($"Unassigned buffer length found during parallel deserialize for {nameof(TFrameList)}");
                        }
                        reader = readerBackup;
                        return(DeserializeSynchronous(ref reader, options));
                    }

                    IMessagePackFormatter <T> formatterT   = options.Resolver.GetFormatterWithVerify <T>();
                    ListFrameWrapper          valueWrapper = GetTFrameListWrapper(count);
                    Frame <T>[]        resItems            = valueWrapper.AsFrameArray();
                    BatchSizeEstimator batchEstimator      = new BatchSizeEstimator(frameOptions.BatchSizeEstimatorConfig);

                    void ProcessBatch(BatchWithBufferWritersAndElementOffset batch, CancellationToken token)
                    {
                        try
                        {
                            ReadOnlySpan <int>    lengths = batch.buffers.lengths.WrittenSpan;
                            ReadOnlyMemory <byte> bodies  = batch.buffers.concatenatedBodies.WrittenMemory;
                            int batchSize = batch.buffers.lengths.WrittenCount;
                            var destSpan  = resItems.AsSpan(batch.offset, batchSize);

                            for (int ix = 0, bodyStartIx = 0; ix < batchSize; ix++)
                            {
                                int itemLen = lengths[ix];
                                ReadOnlyMemory <byte> body      = bodies.Slice(bodyStartIx, itemLen);
                                MessagePackReader     tmpReader = new MessagePackReader(body)
                                {
                                    CancellationToken = token
                                };
                                destSpan[ix].BufferLength = body.Length;
                                destSpan[ix].Item         = formatterT.Deserialize(ref tmpReader, options);
                                bodyStartIx += itemLen;
                            }
                        }
                        finally
                        {
                            objPoolBufferWriterBodies.Return(batch.buffers.concatenatedBodies);
                            objPoolBufferWriterBodyLengths.Return(batch.buffers.lengths);
                        }
                    }

                    using (var mtw = new MultiThreadedWorker <BatchWithBufferWritersAndElementOffset>(
                               frameOptions.MthWorkerConfig, ProcessBatch))
                    {
                        int i = 0;
                        while (i < count)
                        {
                            int batchSize    = Math.Min(count - i, batchEstimator.RecomendedBatchSize);
                            var currentBatch = new BatchWithBufferWritersAndElementOffset()
                            {
                                offset  = i,
                                buffers = new BatchWithBufferWriters()
                                {
                                    concatenatedBodies = objPoolBufferWriterBodies.Get(),
                                    lengths            = objPoolBufferWriterBodyLengths.Get()
                                }
                            };
                            for (int seqIx = 0; seqIx < batchSize; seqIx++)
                            {
                                int itemLength = FrameItemFormatter <T> .ReadElementHeader(ref reader);

                                if (itemLength == Frame <T> .unassigned)
                                {
                                    throw new StreamSerializationException($"Unassigned buffer length found during parallel deserialize for {nameof(TFrameList)}");
                                }
                                currentBatch.buffers.lengths.GetSpan(1)[0] = itemLength;
                                currentBatch.buffers.lengths.Advance(1);
                                ReadOnlySequence <byte> raw = reader.ReadRaw(itemLength);
                                raw.CopyTo(currentBatch.buffers.concatenatedBodies.GetSpan(itemLength));
                                currentBatch.buffers.concatenatedBodies.Advance(itemLength);
                                batchEstimator.UpdateEstimate(itemLength);
                            }
                            mtw.AddWorkItem(currentBatch, reader.CancellationToken);
                            i += batchSize;
                        }
                    }
                    return(valueWrapper.AsFrameList());
                }
                finally
                {
                    reader.Depth--;
                }
            }
            finally
            {
                Interlocked.Decrement(ref ParallelGatekeeperSingleton.wrapperDepth);
            }
        }
        private object[] ReadArguments(ref MessagePackReader reader, string target)
        {
            var subscription = this.Connection.GetSubscription(target);

            object[] args = null;
            if (subscription == null || subscription.callbacks == null || subscription.callbacks.Count == 0)
            {
                reader.Skip();
            }
            else
            {
                int count = reader.ReadArrayHeader();

                if (subscription.callbacks[0].ParamTypes != null)
                {
                    args = new object[subscription.callbacks[0].ParamTypes.Length];
                    for (int i = 0; i < subscription.callbacks[0].ParamTypes.Length; ++i)
                    {
                        args[i] = MessagePackSerializer.Deserialize(subscription.callbacks[0].ParamTypes[i], reader.ReadRaw());
                        //args[i] = MessagePackSerializer.Deserialize(subscription.callbacks[0].ParamTypes[i], ref reader);
                    }
                }
                else
                {
                    args = null;
                }
            }

            return(args);
        }