public BucketBytes AsBytes(BucketBytes appendBytes) { if (IsEmpty) { return(appendBytes); } else if (appendBytes.IsEmpty) { return(IsEmpty ? BucketBytes.Empty : AsBytes()); } if (_expected > 0) { _expected = 0; if (Length > 0) { byte[] bb = (byte[])_bytes !; _bytes = _bytes !.Take(Length); if (Length + appendBytes.Length <= bb.Length) { appendBytes.CopyTo(bb.AsSpan(Length)); return(new BucketBytes(bb, 0, Length + appendBytes.Length)); } } } return(_bytes !.Concat(appendBytes.ToArray()).ToArray()); }
async Task <BucketBytes> DoRead(int requested) { if (_unread.Length > 0) { var bb = _unread.Slice(0, Math.Min(requested, _unread.Length)); _unread = _unread.Slice(bb.Length); return(bb); } else if (_readEof) { return(BucketBytes.Eof); } int len = await Socket.ReceiveAsync(new ArraySegment <byte>(_inputBuffer), SocketFlags.None).ConfigureAwait(false); if (len > 0) { _bytesRead += len; if (len > requested) { _unread = new BucketBytes(_inputBuffer, requested, len - requested); return(new BucketBytes(_inputBuffer, 0, requested)); } else { return(new BucketBytes(_inputBuffer, 0, len)); } } else { _readEof = true; return(BucketBytes.Eof); } }
public static bool IsEmpty(this BucketBytes bytes, BucketEol eol) { if (bytes.IsEmpty || bytes.Length == eol.CharCount()) { return(true); } return(false); }
internal static Task <int> SendAsync(this Socket socket, ReadOnlyMemory <byte> buffer, SocketFlags socketFlags) { if (socket is null) { throw new ArgumentNullException(nameof(socket)); } return(Task <int> .Factory.FromAsync( (AsyncCallback cb, object?state) => { var(arr, offset) = BucketBytes.ExpandToArray(buffer); return socket.BeginSend(arr !, offset, buffer.Length, socketFlags, cb, state); }, socket.EndSend, null)); }
public void Append(BucketBytes bytes) { if (bytes.Length == 0) { return; } if (_expected > 0) { byte[]? bb = _bytes as byte[]; if (bytes.Length + (bb?.Length ?? 0) <= _expected) { _bytes = bb ??= new byte[_expected]; bytes.CopyTo(bb.AsSpan(Length)); Length += bytes.Length; return; } else if (Length == 0) { _bytes = bytes !.ToArray(); Length = bytes.Length; _expected = 0; return; } else { _bytes = _bytes !.Take(Length); _expected = 0; // And fall through } } if (_bytes is null) { _bytes = bytes.ToArray(); } else { _bytes = _bytes.Concat(bytes.ToArray()); } Length += bytes.Length; }
public static ValueTask WriteAsync(this Stream stream, BucketBytes bucketBytes, CancellationToken cancellationToken = default) { if (stream is null) { throw new ArgumentNullException(nameof(stream)); } #if !NETFRAMEWORK return(stream.WriteAsync(bucketBytes.Memory, cancellationToken)); #else var(q, r) = bucketBytes; if (q is not null) { return(new ValueTask(stream.WriteAsync(q, r, bucketBytes.Length, cancellationToken))); } else { q = bucketBytes.ToArray(); return(new ValueTask(stream.WriteAsync(q, 0, bucketBytes.Length, cancellationToken))); } #endif }
internal static string AsDebuggerDisplay(this BucketBytes bb) => bb.Memory.AsDebuggerDisplay();
public async ValueTask <BucketBytes> ReadAsync(int readBytes) { try { if (AlreadyRead == 0) { return(await Bucket.ReadAsync(readBytes).ConfigureAwait(false)); } else if (readBytes <= AlreadyRead) { if (readBytes < AlreadyRead) { throw new InvalidOperationException(); } AlreadyRead = 0; var r = Data.Slice(0, readBytes); Data = Data.Slice(readBytes); return(r); } else if (readBytes > Data.Length) { byte[] returnData; if (readBytes < Data.Length) { returnData = Data.Slice(0, readBytes).ToArray(); } else { returnData = Data.ToArray(); } int consume = readBytes - AlreadyRead; int copy = AlreadyRead; AlreadyRead = 0; // No errors in Dispose please var bb = await Bucket.ReadAsync(consume).ConfigureAwait(false); if (bb.IsEof) { return(new BucketBytes(returnData, 0, copy)); } if (copy + bb.Length <= returnData.Length) { return(new BucketBytes(returnData, 0, copy + bb.Length)); // Data already available from peek buffer } // We got new and old data, but how can we return that? var(arr, offset) = bb; // Unlikely, but cheap: The return buffer is what we need if (arr is not null && offset >= copy && new ReadOnlySpan <byte>(arr, offset - copy, copy).SequenceEqual(returnData)) { return(new BucketBytes(arr, offset - copy, bb.Length + copy)); } byte[] ret = new byte[bb.Length + copy]; Array.Copy(returnData, ret, copy); bb.Span.CopyTo(new Span <byte>(ret, copy, bb.Length)); return(ret); } else { int consume = readBytes - AlreadyRead; BucketBytes slicedDataCopy = Data.Slice(0, Math.Min(readBytes, Data.Length)).ToArray(); var bb = await Bucket.ReadAsync(consume).ConfigureAwait(false); AlreadyRead = Math.Max(0, AlreadyRead - bb.Length); if (bb.Length == consume) { return(slicedDataCopy); } else if (bb.Length < consume) { return(slicedDataCopy.Slice(0, slicedDataCopy.Length - (consume - bb.Length))); } else { throw new InvalidOperationException(); } } } finally { Data = BucketBytes.Empty; } }
public BucketPollBytes(Bucket bucket, BucketBytes data, int alreadyRead) { Bucket = bucket ?? throw new ArgumentNullException(nameof(bucket)); Data = data; AlreadyRead = alreadyRead; }
public DebuggerProxy(BucketBytes bytes) { Bytes = bytes; }