/// <summary>
        /// Creates a new <see cref="Scope"/> for the specified <paramref name="state"/> with the provided
        /// <paramref name="name"/> and <paramref name="value"/> and pushes it on the stack of scopes.
        /// </summary>
        /// <param name="state">The <see cref="ODataParameterReaderState"/> to use for the new scope.</param>
        /// <param name="name">The paramter name to attach with the state in the new scope.</param>
        /// <param name="value">The paramter value to attach with the state in the new scope.</param>
        protected void EnterScope(ODataParameterReaderState state, string name, object value)
        {
            if (state == ODataParameterReaderState.Value)
            {
                if (value != null && !(value is ODataComplexValue) && !EdmLibraryExtensions.IsPrimitiveType(value.GetType()))
                {
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataParameterReaderCore_ValueMustBePrimitiveOrComplexOrNull));
                }
            }

            Debug.Assert(this.scopes.Count == 0 || this.State != ODataParameterReaderState.Exception || state == ODataParameterReaderState.Exception, "If the reader is already in Exception state, we shouldn't call EnterScope() except for another Exception.");

            // We only need to enter the exception state once.
            if (this.scopes.Count == 0 || this.State != ODataParameterReaderState.Exception)
            {
                Debug.Assert(
                    state == ODataParameterReaderState.Exception ||
                    state == ODataParameterReaderState.Start && this.scopes.Count == 0 ||
                    state == ODataParameterReaderState.Completed && this.scopes.Count == 0 ||
                    this.scopes.Count == 1 && this.scopes.Peek().State == ODataParameterReaderState.Start,
                    "Unexpected state in the scopes stack.");

                // Make sure there aren't any missing parameter in the payload.
                if (state == ODataParameterReaderState.Completed)
                {
                    List <string> missingParameters = new List <string>();

                    // Note that the binding parameter will be specified on the Uri rather than the payload, skip the binding parameter.
                    foreach (IEdmFunctionParameter parameter in this.FunctionImport.Parameters.Skip(this.FunctionImport.IsBindable ? 1 : 0))
                    {
                        if (!this.parametersRead.Contains(parameter.Name) && !parameter.Type.IsNullable)
                        {
                            missingParameters.Add(parameter.Name);
                        }
                    }

                    if (missingParameters.Count > 0)
                    {
                        this.scopes.Push(new Scope(ODataParameterReaderState.Exception, null, null));
                        throw new ODataException(Strings.ODataParameterReaderCore_ParametersMissingInPayload(this.FunctionImport.Name, string.Join(",", missingParameters.ToArray())));
                    }
                }

                this.scopes.Push(new Scope(state, name, value));
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Asynchronously creates an instance of the input context for this format.
        /// </summary>
        /// <param name="readerPayloadKind">The <see cref="ODataPayloadKind"/> to read.</param>
        /// <param name="message">The message to use.</param>
        /// <param name="contentType">The content type of the message to read.</param>
        /// <param name="encoding">The encoding to use.</param>
        /// <param name="messageReaderSettings">Configuration settings of the OData reader.</param>
        /// <param name="version">The OData protocol version to be used for reading the payload.</param>
        /// <param name="readingResponse">true if reading a response message; otherwise false.</param>
        /// <param name="model">The model to use.</param>
        /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs read from the payload.</param>
        /// <param name="payloadKindDetectionFormatState">Format specific state stored during payload kind detection
        /// using the <see cref="ODataPayloadKindDetectionInfo.SetPayloadKindDetectionFormatState"/>.</param>
        /// <returns>Task which when completed returned the newly created input context.</returns>
        internal override Task <ODataInputContext> CreateInputContextAsync(
            ODataPayloadKind readerPayloadKind,
            ODataMessage message,
            MediaType contentType,
            Encoding encoding,
            ODataMessageReaderSettings messageReaderSettings,
            ODataVersion version,
            bool readingResponse,
            IEdmModel model,
            IODataUrlResolver urlResolver,
            object payloadKindDetectionFormatState)
        {
            DebugUtils.CheckNoExternalCallers();
            ExceptionUtils.CheckArgumentNotNull(message, "message");
            ExceptionUtils.CheckArgumentNotNull(messageReaderSettings, "messageReaderSettings");

            throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataMetadataFormat_CreateInputContextAsync));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Converts a given <see cref="AtomTextConstructKind"/> to a string appropriate for Atom format.
        /// </summary>
        /// <param name="textConstructKind">The text construct kind to convert.</param>
        /// <returns>The string version of the text construct format in Atom format.</returns>
        internal static string ToString(AtomTextConstructKind textConstructKind)
        {
            DebugUtils.CheckNoExternalCallers();

            switch (textConstructKind)
            {
            case AtomTextConstructKind.Text:
                return(AtomConstants.AtomTextConstructTextKind);

            case AtomTextConstructKind.Html:
                return(AtomConstants.AtomTextConstructHtmlKind);

            case AtomTextConstructKind.Xhtml:
                return(AtomConstants.AtomTextConstructXHtmlKind);

            default:
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataAtomConvert_ToString));
            }
        }
Ejemplo n.º 4
0
        internal bool SkipToBoundary(out bool isEndBoundary, out bool isParentBoundary)
        {
            this.EnsureBatchEncoding();
            ODataBatchReaderStreamScanResult noMatch = ODataBatchReaderStreamScanResult.NoMatch;

            while (noMatch != ODataBatchReaderStreamScanResult.Match)
            {
                int num;
                int num2;
                switch (this.batchBuffer.ScanForBoundary(this.CurrentBoundaries, 0x7fffffff, out num, out num2, out isEndBoundary, out isParentBoundary))
                {
                case ODataBatchReaderStreamScanResult.NoMatch:
                    if (!this.underlyingStreamExhausted)
                    {
                        break;
                    }
                    this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + this.batchBuffer.NumberOfBytesInBuffer);
                    return(false);

                case ODataBatchReaderStreamScanResult.PartialMatch:
                    if (!this.underlyingStreamExhausted)
                    {
                        goto Label_00BE;
                    }
                    this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + this.batchBuffer.NumberOfBytesInBuffer);
                    return(false);

                case ODataBatchReaderStreamScanResult.Match:
                    this.batchBuffer.SkipTo(isParentBoundary ? num : (num2 + 1));
                    return(true);

                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_SkipToBoundary));
                }
                this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, 0x1f40);
                continue;
Label_00BE:
                this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, num);
            }
            throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_SkipToBoundary));
        }
