Skip to content

Commit

Permalink
.NET Standard 2.1 backport
Browse files Browse the repository at this point in the history
  • Loading branch information
Kir-Antipov committed Dec 10, 2023
1 parent b450737 commit 9080109
Show file tree
Hide file tree
Showing 41 changed files with 881 additions and 3,481 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<PropertyGroup>
<IsPublishable>false</IsPublishable>
<IsPackable>false</IsPackable>
<Version>1.0.0</Version>
<Version>0.1.0</Version>
<Authors>Kir_Antipov</Authors>
<ReleaseYear>2023</ReleaseYear>
<RepositoryUrl>https://github.com/Kir-Antipov/Spanned</RepositoryUrl>
Expand Down
63 changes: 51 additions & 12 deletions src/Spanned/Collections/Generic/InlineArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,58 +6,89 @@ namespace Spanned.Collections.Generic;
/// Represents an inline array with one element.
/// </summary>
/// <typeparam name="T">The type of the elements in the array.</typeparam>
[InlineArray(1)]
[StructLayout(LayoutKind.Sequential)] // Like it's gonna help...
internal struct InlineArray1<T>
{
/// <summary>
/// The reference to the first element.
/// </summary>
private T? _element0;
private T _element0;

/// <summary>
/// Initializes a new instance of the <see cref="InlineArray1{T}"/> struct with the specified elements.
/// </summary>
/// <inheritdoc cref="InlineArray3{T}(T, T, T)"/>
public InlineArray1(T arg0)
{
this[0] = arg0;
_element0 = arg0;
}

/// <summary>
/// Implicitly converts an <see cref="InlineArray1{T}"/> to a <see cref="ReadOnlySpan{T}"/>.
/// </summary>
/// <param name="inlineArray">The <see cref="InlineArray1{T}"/> to convert.</param>
/// <returns>A <see cref="ReadOnlySpan{T}"/> representing the elements of the <see cref="InlineArray1{T}"/>.</returns>
public static implicit operator ReadOnlySpan<T>(in InlineArray1<T> inlineArray)
=> MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef(in inlineArray._element0), 1);
}

/// <summary>
/// Represents an inline array with two elements.
/// </summary>
/// <typeparam name="T">The type of the elements in the array.</typeparam>
[InlineArray(2)]
[StructLayout(LayoutKind.Sequential)] // Like it's gonna help...
internal struct InlineArray2<T>
{
/// <summary>
/// The reference to the first element.
/// </summary>
private T? _element0;
private T _element0;

/// <summary>
/// The reference to the second element.
/// </summary>
private T _element1;

/// <summary>
/// Initializes a new instance of the <see cref="InlineArray2{T}"/> struct with the specified elements.
/// </summary>
/// <inheritdoc cref="InlineArray3{T}(T, T, T)"/>
public InlineArray2(T arg0, T arg1)
{
this[0] = arg0;
this[1] = arg1;
_element0 = arg0;
_element1 = arg1;
}

/// <summary>
/// Implicitly converts an <see cref="InlineArray2{T}"/> to a <see cref="ReadOnlySpan{T}"/>.
/// </summary>
/// <param name="inlineArray">The <see cref="InlineArray2{T}"/> to convert.</param>
/// <returns>A <see cref="ReadOnlySpan{T}"/> representing the elements of the <see cref="InlineArray2{T}"/>.</returns>
public static implicit operator ReadOnlySpan<T>(in InlineArray2<T> inlineArray)
=> MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef(in inlineArray._element0), 2);
}

/// <summary>
/// Represents an inline array with three elements.
/// </summary>
/// <typeparam name="T">The type of the elements in the array.</typeparam>
[InlineArray(3)]
[StructLayout(LayoutKind.Sequential)] // Like it's gonna help...
internal struct InlineArray3<T>
{
/// <summary>
/// The reference to the first element.
/// </summary>
private T? _element0;
private T _element0;

/// <summary>
/// The reference to the second element.
/// </summary>
private T _element1;

/// <summary>
/// The reference to the third element.
/// </summary>
private T _element2;

/// <summary>
/// Initializes a new instance of the <see cref="InlineArray3{T}"/> struct with the specified elements.
Expand All @@ -67,10 +98,18 @@ internal struct InlineArray3<T>
/// <param name="arg2">The third element.</param>
public InlineArray3(T arg0, T arg1, T arg2)
{
this[0] = arg0;
this[1] = arg1;
this[2] = arg2;
_element0 = arg0;
_element1 = arg1;
_element2 = arg2;
}

/// <summary>
/// Implicitly converts an <see cref="InlineArray3{T}"/> to a <see cref="ReadOnlySpan{T}"/>.
/// </summary>
/// <param name="inlineArray">The <see cref="InlineArray3{T}"/> to convert.</param>
/// <returns>A <see cref="ReadOnlySpan{T}"/> representing the elements of the <see cref="InlineArray3{T}"/>.</returns>
public static implicit operator ReadOnlySpan<T>(in InlineArray3<T> inlineArray)
=> MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef(in inlineArray._element0), 3);
}

#pragma warning restore CA1823, CS0169, IDE0044, IDE0051 // `_element0` is used by the compiler.
30 changes: 16 additions & 14 deletions src/Spanned/Collections/Generic/ValueEnumerable.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System.Collections;

namespace Spanned.Collections.Generic;

/// <summary>
Expand Down Expand Up @@ -45,19 +47,6 @@ public ValueEnumerable(T[]? array)
_span = new(array);
}

/// <summary>
/// Initializes a new instance of the <see cref="ValueEnumerable{T}"/> struct.
/// </summary>
/// <param name="list">
/// The list to create the <see cref="ValueEnumerable{T}"/> from.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ValueEnumerable(List<T>? list)
{
_enumerable = null;
_span = CollectionsMarshal.AsSpan(list);
}

