linux-packaging-mono/mcs/class/System/corefx/SocketAsyncEventArgs.cs
Xamarin Public Jenkins (auto-signing) 73ee7591e8 Imported Upstream version 6.8.0.73
Former-commit-id: d18deab1b47cfd3ad8cba82b3f37d00eec2170af
2019-12-10 18:00:56 +00:00

170 lines
5.4 KiB
C#

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Security;
using System.Threading;
namespace System.Net.Sockets
{
partial class SocketAsyncEventArgs
{
// Single buffer.
private Memory<byte> _buffer;
private int _offset;
private int _count;
private bool _bufferIsExplicitArray;
// BufferList property variables.
private IList<ArraySegment<byte>> _bufferList;
private List<ArraySegment<byte>> _bufferListInternal;
public byte[] Buffer
{
get
{
if (_bufferIsExplicitArray)
{
bool success = MemoryMarshal.TryGetArray(_buffer, out ArraySegment<byte> arraySegment);
Debug.Assert(success);
return arraySegment.Array;
}
return null;
}
}
public Memory<byte> MemoryBuffer => _buffer;
public int Offset => _offset;
public int Count => _count;
// NOTE: this property is mutually exclusive with Buffer.
// Setting this property with an existing non-null Buffer will throw.
public IList<ArraySegment<byte>> BufferList
{
get { return _bufferList; }
set
{
if (value != null)
{
if (!_buffer.Equals(default))
{
// Can't have both set
throw new ArgumentException(SR.Format(SR.net_ambiguousbuffers, nameof(Buffer)));
}
// Copy the user-provided list into our internal buffer list,
// so that we are not affected by subsequent changes to the list.
// We reuse the existing list so that we can avoid reallocation when possible.
int bufferCount = value.Count;
if (_bufferListInternal == null)
{
_bufferListInternal = new List<ArraySegment<byte>>(bufferCount);
}
else
{
_bufferListInternal.Clear();
}
for (int i = 0; i < bufferCount; i++)
{
ArraySegment<byte> buffer = value[i];
RangeValidationHelpers.ValidateSegment(buffer);
_bufferListInternal.Add(buffer);
}
}
else
{
_bufferListInternal?.Clear();
}
_bufferList = value;
}
}
public void SetBuffer(int offset, int count)
{
if (!_buffer.Equals(default))
{
if ((uint)offset > _buffer.Length)
{
throw new ArgumentOutOfRangeException(nameof(offset));
}
if ((uint)count > (_buffer.Length - offset))
{
throw new ArgumentOutOfRangeException(nameof(count));
}
if (!_bufferIsExplicitArray)
{
throw new InvalidOperationException(SR.InvalidOperation_BufferNotExplicitArray);
}
_offset = offset;
_count = count;
}
}
internal void CopyBufferFrom(SocketAsyncEventArgs source)
{
_buffer = source._buffer;
_offset = source._offset;
_count = source._count;
_bufferIsExplicitArray = source._bufferIsExplicitArray;
}
public void SetBuffer(byte[] buffer, int offset, int count)
{
if (buffer == null)
{
// Clear out existing buffer.
_buffer = default;
_offset = 0;
_count = 0;
_bufferIsExplicitArray = false;
}
else
{
// Can't have both Buffer and BufferList.
if (_bufferList != null)
{
throw new ArgumentException(SR.Format(SR.net_ambiguousbuffers, nameof(BufferList)));
}
// Offset and count can't be negative and the
// combination must be in bounds of the array.
if ((uint)offset > buffer.Length)
{
throw new ArgumentOutOfRangeException(nameof(offset));
}
if ((uint)count > (buffer.Length - offset))
{
throw new ArgumentOutOfRangeException(nameof(count));
}
_buffer = buffer;
_offset = offset;
_count = count;
_bufferIsExplicitArray = true;
}
}
public void SetBuffer(Memory<byte> buffer)
{
if (buffer.Length != 0 && _bufferList != null)
{
throw new ArgumentException(SR.Format(SR.net_ambiguousbuffers, nameof(BufferList)));
}
_buffer = buffer;
_offset = 0;
_count = buffer.Length;
_bufferIsExplicitArray = false;
}
internal bool HasMultipleBuffers => _bufferList != null;
}
}