// The highest order bit of _index is used to discern whether _object is an array/string or an owned memory
// if (_index >> 31) == 1, object _object is an OwnedMemory<T>
- // else, object _object is a T[] or a string. It can only be a string if the Memory<T> was created by
+ // else, object _object is a T[] or a string. It can only be a string if the Memory<T> was created by
// using unsafe / marshaling code to reinterpret a ReadOnlyMemory<char> wrapped around a string as
// a Memory<T>.
private readonly object _object;
/// <summary>
/// Returns an empty <see cref="Memory{T}"/>
/// </summary>
- public static Memory<T> Empty { get; } = Array.Empty<T>();
+ public static Memory<T> Empty => default;
/// <summary>
/// The number of items in the memory.
{
// This is dangerous, returning a writable span for a string that should be immutable.
// However, we need to handle the case where a ReadOnlyMemory<char> was created from a string
- // and then cast to a Memory<T>. Such a cast can only be done with unsafe or marshaling code,
+ // and then cast to a Memory<T>. Such a cast can only be done with unsafe or marshaling code,
// in which case that's the dangerous operation performed by the dev, and we're just following
// suit here to make it work as best as possible.
return new Span<T>(ref Unsafe.As<char, T>(ref s.GetRawStringData()), s.Length).Slice(_index, _length);
}
- else
+ else if (_object != null)
{
return new Span<T>((T[])_object, _index, _length);
}
+ else
+ {
+ return default;
+ }
}
}
public unsafe MemoryHandle Retain(bool pin = false)
{
- MemoryHandle memoryHandle;
+ MemoryHandle memoryHandle = default;
if (pin)
{
if (_index < 0)
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
memoryHandle = new MemoryHandle(null, pointer, handle);
}
- else
+ else if (_object is T[] array)
{
- var array = (T[])_object;
var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
memoryHandle = new MemoryHandle(null, pointer, handle);
((OwnedMemory<T>)_object).Retain();
memoryHandle = new MemoryHandle((OwnedMemory<T>)_object);
}
- else
- {
- memoryHandle = new MemoryHandle(null);
- }
}
return memoryHandle;
}
return true;
}
}
- else
+ else if (_object is T[] arr)
{
- T[] arr = _object as T[];
- if (typeof(T) != typeof(char) || arr != null)
- {
- arraySegment = new ArraySegment<T>(arr, _index, _length);
- return true;
- }
+ arraySegment = new ArraySegment<T>(arr, _index, _length);
+ return true;
}
arraySegment = default(ArraySegment<T>);
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode()
{
- return CombineHashCodes(_object.GetHashCode(), _index.GetHashCode(), _length.GetHashCode());
+ return _object != null ? CombineHashCodes(_object.GetHashCode(), _index.GetHashCode(), _length.GetHashCode()) : 0;
}
private static int CombineHashCodes(int left, int right)
_length = length;
}
- /// <summary>Creates a new memory over the existing object, start, and length. No validation is performed.</summary>
+ /// <summary>Creates a new memory over the existing object, start, and length. No validation is performed.</summary>
/// <param name="obj">The target object.</param>
/// <param name="start">The index at which to begin the memory.</param>
/// <param name="length">The number of items in the memory.</param>
/// <summary>
/// Returns an empty <see cref="ReadOnlyMemory{T}"/>
/// </summary>
- public static ReadOnlyMemory<T> Empty { get; } = Array.Empty<T>();
+ public static ReadOnlyMemory<T> Empty => default;
/// <summary>
/// The number of items in the memory.
{
return new ReadOnlySpan<T>(ref Unsafe.As<char, T>(ref s.GetRawStringData()), s.Length).Slice(_index, _length);
}
- else
+ else if (_object != null)
{
return new ReadOnlySpan<T>((T[])_object, _index, _length);
}
+ else
+ {
+ return default;
+ }
}
}
/// </param>
public unsafe MemoryHandle Retain(bool pin = false)
{
- MemoryHandle memoryHandle;
+ MemoryHandle memoryHandle = default;
if (pin)
{
if (_index < 0)
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
memoryHandle = new MemoryHandle(null, pointer, handle);
}
- else
+ else if (_object is T[] array)
{
- var array = (T[])_object;
var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
memoryHandle = new MemoryHandle(null, pointer, handle);
((OwnedMemory<T>)_object).Retain();
memoryHandle = new MemoryHandle((OwnedMemory<T>)_object);
}
- else
- {
- memoryHandle = new MemoryHandle(null);
- }
}
return memoryHandle;
}
return true;
}
}
- else
+ else if (_object is T[] arr)
{
- T[] arr = _object as T[];
- if (typeof(T) != typeof(char) || arr != null)
- {
- arraySegment = new ArraySegment<T>(arr, _index, _length);
- return true;
- }
+ arraySegment = new ArraySegment<T>(arr, _index, _length);
+ return true;
}
arraySegment = default;
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode()
{
- return CombineHashCodes(_object.GetHashCode(), _index.GetHashCode(), _length.GetHashCode());
+ return _object != null ? CombineHashCodes(_object.GetHashCode(), _index.GetHashCode(), _length.GetHashCode()) : 0;
}
private static int CombineHashCodes(int left, int right)