Ejemplo n.º 5
0
        private bool ReadImplementation()
        {
            switch (this.State)
            {
            case ODataBatchReaderState.Initial:
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.Operation:
                if (this.operationState == OperationState.None)
                {
                    throw new ODataException(Strings.ODataBatchReader_NoMessageWasCreatedForOperation);
                }
                this.operationState = OperationState.None;
                if (this.contentIdToAddOnNextRead != null)
                {
                    this.urlResolver.AddContentId(this.contentIdToAddOnNextRead);
                    this.contentIdToAddOnNextRead = null;
                }
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.ChangesetStart:
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.ChangesetEnd:
                this.ResetChangeSetSize();
                this.batchStream.ResetChangeSetBoundary();
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.Completed:
            case ODataBatchReaderState.Exception:
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation));

            default:
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation));
            }
            return((this.batchReaderState != ODataBatchReaderState.Completed) && (this.batchReaderState != ODataBatchReaderState.Exception));
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Converts a given <paramref name="version"/> to its <see cref="System.Version"/> representation.
        /// </summary>
        /// <param name="version">The <see cref="ODataVersion"/> instance to convert.</param>
        /// <returns>The <see cref="System.Version"/> representation of the <paramref name="version"/>.</returns>
        internal static Version ToDataServiceVersion(this ODataVersion version)
        {
            DebugUtils.CheckNoExternalCallers();

            switch (version)
            {
            case ODataVersion.V1:
                return(new Version(1, 0));

            case ODataVersion.V2:
                return(new Version(2, 0));

            case ODataVersion.V3:
                return(new Version(3, 0));

            default:
                string errorMessage = Strings.General_InternalError(InternalErrorCodes.ODataUtilsInternal_ToDataServiceVersion_UnreachableCodePath);
                Debug.Assert(false, errorMessage);
                throw new ODataException(errorMessage);
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Returns the next state of the batch reader after an end boundary has been found.
        /// </summary>
        /// <returns>The next state of the batch reader.</returns>
        private ODataBatchReaderState GetEndBoundaryState()
        {
            switch (this.batchReaderState)
            {
            case ODataBatchReaderState.Initial:
                // If we find an end boundary when in state 'Initial' it means that we
                // have an empty batch. The next state will be 'Completed'.
                return(ODataBatchReaderState.Completed);

            case ODataBatchReaderState.Operation:
                // If we find an end boundary in state 'Operation' we have finished
                // processing an operation and found the end boundary of either the
                // current changeset or the batch.
                return(this.batchStream.ChangeSetBoundary == null
                        ? ODataBatchReaderState.Completed
                        : ODataBatchReaderState.ChangesetEnd);

            case ODataBatchReaderState.ChangesetStart:
                // If we find an end boundary when in state 'ChangeSetStart' it means that
                // we have an empty changeset. The next state will be 'ChangeSetEnd'
                return(ODataBatchReaderState.ChangesetEnd);

            case ODataBatchReaderState.ChangesetEnd:
                // If we are at the end of a changeset and find an end boundary
                // we reached the end of the batch
                return(ODataBatchReaderState.Completed);

            case ODataBatchReaderState.Completed:
                // We should never get here when in Completed state.
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_GetEndBoundary_Completed));

            case ODataBatchReaderState.Exception:
                // We should never get here when in Exception state.
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_GetEndBoundary_Exception));

            default:
                // Invalid enum value
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_GetEndBoundary_UnknownValue));
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Indexer to get the cached item when given the ODataVersion.
        /// </summary>
        /// <param name="version">The ODataVersion to look up.</param>
        /// <returns>The cached item.</returns>
        internal T this[ODataVersion version]
        {
            get
            {
                DebugUtils.CheckNoExternalCallers();

                switch (version)
                {
                case ODataVersion.V1:
                    return(this.v1.Value);

                case ODataVersion.V2:
                    return(this.v2.Value);

                case ODataVersion.V3:
                    return(this.v3.Value);

                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataVersionCache_UnknownVersion));
                }
            }
        }
        /// <summary>
        /// Scans the current buffer for the specified boundary.
        /// </summary>
        /// <param name="boundaries">The boundary strings to search for; this enumerable is sorted from the inner-most boundary
        /// to the top-most boundary. The boundary strings don't include the leading line terminator or the leading dashes.</param>
        /// <param name="maxDataBytesToScan">Stop if no boundary (or boundary start) is found after this number of bytes.</param>
        /// <param name="boundaryStartPosition">The start position of the boundary or -1 if not found.
        /// Note that the start position is the first byte of the leading line terminator.</param>
        /// <param name="boundaryEndPosition">The end position of the boundary or -1 if not found.
        /// Note that the end position is the last byte of the trailing line terminator.</param>
        /// <param name="isEndBoundary">true if the boundary is an end boundary (followed by two dashes); otherwise false.</param>
        /// <param name="isParentBoundary">true if the detected boundary is the parent boundary; otherwise false.</param>
        /// <returns>An enumeration value indicating whether the boundary was completely, partially or not found in the buffer.</returns>
        internal ODataBatchReaderStreamScanResult ScanForBoundary(
            IEnumerable <string> boundaries,
            int maxDataBytesToScan,
            out int boundaryStartPosition,
            out int boundaryEndPosition,
            out bool isEndBoundary,
            out bool isParentBoundary)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(boundaries != null, "boundaries != null");

            boundaryStartPosition = -1;
            boundaryEndPosition   = -1;
            isEndBoundary         = false;
            isParentBoundary      = false;

            int lineScanStartIndex = this.currentReadPosition;

            while (true)
            {
                // NOTE: a boundary has to start with a line terminator followed by two dashes ('-'),
                //       the actual boundary string, another two dashes (for an end boundary),
                //       optional whitespace characters and another line terminator.
                // NOTE: for WCF DS compatibility we do not require the leading line terminator.
                int lineEndStartPosition, boundaryDelimiterStartPosition;
                ODataBatchReaderStreamScanResult lineEndScanResult = this.ScanForBoundaryStart(
                    lineScanStartIndex,
                    maxDataBytesToScan,
                    out lineEndStartPosition,
                    out boundaryDelimiterStartPosition);

                switch (lineEndScanResult)
                {
                case ODataBatchReaderStreamScanResult.NoMatch:
                    // Did not find a line end or boundary delimiter in the buffer or after reading maxDataBytesToScan bytes.
                    // Report no boundary match.
                    return(ODataBatchReaderStreamScanResult.NoMatch);

                case ODataBatchReaderStreamScanResult.PartialMatch:
                    // Found a partial line end or boundary delimiter at the end of the buffer but before reading maxDataBytesToScan.
                    // Report a partial boundary match.
                    boundaryStartPosition = lineEndStartPosition < 0 ? boundaryDelimiterStartPosition : lineEndStartPosition;
                    return(ODataBatchReaderStreamScanResult.PartialMatch);

                case ODataBatchReaderStreamScanResult.Match:
                    // Found a full line end or boundary delimiter start ('--') before reading maxDataBytesToScan or
                    // hitting the end of the buffer. Start matching the boundary delimiters.
                    //
                    // Start with the expected boundary (the first one in the enumerable):
                    // * if we find a full match - return match because we are done
                    // * if we find a partial match - return partial match because we have to continue checking the expected boundary.
                    // * if we find no match - we know that it is not the expected boundary; check the parent boundary (if it exists).
                    isParentBoundary = false;
                    foreach (string boundary in boundaries)
                    {
                        ODataBatchReaderStreamScanResult boundaryMatch = this.MatchBoundary(
                            lineEndStartPosition,
                            boundaryDelimiterStartPosition,
                            boundary,
                            out boundaryStartPosition,
                            out boundaryEndPosition,
                            out isEndBoundary);
                        switch (boundaryMatch)
                        {
                        case ODataBatchReaderStreamScanResult.Match:
                            return(ODataBatchReaderStreamScanResult.Match);

                        case ODataBatchReaderStreamScanResult.PartialMatch:
                            boundaryEndPosition = -1;
                            isEndBoundary       = false;
                            return(ODataBatchReaderStreamScanResult.PartialMatch);

                        case ODataBatchReaderStreamScanResult.NoMatch:
                            // try the parent boundary (if any) or continue scanning
                            boundaryStartPosition = -1;
                            boundaryEndPosition   = -1;
                            isEndBoundary         = false;
                            isParentBoundary      = true;
                            break;

                        default:
                            throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStreamBuffer_ScanForBoundary));
                        }
                    }

                    // If we could not match the boundary, try again starting at the current boundary start index. Or if we already did that
                    // move one character ahead.
                    lineScanStartIndex = lineScanStartIndex == boundaryDelimiterStartPosition
                            ? boundaryDelimiterStartPosition + 1
                            : boundaryDelimiterStartPosition;

                    break;

                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStreamBuffer_ScanForBoundary));
                }
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Creates an instance of the input context for the specified format.
        /// </summary>
        /// <param name="format">The format to create the context for.</param>
        /// <param name="readerPayloadKind">The <see cref="ODataPayloadKind"/> to read.</param>
        /// <param name="message">The message to use.</param>
        /// <param name="encoding">The encoding to use.</param>
        /// <param name="messageReaderSettings">Configuration settings of the OData reader.</param>
        /// <param name="version">The OData protocol version to be used for reading the payload.</param>
        /// <param name="readingResponse">true if reading a response message; otherwise false.</param>
        /// <param name="model">The model to use.</param>
        /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs read from the payload.</param>
        /// <returns>The newly created input context.</returns>
        internal static ODataInputContext CreateInputContext(
            ODataFormat format,
            ODataPayloadKind readerPayloadKind,
            ODataMessage message,
            Encoding encoding,
            ODataMessageReaderSettings messageReaderSettings,
            ODataVersion version,
            bool readingResponse,
            IEdmModel model,
            IODataUrlResolver urlResolver)
        {
            DebugUtils.CheckNoExternalCallers();

            if (format == ODataFormat.Atom)
            {
                return(ODataAtomInputContext.Create(
                           format,
                           message,
                           encoding,
                           messageReaderSettings,
                           version,
                           readingResponse,
                           model,
                           urlResolver));
            }

            if (format == ODataFormat.VerboseJson)
            {
                return(ODataJsonInputContext.Create(
                           format,
                           message,
                           encoding,
                           messageReaderSettings,
                           version,
                           readingResponse,
                           model,
                           urlResolver));
            }

            if (format == ODataFormat.Metadata)
            {
                return(ODataMetadataInputContext.Create(
                           format,
                           message,
                           encoding,
                           messageReaderSettings,
                           version,
                           readingResponse,
                           model,
                           urlResolver));
            }

            if (format == ODataFormat.Batch || format == ODataFormat.RawValue)
            {
                return(ODataRawInputContext.Create(
                           format,
                           message,
                           encoding,
                           messageReaderSettings,
                           version,
                           readingResponse,
                           model,
                           urlResolver,
                           readerPayloadKind));
            }

            throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataInputContext_CreateInputContext_UnrecognizedFormat));
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Continues reading from the batch message payload.
        /// </summary>
        /// <returns>true if more items were read; otherwise false.</returns>
        private bool ReadImplementation()
        {
            Debug.Assert(this.operationState != OperationState.StreamRequested, "Should have verified that no operation stream is still active.");

            switch (this.State)
            {
            case ODataBatchReaderState.Initial:
                // The stream should be positioned at the beginning of the batch content,
                // that is before the first boundary (or the preamble if there is one).
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.Operation:
                // When reaching this state we already read the MIME headers of the operation.
                // Clients MUST call CreateOperationRequestMessage
                // or CreateOperationResponseMessage to read at least the headers of the operation.
                // This is important since we need to read the ContentId header (if present) and
                // add it to the URL resolver.
                if (this.operationState == OperationState.None)
                {
                    // No message was created; fail
                    throw new ODataException(Strings.ODataBatchReader_NoMessageWasCreatedForOperation);
                }

                // Reset the operation state; the operation state only
                // tracks the state of a batch operation while in state Operation.
                this.operationState = OperationState.None;

                // Also add a pending ContentId header to the URL resolver now. We ensured above
                // that a message has been created for this operation and thus the headers (incl.
                // a potential content ID header) have been read.
                if (this.contentIdToAddOnNextRead != null)
                {
                    this.urlResolver.AddContentId(this.contentIdToAddOnNextRead);
                    this.contentIdToAddOnNextRead = null;
                }

                // When we are done with an operation, we have to skip ahead to the next part
                // when Read is called again. Note that if the operation stream was never requested
                // and the content of the operation has not been read, we'll skip it here.
                Debug.Assert(this.operationState == OperationState.None, "Operation state must be 'None' at the end of the operation.");
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.ChangesetStart:
                // When at the start of a changeset, skip ahead to the first operation in the
                // changeset (or the end boundary of the changeset).
                Debug.Assert(this.batchStream.ChangeSetBoundary != null, "Changeset boundary must have been set by now.");
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.ChangesetEnd:
                // When at the end of a changeset, reset the changeset boundary and the
                // changeset size and then skip to the next part.
                this.ResetChangeSetSize();
                this.batchStream.ResetChangeSetBoundary();
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.Exception:        // fall through
            case ODataBatchReaderState.Completed:
                Debug.Assert(false, "Should have checked in VerifyCanRead that we are not in one of these states.");
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation));

            default:
                Debug.Assert(false, "Unsupported reader state " + this.State + " detected.");
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation));
            }

            return(this.batchReaderState != ODataBatchReaderState.Completed && this.batchReaderState != ODataBatchReaderState.Exception);
        }
