public static bool Contains<T>(this Span<T> span, T value)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.Contains(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
- if (typeof(T) == typeof(char))
+ if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.Contains(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, char>(ref value),
public static bool Contains<T>(this ReadOnlySpan<T> span, T value)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.Contains(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
- if (typeof(T) == typeof(char))
+ if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.Contains(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, char>(ref value),
public static int IndexOf<T>(this Span<T> span, T value)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOf(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
- if (typeof(T) == typeof(char))
+ if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOf(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, char>(ref value),
public static int IndexOf<T>(this Span<T> span, ReadOnlySpan<T> value)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOf(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
value.Length);
- if (typeof(T) == typeof(char))
+ if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOf(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
span.Length,
public static int LastIndexOf<T>(this Span<T> span, T value)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.LastIndexOf(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
- if (typeof(T) == typeof(char))
+ if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.LastIndexOf(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, char>(ref value),
public static int LastIndexOf<T>(this Span<T> span, ReadOnlySpan<T> value)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.LastIndexOf(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
span.Length,
{
int length = span.Length;
- if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
+ if (RuntimeHelpers.IsBitwiseEquatable<T>())
+ {
+ nuint size = (nuint)Unsafe.SizeOf<T>();
return length == other.Length &&
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)),
((nuint)length) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+ }
return length == other.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length);
}
public static int SequenceCompareTo<T>(this Span<T> span, ReadOnlySpan<T> other)
where T : IComparable<T>
{
+ // Can't use IsBitwiseEquatable<T>() below because that only tells us about
+ // equality checks, not about CompareTo checks.
+
if (typeof(T) == typeof(byte))
return SpanHelpers.SequenceCompareTo(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
public static int IndexOf<T>(this ReadOnlySpan<T> span, T value)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOf(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
- if (typeof(T) == typeof(char))
+ if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOf(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, char>(ref value),
public static int IndexOf<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> value)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOf(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
value.Length);
- if (typeof(T) == typeof(char))
+ if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOf(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
span.Length,
public static int LastIndexOf<T>(this ReadOnlySpan<T> span, T value)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.LastIndexOf(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
- if (typeof(T) == typeof(char))
+ if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.LastIndexOf(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, char>(ref value),
public static int LastIndexOf<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> value)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.LastIndexOf(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
span.Length,
public static int IndexOfAny<T>(this Span<T> span, T value0, T value1)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOfAny(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value0),
Unsafe.As<T, byte>(ref value1),
span.Length);
- if (typeof(T) == typeof(char))
+ if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOfAny(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, char>(ref value0),
public static int IndexOfAny<T>(this Span<T> span, T value0, T value1, T value2)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOfAny(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value0),
Unsafe.As<T, byte>(ref value1),
Unsafe.As<T, byte>(ref value2),
span.Length);
- if (typeof(T) == typeof(char))
+ if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOfAny(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, char>(ref value0),
public static int IndexOfAny<T>(this Span<T> span, ReadOnlySpan<T> values)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
{
ref byte valueRef = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values));
if (values.Length == 2)
values.Length);
}
}
- if (typeof(T) == typeof(char))
+ if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>())
{
ref var valueRef = ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(values));
if (values.Length == 5)
public static int IndexOfAny<T>(this ReadOnlySpan<T> span, T value0, T value1)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOfAny(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value0),
Unsafe.As<T, byte>(ref value1),
span.Length);
- if (typeof(T) == typeof(char))
+ if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOfAny(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, char>(ref value0),
public static int IndexOfAny<T>(this ReadOnlySpan<T> span, T value0, T value1, T value2)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOfAny(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value0),
Unsafe.As<T, byte>(ref value1),
Unsafe.As<T, byte>(ref value2),
span.Length);
- if (typeof(T) == typeof(char))
+ if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.IndexOfAny(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, char>(ref value0),
public static int IndexOfAny<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> values)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
{
ref byte valueRef = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values));
if (values.Length == 2)
}
}
- if (typeof(T) == typeof(char))
+ if (Unsafe.SizeOf<T>() == sizeof(char) && RuntimeHelpers.IsBitwiseEquatable<T>())
{
ref var valueRef = ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(values));
if (values.Length == 5)
public static int LastIndexOfAny<T>(this Span<T> span, T value0, T value1)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.LastIndexOfAny(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value0),
public static int LastIndexOfAny<T>(this Span<T> span, T value0, T value1, T value2)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.LastIndexOfAny(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value0),
public static int LastIndexOfAny<T>(this Span<T> span, ReadOnlySpan<T> values)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.LastIndexOfAny(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
span.Length,
public static int LastIndexOfAny<T>(this ReadOnlySpan<T> span, T value0, T value1)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.LastIndexOfAny(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value0),
public static int LastIndexOfAny<T>(this ReadOnlySpan<T> span, T value0, T value1, T value2)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.LastIndexOfAny(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value0),
public static int LastIndexOfAny<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> values)
where T : IEquatable<T>
{
- if (typeof(T) == typeof(byte))
+ if (Unsafe.SizeOf<T>() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable<T>())
return SpanHelpers.LastIndexOfAny(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
span.Length,
where T : IEquatable<T>
{
int length = span.Length;
- if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
+ if (RuntimeHelpers.IsBitwiseEquatable<T>())
+ {
+ nuint size = (nuint)Unsafe.SizeOf<T>();
return length == other.Length &&
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)),
((nuint)length) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+ }
return length == other.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length);
}
public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other)
where T : IComparable<T>
{
+ // Can't use IsBitwiseEquatable<T>() below because that only tells us about
+ // equality checks, not about CompareTo checks.
+
if (typeof(T) == typeof(byte))
return SpanHelpers.SequenceCompareTo(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
where T : IEquatable<T>
{
int valueLength = value.Length;
- if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
+ if (RuntimeHelpers.IsBitwiseEquatable<T>())
+ {
+ nuint size = (nuint)Unsafe.SizeOf<T>();
return valueLength <= span.Length &&
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
((nuint)valueLength) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+ }
return valueLength <= span.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), valueLength);
}
where T : IEquatable<T>
{
int valueLength = value.Length;
- if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
+ if (RuntimeHelpers.IsBitwiseEquatable<T>())
+ {
+ nuint size = (nuint)Unsafe.SizeOf<T>();
return valueLength <= span.Length &&
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
((nuint)valueLength) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+ }
return valueLength <= span.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), valueLength);
}
{
int spanLength = span.Length;
int valueLength = value.Length;
- if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
+ if (RuntimeHelpers.IsBitwiseEquatable<T>())
+ {
+ nuint size = (nuint)Unsafe.SizeOf<T>();
return valueLength <= spanLength &&
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), spanLength - valueLength)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
((nuint)valueLength) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+ }
return valueLength <= spanLength &&
SpanHelpers.SequenceEqual(
{
int spanLength = span.Length;
int valueLength = value.Length;
- if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
+ if (RuntimeHelpers.IsBitwiseEquatable<T>())
+ {
+ nuint size = (nuint)Unsafe.SizeOf<T>();
return valueLength <= spanLength &&
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), spanLength - valueLength)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
((nuint)valueLength) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+ }
return valueLength <= spanLength &&
SpanHelpers.SequenceEqual(
value, comparer);
return BinarySearch(span, comparable);
}
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static bool IsTypeComparableAsBytes<T>(out nuint size)
- {
- if (typeof(T) == typeof(byte) || typeof(T) == typeof(sbyte))
- {
- size = sizeof(byte);
- return true;
- }
-
- if (typeof(T) == typeof(char) || typeof(T) == typeof(short) || typeof(T) == typeof(ushort))
- {
- size = sizeof(char);
- return true;
- }
-
- if (typeof(T) == typeof(int) || typeof(T) == typeof(uint))
- {
- size = sizeof(int);
- return true;
- }
-
- if (typeof(T) == typeof(long) || typeof(T) == typeof(ulong))
- {
- size = sizeof(long);
- return true;
- }
-
- size = default;
- return false;
- }
}
}