/// <summary>
/// Initializes a new instance of the <see cref="ValueEnumerable{T}"/> struct.
/// </summary>
Expand Down Expand Up @@ -294,6 +283,19 @@ public static bool TryGetNonEnumeratedCount<TSource>(this scoped ValueEnumerable
return true;
}

return source._enumerable.TryGetNonEnumeratedCount(out count);
if (source._enumerable is ICollection<TSource> collection)
{
count = collection.Count;
return true;
}

if (source._enumerable is ICollection nonGenericCollection)
{
count = nonGenericCollection.Count;
return true;
}

count = 0;
return false;
}
}
14 changes: 5 additions & 9 deletions src/Spanned/Collections/ValueBitArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal readonly ref struct ValueBitArray
/// <summary>
/// The reference to the start of the <see cref="ValueBitArray"/>.
/// </summary>
private readonly ref int _start;
private readonly Span<int> _ints;

/// <summary>
/// The number of bits contained in the <see cref="ValueBitArray"/>.
Expand All @@ -36,7 +36,7 @@ public ValueBitArray(Span<byte> bytes)
/// <param name="ints">The span of <see cref="int"/>s to create a bit array from.</param>
public ValueBitArray(Span<int> ints)
{
_start = ref MemoryMarshal.GetReference(ints);
_ints = ints;
_length = checked(ints.Length * BitsPerInt32);
}

Expand Down Expand Up @@ -93,7 +93,7 @@ public bool this[int index]
uint bitIndex = (uint)index % BitsPerInt32;
int bitMask = 1 << (int)bitIndex;

ref int intValue = ref Unsafe.Add(ref _start, (nint)intIndex);
ref int intValue = ref Unsafe.Add(ref MemoryMarshal.GetReference(_ints), (nint)intIndex);
intValue = value ? (intValue | bitMask) : (intValue & ~bitMask);
}

Expand All @@ -106,18 +106,14 @@ public bool this[int index]
uint bitIndex = (uint)index % BitsPerInt32;
int bitMask = 1 << (int)bitIndex;

return (Unsafe.Add(ref _start, (nint)intIndex) & bitMask) != 0;
return (Unsafe.Add(ref MemoryMarshal.GetReference(_ints), (nint)intIndex) & bitMask) != 0;
}
}

/// <summary>
/// Clears all the bits in the bit array.
/// </summary>
public void Clear()
{
Span<int> bytes = MemoryMarshal.CreateSpan(ref _start, _length / BitsPerInt32);
bytes.Clear();
}
public void Clear() => _ints.Clear();

/// <summary>
/// Converts this instance to a boolean array.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace System.Diagnostics.CodeAnalysis;

[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
internal sealed class StringSyntaxAttribute : Attribute
{
public StringSyntaxAttribute(string syntax)
{
Syntax = syntax;
Arguments = Array.Empty<object?>();
}

public StringSyntaxAttribute(string syntax, params object?[] arguments)
{
Syntax = syntax;
Arguments = arguments;
}

public string Syntax { get; }

public object?[] Arguments { get; }

public const string CompositeFormat = nameof(CompositeFormat);
}
25 changes: 25 additions & 0 deletions src/Spanned/Compat/System/Numerics/ByteNumber.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace System.Numerics;

internal readonly struct ByteNumber : INumber<byte>
{
public byte MinValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => byte.MinValue;
}

public byte MaxValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => byte.MaxValue;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte Add(byte left, byte right) => (byte)(left + right);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte AddChecked(byte left, byte right) => checked((byte)(left + right));

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsNegative(byte value) => false;
}
25 changes: 25 additions & 0 deletions src/Spanned/Compat/System/Numerics/DecimalNumber.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace System.Numerics;

internal readonly struct DecimalNumber : INumber<decimal>
{
public decimal MinValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => decimal.MinValue;
}

public decimal MaxValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => decimal.MaxValue;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public decimal Add(decimal left, decimal right) => left + right;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public decimal AddChecked(decimal left, decimal right) => left + right;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsNegative(decimal value) => value < 0m;
}
25 changes: 25 additions & 0 deletions src/Spanned/Compat/System/Numerics/DoubleNumber.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace System.Numerics;

internal readonly struct DoubleNumber : INumber<double>
{
public double MinValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => double.MinValue;
}

public double MaxValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => double.MaxValue;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public double Add(double left, double right) => left + right;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public double AddChecked(double left, double right) => left + right;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsNegative(double value) => value < 0d;
}
14 changes: 14 additions & 0 deletions src/Spanned/Compat/System/Numerics/INumber.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace System.Numerics;

internal interface INumber<T> where T : struct
{
T MinValue { get; }

T MaxValue { get; }

bool IsNegative(T value);

T Add(T left, T right);

T AddChecked(T left, T right);
}
25 changes: 25 additions & 0 deletions src/Spanned/Compat/System/Numerics/Int16Number.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace System.Numerics;

internal readonly struct Int16Number : INumber<short>
{
public short MinValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => short.MinValue;
}

public short MaxValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => short.MaxValue;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public short Add(short left, short right) => (short)(left + right);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public short AddChecked(short left, short right) => checked((short)(left + right));

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsNegative(short value) => value < (short)0;
}
25 changes: 25 additions & 0 deletions src/Spanned/Compat/System/Numerics/Int32Number.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace System.Numerics;

internal readonly struct Int32Number : INumber<int>
{
public int MinValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => int.MinValue;
}

public int MaxValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => int.MaxValue;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Add(int left, int right) => left + right;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int AddChecked(int left, int right) => checked(left + right);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsNegative(int value) => value < 0;
}
Loading

0 comments on commit 9080109

Please sign in to comment.