Ejemplo n.º 12
0
        private ODataBatchReaderStreamScanResult MatchBoundary(int lineEndStartPosition, int boundaryDelimiterStartPosition, string boundary, out int boundaryStartPosition, out int boundaryEndPosition, out bool isEndBoundary)
        {
            bool flag;
            int  num3;

            boundaryStartPosition = -1;
            boundaryEndPosition   = -1;
            int num  = (this.currentReadPosition + this.numberOfBytesInBuffer) - 1;
            int num2 = (((boundaryDelimiterStartPosition + 2) + boundary.Length) + 2) - 1;

            if (num < (num2 + 2))
            {
                flag = true;
                num3 = (Math.Min(num, num2) - boundaryDelimiterStartPosition) + 1;
            }
            else
            {
                flag = false;
                num3 = (num2 - boundaryDelimiterStartPosition) + 1;
            }
            if (this.MatchBoundary(boundary, boundaryDelimiterStartPosition, num3, out isEndBoundary))
            {
                int  num4;
                int  num5;
                bool flag2;
                boundaryStartPosition = (lineEndStartPosition < 0) ? boundaryDelimiterStartPosition : lineEndStartPosition;
                if (flag)
                {
                    isEndBoundary = false;
                    return(ODataBatchReaderStreamScanResult.PartialMatch);
                }
                boundaryEndPosition = ((boundaryDelimiterStartPosition + 2) + boundary.Length) - 1;
                if (isEndBoundary)
                {
                    boundaryEndPosition += 2;
                }
                switch (this.ScanForLineEnd(boundaryEndPosition + 1, 0x7fffffff, true, out num4, out num5, out flag2))
                {
                case ODataBatchReaderStreamScanResult.NoMatch:
                    if (flag2)
                    {
                        if (boundaryStartPosition == 0)
                        {
                            throw new ODataException(Strings.ODataBatchReaderStreamBuffer_BoundaryLineSecurityLimitReached(0x1f40));
                        }
                        isEndBoundary = false;
                        return(ODataBatchReaderStreamScanResult.PartialMatch);
                    }
                    break;

                case ODataBatchReaderStreamScanResult.PartialMatch:
                    if (boundaryStartPosition == 0)
                    {
                        throw new ODataException(Strings.ODataBatchReaderStreamBuffer_BoundaryLineSecurityLimitReached(0x1f40));
                    }
                    isEndBoundary = false;
                    return(ODataBatchReaderStreamScanResult.PartialMatch);

                case ODataBatchReaderStreamScanResult.Match:
                    boundaryEndPosition = num5;
                    return(ODataBatchReaderStreamScanResult.Match);

                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStreamBuffer_ScanForBoundary));
                }
            }
            return(ODataBatchReaderStreamScanResult.NoMatch);
        }
