public override int Read(byte[] buffer, int offset, int count) { CheckDisposed(); if (!CanRead) { throw new InvalidOperationException("Stream not open for reading"); } if (_isConsumed) { return(0); } if (_leftToReadInDataMsg == 0) { // We've consumed the current DataMessage (or haven't yet received the first), // read the next message var msg = _connector.ReadMessage(DataRowLoadingMode.NonSequential); switch (msg.Code) { case BackendMessageCode.CopyData: _leftToReadInDataMsg = ((CopyDataMessage)msg).Length; break; case BackendMessageCode.CopyDone: _connector.ReadExpecting <CommandCompleteMessage>(); _connector.ReadExpecting <ReadyForQueryMessage>(); _isConsumed = true; return(0); default: throw _connector.UnexpectedMessageReceived(msg.Code); } } Contract.Assume(_leftToReadInDataMsg > 0); // If our buffer is empty, read in more. Otherwise return whatever is there, even if the // user asked for more (normal socket behavior) if (_readBuf.ReadBytesLeft == 0) { _readBuf.ReadMore(); } Contract.Assert(_readBuf.ReadBytesLeft > 0); var maxCount = Math.Min(_readBuf.ReadBytesLeft, _leftToReadInDataMsg); if (count > maxCount) { count = maxCount; } _leftToReadInDataMsg -= count; _readBuf.ReadBytes(buffer, offset, count); return(count); }
internal override T2 ReadFully <T2>(ReadBuffer buf, int len, FieldDescription fieldDescription = null) { var asTypedHandler = this as IChunkingTypeHandler <T2>; if (asTypedHandler == null) { throw new InvalidCastException(fieldDescription == null ? "Can't cast database type to " + typeof(T2).Name : $"Can't cast database type {fieldDescription.Handler.PgDisplayName} to {typeof(T2).Name}" ); } asTypedHandler.PrepareRead(buf, len, fieldDescription); T2 result; while (!asTypedHandler.Read(out result)) { buf.ReadMore(); } return(result); }