private bool PrepareMetadata(StreamScope scope) { // The metadata stream can either be inlined or compressed var token = ReadToken(); if (token == ArchiveMetadataToken.PackedHeader) { var streams = ReadPackedStreams(); // Compressed metadata without content is odd but allowed. if (streams.IsDefaultOrEmpty) { return(false); } // Compressed metadata with multiple streams is not allowed. if (streams.Length != 1) { throw new InvalidDataException(); } // Switch over to the decoded metadata stream. scope.SetSource(streams[0]); token = ReadToken(); } // The metadata stream must start with this token. if (token != ArchiveMetadataToken.Header) { throw new InvalidDataException(); } return(true); }
/// <summary> /// This method is called when a stream is disposed. /// </summary> void IODataStreamListener.StreamDisposed() { Debug.Assert(this.State == ODataReaderState.Stream, "Stream was disposed when not in ReaderState.Stream state."); StreamScope scope = this.CurrentScope as StreamScope; Debug.Assert(scope != null, "Stream disposed when not in stream scope"); Debug.Assert(scope.StreamingState == StreamingState.Streaming, "StreamDisposed called when reader was not streaming"); scope.StreamingState = StreamingState.Completed; }
/// <summary> /// Creates a stream for reading an inline stream property. /// </summary> /// <returns>A stream for reading the stream property.</returns> public override sealed Stream CreateReadStream() { if (this.State != ODataReaderState.Stream) { throw new ODataException(Strings.ODataReaderCore_CreateReadStreamCalledInInvalidState); } StreamScope scope = this.CurrentScope as StreamScope; Debug.Assert(scope != null, "ODataReaderState.Stream when Scope is not a StreamScope"); if (scope.StreamingState != StreamingState.None) { throw new ODataException(Strings.ODataReaderCore_CreateReadStreamCalledInInvalidState); } scope.StreamingState = StreamingState.Streaming; return(new ODataNotificationStream(this.InterceptException(this.CreateReadStreamImplementation), this)); }
/// <summary> /// Verifies that calling Read is valid. /// </summary> /// <param name="synchronousCall">true if the call is to be synchronous; false otherwise.</param> private void VerifyCanRead(bool synchronousCall) { this.inputContext.VerifyNotDisposed(); this.VerifyCallAllowed(synchronousCall); if (this.State == ODataReaderState.Exception || this.State == ODataReaderState.Completed) { throw new ODataException(Strings.ODataReaderCore_ReadOrReadAsyncCalledInInvalidState(this.State)); } if (this.State == ODataReaderState.Stream) { StreamScope scope = this.CurrentScope as StreamScope; Debug.Assert(scope != null, "In stream state without a stream scope"); if (scope.StreamingState != StreamingState.Completed) { throw new ODataException(Strings.ODataReaderCore_ReadCalledWithOpenStream); } } }
/// <summary>Asynchronously creates a <see cref="TextReader"/> for reading an inline string property.</summary> /// <returns> /// A task that represents the asynchronous operation. /// The value of the TResult parameter contains a <see cref="TextReader"/> for reading the string property. /// </returns> public override async Task <TextReader> CreateTextReaderAsync() { if (this.State != ODataReaderState.Stream) { throw new ODataException(Strings.ODataReaderCore_CreateTextReaderCalledInInvalidState); } StreamScope scope = this.CurrentScope as StreamScope; Debug.Assert(scope != null, "ODataReaderState.Stream when Scope is not a StreamScope"); if (scope.StreamingState != StreamingState.None) { throw new ODataException(Strings.ODataReaderCore_CreateReadStreamCalledInInvalidState); } scope.StreamingState = StreamingState.Streaming; return(new ODataNotificationReader( textReader: await this.InterceptExceptionAsync(thisParam => thisParam.CreateTextReaderImplementationAsync()).ConfigureAwait(false), listener: this, synchronous: false)); }
private StreamScope SelectStream(ImmutableArray <Stream> streams) { var switchStream = ReadByte(); if (switchStream == 0) { return(null); } var streamIndex = ReadNumberAsInt32(); if (streamIndex < 0 || streamIndex >= streams.Length) { throw new InvalidDataException(); } var stream = streams[streamIndex]; var scope = new StreamScope(this); scope.SetSource(stream); return(scope); }
protected ArchiveMetadata ReadMetadataCore(Stream stream, PasswordStorage password) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } if (!stream.CanRead || !stream.CanSeek) { throw new InvalidOperationException("Stream must support reading and seeking."); } if (mStream != null) { throw new InvalidOperationException("Recursive invocation."); } try { mPassword = password; mStream = stream; mStream.Position = 0; mStreamLength = stream.Length; var exception = ReadFileHeader(mStream, mStreamLength, out mMajorVersion, out mMinorVersion, out mMetadataOffset, out mMetadataLength, out mMetadataChecksum); if (exception != null) { throw exception; } if (mMetadataLength == 0) { return(new ArchiveMetadata()); } // TODO: validate metadata stream checksum using (var metadataStream = new ConstrainedReadStream(mStream, ArchiveMetadataFormat.kHeaderLength + mMetadataOffset, mMetadataLength)) using (var scope = new StreamScope(this)) { scope.SetSource(metadataStream); if (!PrepareMetadata(scope)) { return(new ArchiveMetadata()); } return(ReadArchive()); } } finally { // Drop references to password and stream so they aren't retained. mPassword = null; mStream = null; // It is also important to reset optional values to their defaults. Otherwise if // the next archive we are reading doesn't contain some of the optional values // we could mistake the values from the previous archive as current values. //mFileCount = 0; } }
public StreamScope(ArchiveMetadataReader reader) { mReader = reader; mOuterScope = reader.mScope; reader.mScope = this; }
private bool PrepareMetadata(StreamScope scope) { // The metadata stream can either be inlined or compressed var token = ReadToken(); if (token == ArchiveMetadataToken.PackedHeader) { var streams = ReadPackedStreams(); // Compressed metadata without content is odd but allowed. if (streams.IsDefaultOrEmpty) return false; // Compressed metadata with multiple streams is not allowed. if (streams.Length != 1) throw new InvalidDataException(); // Switch over to the decoded metadata stream. scope.SetSource(streams[0]); token = ReadToken(); } // The metadata stream must start with this token. if (token != ArchiveMetadataToken.Header) throw new InvalidDataException(); return true; }
protected ArchiveMetadata ReadMetadataCore(Stream stream, PasswordStorage password) { if (stream == null) throw new ArgumentNullException(nameof(stream)); if (!stream.CanRead || !stream.CanSeek) throw new InvalidOperationException("Stream must support reading and seeking."); if (mStream != null) throw new InvalidOperationException("Recursive invocation."); try { mPassword = password; mStream = stream; mStream.Position = 0; mStreamLength = stream.Length; var exception = ReadFileHeader(mStream, mStreamLength, out mMajorVersion, out mMinorVersion, out mMetadataOffset, out mMetadataLength, out mMetadataChecksum); if (exception != null) throw exception; if (mMetadataLength == 0) return new ArchiveMetadata(); // TODO: validate metadata stream checksum using (var metadataStream = new ConstrainedReadStream(mStream, ArchiveMetadataFormat.kHeaderLength + mMetadataOffset, mMetadataLength)) using (var scope = new StreamScope(this)) { scope.SetSource(metadataStream); if (!PrepareMetadata(scope)) return new ArchiveMetadata(); return ReadArchive(); } } finally { // Drop references to password and stream so they aren't retained. mPassword = null; mStream = null; // It is also important to reset optional values to their defaults. Otherwise if // the next archive we are reading doesn't contain some of the optional values // we could mistake the values from the previous archive as current values. //mFileCount = 0; } }
private StreamScope SelectStream(ImmutableArray<Stream> streams) { var switchStream = ReadByte(); if (switchStream == 0) return null; var streamIndex = ReadNumberAsInt32(); if (streamIndex < 0 || streamIndex >= streams.Length) throw new InvalidDataException(); var stream = streams[streamIndex]; var scope = new StreamScope(this); scope.SetSource(stream); return scope; }