Ejemplo n.º 13
0
        internal int ReadWithDelimiter(byte[] userBuffer, int userBufferOffset, int count)
        {
            if (count == 0)
            {
                return(0);
            }
            int maxDataBytesToScan = count;
            ODataBatchReaderStreamScanResult noMatch = ODataBatchReaderStreamScanResult.NoMatch;

            while ((maxDataBytesToScan > 0) && (noMatch != ODataBatchReaderStreamScanResult.Match))
            {
                int  num2;
                int  num3;
                bool flag;
                bool flag2;
                int  num4;
                switch (this.batchBuffer.ScanForBoundary(this.CurrentBoundaries, maxDataBytesToScan, out num2, out num3, out flag, out flag2))
                {
                case ODataBatchReaderStreamScanResult.NoMatch:
                    if (this.batchBuffer.NumberOfBytesInBuffer < maxDataBytesToScan)
                    {
                        break;
                    }
                    Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, maxDataBytesToScan);
                    this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + maxDataBytesToScan);
                    return(count);

                case ODataBatchReaderStreamScanResult.PartialMatch:
                {
                    if (!this.underlyingStreamExhausted)
                    {
                        goto Label_0168;
                    }
                    int num6 = Math.Min(this.batchBuffer.NumberOfBytesInBuffer, maxDataBytesToScan);
                    Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, num6);
                    this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + num6);
                    maxDataBytesToScan -= num6;
                    return(count - maxDataBytesToScan);
                }

                case ODataBatchReaderStreamScanResult.Match:
                    num4 = num2 - this.batchBuffer.CurrentReadPosition;
                    Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, num4);
                    maxDataBytesToScan -= num4;
                    userBufferOffset   += num4;
                    this.batchBuffer.SkipTo(num2);
                    return(count - maxDataBytesToScan);

                default:
                {
                    continue;
                }
                }
                int numberOfBytesInBuffer = this.batchBuffer.NumberOfBytesInBuffer;
                Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, numberOfBytesInBuffer);
                maxDataBytesToScan -= numberOfBytesInBuffer;
                userBufferOffset   += numberOfBytesInBuffer;
                if (this.underlyingStreamExhausted)
                {
                    this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + numberOfBytesInBuffer);
                    return(count - maxDataBytesToScan);
                }
                this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, 0x1f40);
                continue;
