Esempio n. 1
0
        public (int RequiredBytes, int HeaderLength, int BodyLength) TryRead(ref ReadOnlySequence <byte> input, out Message message)
        {
            if (input.Length < FramingLength)
            {
                message = default;
                return(FramingLength, 0, 0);
            }

            Span <byte> lengthBytes = stackalloc byte[FramingLength];

            input.Slice(input.Start, FramingLength).CopyTo(lengthBytes);
            var headerLength = BinaryPrimitives.ReadInt32LittleEndian(lengthBytes);
            var bodyLength   = BinaryPrimitives.ReadInt32LittleEndian(lengthBytes.Slice(4));

            // Check lengths
            ThrowIfLengthsInvalid(headerLength, bodyLength);

            var requiredBytes = FramingLength + headerLength + bodyLength;

            if (input.Length < requiredBytes)
            {
                message = default;
                return(requiredBytes, 0, 0);
            }

            try
            {
                // decode header
                var header = input.Slice(FramingLength, headerLength);

                // decode body
                int bodyOffset = FramingLength + headerLength;
                var body       = input.Slice(bodyOffset, bodyLength);

                // build message
                if (header.IsSingleSegment)
                {
                    var headersReader = Reader.Create(header.First.Span, _deserializationSession);
                    message = DeserializeFast(ref headersReader);
                }
                else
                {
                    var headersReader = Reader.Create(header, _deserializationSession);
                    message = DeserializeFast(ref headersReader);
                }

                _deserializationSession.PartialReset();

                // Body deserialization is more likely to fail than header deserialization.
                // Separating the two allows for these kinds of errors to be propagated back to the caller.
                if (body.IsSingleSegment)
                {
                    message.BodyObject = _bodySerializer.Deserialize(body.First.Span, _deserializationSession);
                }
                else
                {
                    message.BodyObject = _bodySerializer.Deserialize(body, _deserializationSession);
                }

                return(0, headerLength, bodyLength);
            }
            finally
            {
                input = input.Slice(requiredBytes);
                _deserializationSession.PartialReset();
            }
        }