Label_0168:
                num4 = num2 - this.batchBuffer.CurrentReadPosition;
                Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, num4);
                maxDataBytesToScan            -= num4;
                userBufferOffset              += num4;
                this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, num2);
            }
            throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_ReadWithDelimiter));
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Creates an instance of the output context for the specified format.
        /// </summary>
        /// <param name="format">The format to create the context for.</param>
        /// <param name="message">The message to use.</param>
        /// <param name="encoding">The encoding to use.</param>
        /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param>
        /// <param name="writingResponse">true if writing a response message; otherwise false.</param>
        /// <param name="model">The model to use.</param>
        /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs written to the payload.</param>
        /// <returns>The newly created output context.</returns>
        internal static ODataOutputContext CreateOutputContext(
            ODataFormat format,
            ODataMessage message,
            Encoding encoding,
            ODataMessageWriterSettings messageWriterSettings,
            bool writingResponse,
            IEdmModel model,
            IODataUrlResolver urlResolver)
        {
            DebugUtils.CheckNoExternalCallers();

            if (format == ODataFormat.Atom)
            {
                return(ODataAtomOutputContext.Create(
                           format,
                           message,
                           encoding,
                           messageWriterSettings,
                           writingResponse,
                           model,
                           urlResolver));
            }

            if (format == ODataFormat.VerboseJson)
            {
                return(ODataJsonOutputContext.Create(
                           format,
                           message,
                           encoding,
                           messageWriterSettings,
                           writingResponse,
                           model,
                           urlResolver));
            }

            if (format == ODataFormat.Metadata)
            {
                return(ODataMetadataOutputContext.Create(
                           format,
                           message,
                           encoding,
                           messageWriterSettings,
                           writingResponse,
                           model,
                           urlResolver));
            }

            if (format == ODataFormat.Batch || format == ODataFormat.RawValue)
            {
                return(ODataRawOutputContext.Create(
                           format,
                           message,
                           encoding,
                           messageWriterSettings,
                           writingResponse,
                           model,
                           urlResolver));
            }

            throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataOutputContext_CreateOutputContext_UnrecognizedFormat));
        }
        /// <summary>
        /// Reads the next <see cref="ODataItem"/> from the message payload.
        /// </summary>
        /// <returns>true if more items were read; otherwise false.</returns>
        protected bool ReadImplementation()
        {
            bool result = false;

            switch (this.State)
            {
            case ODataParameterReaderState.Start:
                result = this.ReadAtStartImplementation();
                Debug.Assert(
                    this.State == ODataParameterReaderState.Value ||
#if SUPPORT_ENTITY_PARAMETER
                    this.State == ODataParameterReaderState.Entry ||
                    this.State == ODataParameterReaderState.Feed ||
#endif
                    this.State == ODataParameterReaderState.Collection ||
                    this.State == ODataParameterReaderState.Completed,
                    "ReadAtParameterStartImplementation should transition the state to ODataParameterReaderState.Value, ODataParameterReaderState.Entry, ODataParameterReaderState.Feed, ODataParameterReaderState.Collection or ODataParameterReaderState.Completed. The current state is: " + this.State);
                break;

            case ODataParameterReaderState.Value:
#if SUPPORT_ENTITY_PARAMETER
            case ODataParameterReaderState.Entry:
            case ODataParameterReaderState.Feed:
#endif
            case ODataParameterReaderState.Collection:
                Debug.Assert(this.State == ODataParameterReaderState.Value || this.subReaderState == SubReaderState.Completed, "this.State == ODataParameterReaderState.Value || this.subReaderState == SubReaderState.Completed");
                this.subReaderState = SubReaderState.None;
                result = this.ReadNextParameterImplementation();
                Debug.Assert(
                    this.State == ODataParameterReaderState.Value ||
#if SUPPORT_ENTITY_PARAMETER
                    this.State == ODataParameterReaderState.Entry ||
                    this.State == ODataParameterReaderState.Feed ||
#endif
                    this.State == ODataParameterReaderState.Collection ||
                    this.State == ODataParameterReaderState.Completed,
                    "ReadAtParameterStartImplementation should transition the state to ODataParameterReaderState.Value, ODataParameterReaderState.Entry, ODataParameterReaderState.Feed, ODataParameterReaderState.Collection or ODataParameterReaderState.Completed. The current state is: " + this.State);
                break;

            case ODataParameterReaderState.Exception:        // fall through
            case ODataParameterReaderState.Completed:
                Debug.Assert(false, "This case should have been caught earlier.");
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataParameterReader_ReadImplementation));

            default:
                Debug.Assert(false, "Unsupported parameter reader state " + this.State + " detected.");
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataParameterReader_ReadImplementation));
            }

            if (this.State != ODataParameterReaderState.Completed)
            {
                Debug.Assert(!string.IsNullOrEmpty(this.Name), "!string.IsNullOrEmpty(this.Name)");
                if (this.parametersRead.Contains(this.Name))
                {
                    throw new ODataException(Strings.ODataParameterReaderCore_DuplicateParametersInPayload(this.Name));
                }

                this.parametersRead.Add(this.Name);
            }

            return(result);
        }
        /// <summary>
        /// Check whether the bytes in the buffer at the specified start index match the expected boundary string.
        /// </summary>
        /// <param name="lineEndStartPosition">The start of the line feed preceding the boundary (if present).</param>
        /// <param name="boundaryDelimiterStartPosition">The start position of the boundary delimiter.</param>
        /// <param name="boundary">The boundary string to check for.</param>
        /// <param name="boundaryStartPosition">If a match is detected, the start of the boundary delimiter,
        /// i.e., either the start of the leading line feed or of the leading dashes.</param>
        /// <param name="boundaryEndPosition">If a match is detected, the position of the boundary end; otherwise -1.</param>
        /// <param name="isEndBoundary">true if the detected boundary is an end boundary; otherwise false.</param>
        /// <returns>An <see cref="ODataBatchReaderStreamScanResult"/> indicating whether a match, a partial match or no match was found.</returns>
        private ODataBatchReaderStreamScanResult MatchBoundary(
            int lineEndStartPosition,
            int boundaryDelimiterStartPosition,
            string boundary,
            out int boundaryStartPosition,
            out int boundaryEndPosition,
            out bool isEndBoundary)
        {
            boundaryStartPosition = -1;
            boundaryEndPosition   = -1;

            int bufferLastByte = this.currentReadPosition + this.numberOfBytesInBuffer - 1;
            int boundaryEndPositionAfterLineFeed =
                boundaryDelimiterStartPosition + TwoDashesLength + boundary.Length + TwoDashesLength - 1;

            // NOTE: for simplicity reasons we require that the full end (!) boundary plus the maximum size
            //       of the line terminator fits into the buffer to get a non-partial match.
            //       By doing so we can reliably detect whether we are dealing with an end boundary or not.
            //       Otherwise the logic to figure out whether we found a boundary or not is riddled with
            //       corner cases that only complicate the code.
            bool isPartialMatch;
            int  matchLength;

            if (bufferLastByte < boundaryEndPositionAfterLineFeed + MaxLineFeedLength)
            {
                isPartialMatch = true;
                matchLength    = Math.Min(bufferLastByte, boundaryEndPositionAfterLineFeed) - boundaryDelimiterStartPosition + 1;
            }
            else
            {
                isPartialMatch = false;
                matchLength    = boundaryEndPositionAfterLineFeed - boundaryDelimiterStartPosition + 1;
            }

            if (this.MatchBoundary(boundary, boundaryDelimiterStartPosition, matchLength, out isEndBoundary))
            {
                boundaryStartPosition = lineEndStartPosition < 0 ? boundaryDelimiterStartPosition : lineEndStartPosition;

                if (isPartialMatch)
                {
                    isEndBoundary = false;
                    return(ODataBatchReaderStreamScanResult.PartialMatch);
                }
                else
                {
                    // If we fully matched the boundary compute the boundary end position
                    boundaryEndPosition = boundaryDelimiterStartPosition + TwoDashesLength + boundary.Length - 1;
                    if (isEndBoundary)
                    {
                        boundaryEndPosition += TwoDashesLength;
                    }

                    // Once we could match all the characters and delimiters of the boundary string
                    // (and the optional trailing '--') we now have to continue reading until the next
                    // line feed that terminates the boundary. Only whitespace characters may exist
                    // after the boundary and before the line feed.
                    int  terminatingLineFeedStartPosition, terminatingLineFeedEndPosition;
                    bool endOfBufferReached;
                    ODataBatchReaderStreamScanResult terminatingLineFeedScanResult =
                        this.ScanForLineEnd(
                            boundaryEndPosition + 1,
                            int.MaxValue,
                            /*allowLeadingWhitespaceOnly*/ true,
                            out terminatingLineFeedStartPosition,
                            out terminatingLineFeedEndPosition,
                            out endOfBufferReached);

                    switch (terminatingLineFeedScanResult)
                    {
                    case ODataBatchReaderStreamScanResult.NoMatch:
                        if (endOfBufferReached)
                        {
                            // Reached the end of the buffer and only found whitespaces.
                            if (boundaryStartPosition == 0)
                            {
                                // If the boundary starts at the first position in the buffer
                                // and we still could not find the end of it because there are
                                // so many whitespaces before the terminating line feed - fail
                                // (security limit on the whitespaces)
                                throw new ODataException(Strings.ODataBatchReaderStreamBuffer_BoundaryLineSecurityLimitReached(BufferLength));
                            }

                            // Report a partial match.
                            isEndBoundary = false;
                            return(ODataBatchReaderStreamScanResult.PartialMatch);
                        }
                        else
                        {
                            // Found a different character than whitespace or end-of-line
                            // so we did not match the boundary.
                            break;
                        }

                    case ODataBatchReaderStreamScanResult.PartialMatch:
                        // Found only a partial line end at the end of the buffer.
                        if (boundaryStartPosition == 0)
                        {
                            // If the boundary starts at the first position in the buffer
                            // and we still could not find the end of it because there are
                            // so many whitespaces before the terminating line feed - fail
                            // (security limit on the whitespaces)
                            throw new ODataException(Strings.ODataBatchReaderStreamBuffer_BoundaryLineSecurityLimitReached(BufferLength));
                        }

                        // Report a partial match.
                        isEndBoundary = false;
                        return(ODataBatchReaderStreamScanResult.PartialMatch);

                    case ODataBatchReaderStreamScanResult.Match:
                        // At this point we only found whitespace characters and then the terminating line feed;
                        // adjust the boundary end position
                        boundaryEndPosition = terminatingLineFeedEndPosition;
                        return(ODataBatchReaderStreamScanResult.Match);

                    default:
                        throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStreamBuffer_ScanForBoundary));
                    }
                }
            }

            return(ODataBatchReaderStreamScanResult.NoMatch);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Reads a line (all bytes until a line feed) from the underlying stream.
        /// </summary>
        /// <returns>Returns the string that was read from the underyling stream (not including a terminating line feed).</returns>
        internal string ReadLine()
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(this.batchEncoding != null, "Batch encoding should have been established on first call to SkipToBoundary.");
            Debug.Assert(this.lineBuffer != null && this.lineBuffer.Length == LineBufferLength, "Line buffer should have been created.");

            // The number of bytes in the line buffer that make up the line.
            int lineBufferSize = 0;

            // Start with the pre-allocated line buffer array.
            byte[] bytesForString = this.lineBuffer;

            ODataBatchReaderStreamScanResult scanResult = ODataBatchReaderStreamScanResult.NoMatch;

            while (scanResult != ODataBatchReaderStreamScanResult.Match)
            {
                int byteCount, lineEndStartPosition, lineEndEndPosition;
                scanResult = this.batchBuffer.ScanForLineEnd(out lineEndStartPosition, out lineEndEndPosition);
                switch (scanResult)
                {
                case ODataBatchReaderStreamScanResult.NoMatch:
                    // Copy all the bytes in the batchBuffer into the result byte[] and then continue
                    byteCount = this.batchBuffer.NumberOfBytesInBuffer;
                    if (byteCount > 0)
                    {
                        ODataBatchUtils.EnsureArraySize(ref bytesForString, lineBufferSize, byteCount);
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, bytesForString, lineBufferSize, byteCount);
                        lineBufferSize += byteCount;
                    }

                    if (this.underlyingStreamExhausted)
                    {
                        // Nothing more to read; stop looping
                        scanResult = ODataBatchReaderStreamScanResult.Match;
                        this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + byteCount);
                    }
                    else
                    {
                        this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ ODataBatchReaderStreamBuffer.BufferLength);
                    }

                    break;

                case ODataBatchReaderStreamScanResult.PartialMatch:
                    // We found the start of a line end in the buffer but could not verify whether we saw all of it.
                    // This can happen if a line end is represented as \r\n and we found \r at the very last position in the buffer.
                    // In this case we copy the bytes into the result byte[] and continue at the start of the line end; this will guarantee
                    // that the next scan will find the full line end, not find any additional bytes and then skip the full line end.
                    // It is safe to copy the string right here because we will also accept \r as a line end; we are just not sure whether there
                    // will be a subsequent \n.
                    // This can also happen if the last byte in the stream is \r.
                    byteCount = lineEndStartPosition - this.batchBuffer.CurrentReadPosition;
                    if (byteCount > 0)
                    {
                        ODataBatchUtils.EnsureArraySize(ref bytesForString, lineBufferSize, byteCount);
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, bytesForString, lineBufferSize, byteCount);
                        lineBufferSize += byteCount;
                    }

                    if (this.underlyingStreamExhausted)
                    {
                        // Nothing more to read; stop looping
                        scanResult = ODataBatchReaderStreamScanResult.Match;
                        this.batchBuffer.SkipTo(lineEndStartPosition + 1);
                    }
                    else
                    {
                        this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ lineEndStartPosition);
                    }

                    break;

                case ODataBatchReaderStreamScanResult.Match:
                    // We found a line end in the buffer
                    Debug.Assert(lineEndStartPosition >= this.batchBuffer.CurrentReadPosition, "Line end must be at or after current position.");
                    Debug.Assert(lineEndEndPosition < this.batchBuffer.CurrentReadPosition + this.batchBuffer.NumberOfBytesInBuffer, "Line end must finish withing buffer range.");

                    byteCount = lineEndStartPosition - this.batchBuffer.CurrentReadPosition;
                    if (byteCount > 0)
                    {
                        ODataBatchUtils.EnsureArraySize(ref bytesForString, lineBufferSize, byteCount);
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, bytesForString, lineBufferSize, byteCount);
                        lineBufferSize += byteCount;
                    }

                    this.batchBuffer.SkipTo(lineEndEndPosition + 1);
                    break;

                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_ReadLine));
                }
            }

            if (bytesForString == null)
            {
                return(string.Empty);
            }

            return(this.CurrentEncoding.GetString(bytesForString, 0, lineBufferSize));
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Reads from the batch stream while ensuring that we stop reading at each boundary.
        /// </summary>
        /// <param name="userBuffer">The byte array to read bytes into.</param>
        /// <param name="userBufferOffset">The offset in the buffer where to start reading bytes into.</param>
        /// <param name="count">The number of bytes to read.</param>
        /// <returns>The number of bytes actually read.</returns>
        internal int ReadWithDelimiter(byte[] userBuffer, int userBufferOffset, int count)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(userBuffer != null, "userBuffer != null");
            Debug.Assert(userBufferOffset >= 0 && userBufferOffset < userBuffer.Length, "Offset must be within the range of the user buffer.");
            Debug.Assert(count >= 0, "count >= 0");
            Debug.Assert(this.batchEncoding != null, "Batch encoding should have been established on first call to SkipToBoundary.");

            if (count == 0)
            {
                // Nothing to read.
                return(0);
            }

            int remainingNumberOfBytesToRead            = count;
            ODataBatchReaderStreamScanResult scanResult = ODataBatchReaderStreamScanResult.NoMatch;

            while (remainingNumberOfBytesToRead > 0 && scanResult != ODataBatchReaderStreamScanResult.Match)
            {
                int  boundaryStartPosition, boundaryEndPosition;
                bool isEndBoundary, isParentBoundary;
                scanResult = this.batchBuffer.ScanForBoundary(
                    this.CurrentBoundaries,
                    remainingNumberOfBytesToRead,
                    out boundaryStartPosition,
                    out boundaryEndPosition,
                    out isEndBoundary,
                    out isParentBoundary);

                int bytesBeforeBoundaryStart;
                switch (scanResult)
                {
                case ODataBatchReaderStreamScanResult.NoMatch:
                    // The boundary was not found in the buffer or after the required number of bytes to be read;
                    // Check whether we can satisfy the full read request from the buffer
                    // or whether we have to split the request and read more data into the buffer.
                    if (this.batchBuffer.NumberOfBytesInBuffer >= remainingNumberOfBytesToRead)
                    {
                        // we can satisfy the full read request from the buffer
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, remainingNumberOfBytesToRead);
                        this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + remainingNumberOfBytesToRead);
                        return(count);
                    }
                    else
                    {
                        // we can only partially satisfy the read request
                        int availableBytesToRead = this.batchBuffer.NumberOfBytesInBuffer;
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, availableBytesToRead);
                        remainingNumberOfBytesToRead -= availableBytesToRead;
                        userBufferOffset             += availableBytesToRead;

                        // we exhausted the buffer; if the underlying stream is not exceeded, refill the buffer
                        if (this.underlyingStreamExhausted)
                        {
                            // We cannot fully satisfy the read request since there are not enough bytes in the stream.
                            // Return the number of bytes we read.
                            this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + availableBytesToRead);
                            return(count - remainingNumberOfBytesToRead);
                        }
                        else
                        {
                            this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ ODataBatchReaderStreamBuffer.BufferLength);
                        }
                    }

                    break;

                case ODataBatchReaderStreamScanResult.PartialMatch:
                    // A partial match for the boundary was found at the end of the buffer.
                    // If the underlying stream is not exceeded, refill the buffer. Otherwise return
                    // the available bytes.
                    if (this.underlyingStreamExhausted)
                    {
                        // We cannot fully satisfy the read request since there are not enough bytes in the stream.
                        // Return the remaining bytes in the buffer independently of where a portentially boundary
                        // start was detected since no full boundary can ever be detected if the stream is exhausted.
                        int bytesToReturn = Math.Min(this.batchBuffer.NumberOfBytesInBuffer, remainingNumberOfBytesToRead);
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, bytesToReturn);
                        this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + bytesToReturn);
                        remainingNumberOfBytesToRead -= bytesToReturn;
                        return(count - remainingNumberOfBytesToRead);
                    }
                    else
                    {
                        // Copy the bytes prior to the potential boundary start into the user buffer, refill the buffer and continue.
                        bytesBeforeBoundaryStart = boundaryStartPosition - this.batchBuffer.CurrentReadPosition;
                        Debug.Assert(bytesBeforeBoundaryStart < remainingNumberOfBytesToRead, "When reporting a partial match we should never have read all the remaining bytes to read (or more).");

                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, bytesBeforeBoundaryStart);
                        remainingNumberOfBytesToRead -= bytesBeforeBoundaryStart;
                        userBufferOffset             += bytesBeforeBoundaryStart;

                        this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ boundaryStartPosition);
                    }

                    break;

                case ODataBatchReaderStreamScanResult.Match:
                    // We found the full boundary match; copy everything before the boundary to the buffer
                    bytesBeforeBoundaryStart = boundaryStartPosition - this.batchBuffer.CurrentReadPosition;
                    Debug.Assert(bytesBeforeBoundaryStart <= remainingNumberOfBytesToRead, "When reporting a full match we should never have read more than the remaining bytes to read.");
                    Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, bytesBeforeBoundaryStart);
                    remainingNumberOfBytesToRead -= bytesBeforeBoundaryStart;
                    userBufferOffset             += bytesBeforeBoundaryStart;

                    // position the reader on the position of the boundary start
                    this.batchBuffer.SkipTo(boundaryStartPosition);

                    // return the number of bytes that were read
                    return(count - remainingNumberOfBytesToRead);

                default:
                    break;
                }
            }

            throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_ReadWithDelimiter));
        }
Ejemplo n.º 19
0
        private void ValidateTransition(BatchWriterState newState)
        {
            if (IsErrorState(this.state) || !IsErrorState(newState))
            {
                if ((newState == BatchWriterState.ChangeSetStarted) && (this.changeSetBoundary != null))
                {
                    throw new ODataException(Strings.ODataBatchWriter_CannotStartChangeSetWithActiveChangeSet);
                }
                if ((newState == BatchWriterState.ChangeSetCompleted) && (this.changeSetBoundary == null))
                {
                    throw new ODataException(Strings.ODataBatchWriter_CannotCompleteChangeSetWithoutActiveChangeSet);
                }
                if ((newState == BatchWriterState.BatchCompleted) && (this.changeSetBoundary != null))
                {
                    throw new ODataException(Strings.ODataBatchWriter_CannotCompleteBatchWithActiveChangeSet);
                }
                switch (this.state)
                {
                case BatchWriterState.Start:
                    if (newState != BatchWriterState.BatchStarted)
                    {
                        throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromStart);
                    }
                    break;

                case BatchWriterState.BatchStarted:
                    if (((newState != BatchWriterState.ChangeSetStarted) && (newState != BatchWriterState.OperationCreated)) && (newState != BatchWriterState.BatchCompleted))
                    {
                        throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromBatchStarted);
                    }
                    break;

                case BatchWriterState.ChangeSetStarted:
                    if ((newState != BatchWriterState.OperationCreated) && (newState != BatchWriterState.ChangeSetCompleted))
                    {
                        throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromChangeSetStarted);
                    }
                    break;

                case BatchWriterState.OperationCreated:
                    if ((((newState != BatchWriterState.OperationCreated) && (newState != BatchWriterState.OperationStreamRequested)) && ((newState != BatchWriterState.ChangeSetStarted) && (newState != BatchWriterState.ChangeSetCompleted))) && (newState != BatchWriterState.BatchCompleted))
                    {
                        throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromOperationCreated);
                    }
                    break;

                case BatchWriterState.OperationStreamRequested:
                    if (newState != BatchWriterState.OperationStreamDisposed)
                    {
                        throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromOperationContentStreamRequested);
                    }
                    break;

                case BatchWriterState.OperationStreamDisposed:
                    if (((newState != BatchWriterState.OperationCreated) && (newState != BatchWriterState.ChangeSetStarted)) && ((newState != BatchWriterState.ChangeSetCompleted) && (newState != BatchWriterState.BatchCompleted)))
                    {
                        throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromOperationContentStreamDisposed);
                    }
                    break;

                case BatchWriterState.ChangeSetCompleted:
                    if (((newState != BatchWriterState.BatchCompleted) && (newState != BatchWriterState.ChangeSetStarted)) && (newState != BatchWriterState.OperationCreated))
                    {
                        throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromChangeSetCompleted);
                    }
                    break;

                case BatchWriterState.BatchCompleted:
                    throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromBatchCompleted);

                case BatchWriterState.Error:
                    if (newState != BatchWriterState.Error)
                    {
                        throw new ODataException(Strings.ODataWriterCore_InvalidTransitionFromError(this.state.ToString(), newState.ToString()));
                    }
                    break;

                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchWriter_ValidateTransition_UnreachableCodePath));
                }
            }
        }
Ejemplo n.º 20
0
        internal string ReadLine()
        {
            int numberOfBytesInBuffer = 0;

            byte[] lineBuffer = this.lineBuffer;
            ODataBatchReaderStreamScanResult noMatch = ODataBatchReaderStreamScanResult.NoMatch;

            while (noMatch != ODataBatchReaderStreamScanResult.Match)
            {
                int num2;
                int num3;
                int num4;
                noMatch = this.batchBuffer.ScanForLineEnd(out num3, out num4);
                switch (noMatch)
                {
                case ODataBatchReaderStreamScanResult.NoMatch:
                {
                    num2 = this.batchBuffer.NumberOfBytesInBuffer;
                    if (num2 > 0)
                    {
                        ODataBatchUtils.EnsureArraySize(ref lineBuffer, numberOfBytesInBuffer, num2);
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, lineBuffer, numberOfBytesInBuffer, num2);
                        numberOfBytesInBuffer += num2;
                    }
                    if (this.underlyingStreamExhausted)
                    {
                        noMatch = ODataBatchReaderStreamScanResult.Match;
                        this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + num2);
                    }
                    else
                    {
                        this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, 0x1f40);
                    }
                    continue;
                }

                case ODataBatchReaderStreamScanResult.PartialMatch:
                {
                    num2 = num3 - this.batchBuffer.CurrentReadPosition;
                    if (num2 > 0)
                    {
                        ODataBatchUtils.EnsureArraySize(ref lineBuffer, numberOfBytesInBuffer, num2);
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, lineBuffer, numberOfBytesInBuffer, num2);
                        numberOfBytesInBuffer += num2;
                    }
                    if (this.underlyingStreamExhausted)
                    {
                        noMatch = ODataBatchReaderStreamScanResult.Match;
                        this.batchBuffer.SkipTo(num3 + 1);
                    }
                    else
                    {
                        this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, num3);
                    }
                    continue;
                }

                case ODataBatchReaderStreamScanResult.Match:
                {
                    num2 = num3 - this.batchBuffer.CurrentReadPosition;
                    if (num2 > 0)
                    {
                        ODataBatchUtils.EnsureArraySize(ref lineBuffer, numberOfBytesInBuffer, num2);
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, lineBuffer, numberOfBytesInBuffer, num2);
                        numberOfBytesInBuffer += num2;
                    }
                    this.batchBuffer.SkipTo(num4 + 1);
                    continue;
                }
                }
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_ReadLine));
            }
            if (lineBuffer == null)
            {
                return(string.Empty);
            }
            return(this.CurrentEncoding.GetString(lineBuffer, 0, numberOfBytesInBuffer));
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Converts a string to a primitive value.
        /// </summary>
        /// <param name="text">The string text to convert.</param>
        /// <param name="targetTypeReference">Type to convert the string to.</param>
        /// <returns>The value converted to the target type.</returns>
        /// <remarks>This method does not convert null value.</remarks>
        internal static object ConvertStringToPrimitive(string text, IEdmPrimitiveTypeReference targetTypeReference)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(text != null, "text != null");
            Debug.Assert(targetTypeReference != null, "targetTypeReference != null");

            try
            {
                EdmPrimitiveTypeKind primitiveKind = targetTypeReference.PrimitiveKind();

                switch (primitiveKind)
                {
                case EdmPrimitiveTypeKind.Binary:
                    return(Convert.FromBase64String(text));

                case EdmPrimitiveTypeKind.Boolean:
                    return(ConvertXmlBooleanValue(text));

                case EdmPrimitiveTypeKind.Byte:
                    return(XmlConvert.ToByte(text));

                case EdmPrimitiveTypeKind.DateTime:
                    return(PlatformHelper.ConvertStringToDateTime(text));

                case EdmPrimitiveTypeKind.DateTimeOffset:
                    return(PlatformHelper.ConvertStringToDateTimeOffset(text));

                case EdmPrimitiveTypeKind.Decimal:
                    return(XmlConvert.ToDecimal(text));

                case EdmPrimitiveTypeKind.Double:
                    return(XmlConvert.ToDouble(text));

                case EdmPrimitiveTypeKind.Guid:
                    return(new Guid(text));

                case EdmPrimitiveTypeKind.Int16:
                    return(XmlConvert.ToInt16(text));

                case EdmPrimitiveTypeKind.Int32:
                    return(XmlConvert.ToInt32(text));

                case EdmPrimitiveTypeKind.Int64:
                    return(XmlConvert.ToInt64(text));

                case EdmPrimitiveTypeKind.SByte:
                    return(XmlConvert.ToSByte(text));

                case EdmPrimitiveTypeKind.Single:
                    return(XmlConvert.ToSingle(text));

                case EdmPrimitiveTypeKind.String:
                    return(text);

                case EdmPrimitiveTypeKind.Time:
                    return(XmlConvert.ToTimeSpan(text));

                case EdmPrimitiveTypeKind.Stream:
                case EdmPrimitiveTypeKind.None:
                case EdmPrimitiveTypeKind.Geography:
                case EdmPrimitiveTypeKind.GeographyCollection:
                case EdmPrimitiveTypeKind.GeographyPoint:
                case EdmPrimitiveTypeKind.GeographyLineString:
                case EdmPrimitiveTypeKind.GeographyPolygon:
                case EdmPrimitiveTypeKind.GeometryCollection:
                case EdmPrimitiveTypeKind.GeographyMultiPolygon:
                case EdmPrimitiveTypeKind.GeographyMultiLineString:
                case EdmPrimitiveTypeKind.GeographyMultiPoint:
                case EdmPrimitiveTypeKind.Geometry:
                case EdmPrimitiveTypeKind.GeometryPoint:
                case EdmPrimitiveTypeKind.GeometryLineString:
                case EdmPrimitiveTypeKind.GeometryPolygon:
                case EdmPrimitiveTypeKind.GeometryMultiPolygon:
                case EdmPrimitiveTypeKind.GeometryMultiLineString:
                case EdmPrimitiveTypeKind.GeometryMultiPoint:
                default:
                    // Note that Astoria supports XElement and Binary as well, but they are serialized as string or byte[]
                    // and the metadata will actually talk about string and byte[] as well. Astoria will perform the conversion if necessary.
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.AtomValueUtils_ConvertStringToPrimitive));
                }
            }
            catch (Exception e)
            {
                if (!ExceptionUtils.IsCatchableExceptionType(e))
                {
                    throw;
                }

                throw ReaderValidationUtils.GetPrimitiveTypeConversionException(targetTypeReference, e);
            }
        }
Ejemplo n.º 22
0
        protected override Task <bool> ReadAsynchronously()
        {
            Task <bool> result;

            switch (this.State)
            {
            case ODataReaderState.Start:
                result = this.ReadAtStartImplementationAsync();
                break;

            case ODataReaderState.FeedStart:
                result = this.ReadAtFeedStartImplementationAsync();
                break;

            case ODataReaderState.FeedEnd:
                result = this.ReadAtFeedEndImplementationAsync();
                break;

            case ODataReaderState.EntryStart:
                result = TaskUtils.GetTaskForSynchronousOperation(() => this.IncreaseEntryDepth())
                         .FollowOnSuccessWithTask(t => this.ReadAtEntryStartImplementationAsync());
                break;

            case ODataReaderState.EntryEnd:
                result = TaskUtils.GetTaskForSynchronousOperation(() => this.DecreaseEntryDepth())
                         .FollowOnSuccessWithTask(t => this.ReadAtEntryEndImplementationAsync());
                break;

            case ODataReaderState.NavigationLinkStart:
                result = this.ReadAtNavigationLinkStartImplementationAsync();
                break;

            case ODataReaderState.NavigationLinkEnd:
                result = this.ReadAtNavigationLinkEndImplementationAsync();
                break;

            case ODataReaderState.EntityReferenceLink:
                result = this.ReadAtEntityReferenceLinkAsync();
                break;

            case ODataReaderState.Exception:        // fall through
            case ODataReaderState.Completed:
                result = TaskUtils.GetFaultedTask <bool>(new ODataException(Strings.ODataReaderCore_NoReadCallsAllowed(this.State)));
                break;

            default:
                Debug.Assert(false, "Unsupported reader state " + this.State + " detected.");
                result = TaskUtils.GetFaultedTask <bool>(new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataReaderCoreAsync_ReadAsynchronously)));
                break;
            }

            return(result.FollowOnSuccessWith(t =>
            {
                if ((this.State == ODataReaderState.EntryStart || this.State == ODataReaderState.EntryEnd) && this.Item != null)
                {
                    ReaderValidationUtils.ValidateEntry(this.CurrentEntry);
                }

                return t.Result;
            }));
        }