diff --git a/apiCount.include.md b/apiCount.include.md index 5712bcdc..8fa93ace 100644 --- a/apiCount.include.md +++ b/apiCount.include.md @@ -1,19 +1,19 @@ -**API count: 1119** +**API count: 1139** ### Per Target Framework | Target | APIs | | -- | -- | -| `net461` | 1038 | -| `net462` | 1038 | -| `net47` | 1037 | -| `net471` | 1036 | -| `net472` | 1032 | -| `net48` | 1032 | -| `net481` | 1032 | -| `netstandard2.0` | 1034 | +| `net461` | 1058 | +| `net462` | 1058 | +| `net47` | 1057 | +| `net471` | 1056 | +| `net472` | 1052 | +| `net48` | 1052 | +| `net481` | 1052 | +| `netstandard2.0` | 1054 | | `netstandard2.1` | 887 | -| `netcoreapp2.0` | 957 | +| `netcoreapp2.0` | 977 | | `netcoreapp2.1` | 898 | | `netcoreapp2.2` | 898 | | `netcoreapp3.0` | 859 | @@ -25,4 +25,4 @@ | `net9.0` | 238 | | `net10.0` | 182 | | `net11.0` | 58 | -| `uap10.0` | 1024 | +| `uap10.0` | 1044 | diff --git a/api_list.include.md b/api_list.include.md index d05b43d2..d1ceac91 100644 --- a/api_list.include.md +++ b/api_list.include.md @@ -98,12 +98,32 @@ * `float Int32BitsToSingle(int)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.int32bitstosingle?view=net-11.0) * `int SingleToInt32Bits(float)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.singletoint32bits?view=net-11.0) * `uint SingleToUInt32Bits(float)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.singletouint32bits?view=net-11.0) + * `bool ToBoolean(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toboolean?view=net-11.0#system-bitconverter-toboolean(system-readonlyspan((system-byte)))) + * `char ToChar(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.tochar?view=net-11.0#system-bitconverter-tochar(system-readonlyspan((system-byte)))) + * `double ToDouble(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.todouble?view=net-11.0#system-bitconverter-todouble(system-readonlyspan((system-byte)))) * `Int128 ToInt128(byte[], int)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toint128?view=net-11.0#system-bitconverter-toint128(system-byte()-system-int32)) * `Int128 ToInt128(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toint128?view=net-11.0#system-bitconverter-toint128(system-readonlyspan((system-byte)))) + * `short ToInt16(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toint16?view=net-11.0#system-bitconverter-toint16(system-readonlyspan((system-byte)))) + * `int ToInt32(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toint32?view=net-11.0#system-bitconverter-toint32(system-readonlyspan((system-byte)))) + * `long ToInt64(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toint64?view=net-11.0#system-bitconverter-toint64(system-readonlyspan((system-byte)))) + * `float ToSingle(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.tosingle?view=net-11.0#system-bitconverter-tosingle(system-readonlyspan((system-byte)))) * `UInt128 ToUInt128(byte[], int)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint128?view=net-11.0#system-bitconverter-touint128(system-byte()-system-int32)) * `UInt128 ToUInt128(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint128?view=net-11.0#system-bitconverter-touint128(system-readonlyspan((system-byte)))) + * `ushort ToUInt16(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint16?view=net-11.0#system-bitconverter-touint16(system-readonlyspan((system-byte)))) + * `uint ToUInt32(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint32?view=net-11.0#system-bitconverter-touint32(system-readonlyspan((system-byte)))) + * `ulong ToUInt64(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint64?view=net-11.0#system-bitconverter-touint64(system-readonlyspan((system-byte)))) + * `bool TryWriteBytes(Span, bool)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-boolean)) + * `bool TryWriteBytes(Span, char)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-char)) + * `bool TryWriteBytes(Span, double)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-double)) + * `bool TryWriteBytes(Span, float)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-single)) + * `bool TryWriteBytes(Span, int)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-int32)) * `bool TryWriteBytes(Span, Int128)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-int128)) + * `bool TryWriteBytes(Span, long)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-int64)) + * `bool TryWriteBytes(Span, short)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-int16)) + * `bool TryWriteBytes(Span, uint)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-uint32)) * `bool TryWriteBytes(Span, UInt128)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-uint128)) + * `bool TryWriteBytes(Span, ulong)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-uint64)) + * `bool TryWriteBytes(Span, ushort)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-uint16)) * `float UInt32BitsToSingle(uint)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.uint32bitstosingle?view=net-11.0) * `double UInt64BitsToDouble(ulong)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.uint64bitstodouble?view=net-11.0) diff --git a/assemblySize.include.md b/assemblySize.include.md index 91d26394..637aa729 100644 --- a/assemblySize.include.md +++ b/assemblySize.include.md @@ -2,16 +2,16 @@ | | Empty Assembly | With Polyfill | Diff | Ensure | ArgumentExceptions | StringInterpolation | Nullability | |----------------|----------------|---------------|-----------|-----------|--------------------|---------------------|-------------| -| netstandard2.0 | 8.0KB | 371.5KB | +363.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| netstandard2.0 | 8.0KB | 373.5KB | +365.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | | netstandard2.1 | 8.5KB | 327.0KB | +318.5KB | +8.5KB | +6.5KB | +8.5KB | +13.5KB | -| net461 | 8.5KB | 370.0KB | +361.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | -| net462 | 7.0KB | 375.0KB | +368.0KB | +7.5KB | +6.5KB | +7.5KB | +12.0KB | -| net47 | 7.0KB | 375.0KB | +368.0KB | +7.5KB | +6.5KB | +7.5KB | +12.0KB | -| net471 | 8.5KB | 372.5KB | +364.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | -| net472 | 8.5KB | 371.5KB | +363.0KB | +8.5KB | +6.5KB | +9.0KB | +13.0KB | -| net48 | 8.5KB | 371.5KB | +363.0KB | +8.5KB | +6.5KB | +9.0KB | +13.0KB | -| net481 | 8.5KB | 371.5KB | +363.0KB | +8.5KB | +6.5KB | +9.0KB | +13.0KB | -| netcoreapp2.0 | 9.0KB | 350.5KB | +341.5KB | +7.5KB | +6.5KB | +9.0KB | +13.5KB | +| net461 | 8.5KB | 372.5KB | +364.0KB | +8.5KB | +6.0KB | +8.5KB | +13.0KB | +| net462 | 7.0KB | 377.5KB | +370.5KB | +7.0KB | +6.5KB | +7.5KB | +11.5KB | +| net47 | 7.0KB | 377.0KB | +370.0KB | +7.5KB | +6.5KB | +7.5KB | +12.0KB | +| net471 | 8.5KB | 374.5KB | +366.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| net472 | 8.5KB | 373.5KB | +365.0KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | +| net48 | 8.5KB | 373.5KB | +365.0KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | +| net481 | 8.5KB | 373.5KB | +365.0KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | +| netcoreapp2.0 | 9.0KB | 352.5KB | +343.5KB | +7.5KB | +6.5KB | +9.0KB | +12.0KB | | netcoreapp2.1 | 9.0KB | 330.5KB | +321.5KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | | netcoreapp2.2 | 9.0KB | 330.5KB | +321.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | | netcoreapp3.0 | 9.5KB | 326.5KB | +317.0KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | @@ -19,7 +19,7 @@ | net5.0 | 9.5KB | 288.5KB | +279.0KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | | net6.0 | 10.0KB | 230.0KB | +220.0KB | +10.0KB | +7.0KB | +1.0KB | +3.5KB | | net7.0 | 10.0KB | 199.0KB | +189.0KB | +9.0KB | +5.5KB | +512bytes | +3.0KB | -| net8.0 | 9.5KB | 168.5KB | +159.0KB | +8.5KB | +512bytes | +1.0KB | +3.5KB | +| net8.0 | 9.5KB | 169.0KB | +159.5KB | +8.0KB | | +512bytes | +3.0KB | | net9.0 | 9.5KB | 116.0KB | +106.5KB | +8.0KB | | +512bytes | +3.0KB | | net10.0 | 10.0KB | 93.5KB | +83.5KB | +8.5KB | | +512bytes | +3.0KB | | net11.0 | 10.0KB | 21.0KB | +11.0KB | +9.0KB | | +512bytes | +3.5KB | @@ -29,16 +29,16 @@ | | Empty Assembly | With Polyfill | Diff | Ensure | ArgumentExceptions | StringInterpolation | Nullability | |----------------|----------------|---------------|-----------|-----------|--------------------|---------------------|-------------| -| netstandard2.0 | 8.0KB | 544.9KB | +536.9KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| netstandard2.0 | 8.0KB | 547.4KB | +539.4KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | | netstandard2.1 | 8.5KB | 473.8KB | +465.3KB | +16.2KB | +8.2KB | +13.4KB | +18.9KB | -| net461 | 8.5KB | 544.5KB | +536.0KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | -| net462 | 7.0KB | 549.5KB | +542.5KB | +15.2KB | +8.2KB | +12.4KB | +17.4KB | -| net47 | 7.0KB | 549.2KB | +542.2KB | +15.2KB | +8.2KB | +12.4KB | +17.4KB | -| net471 | 8.5KB | 546.4KB | +537.9KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | -| net472 | 8.5KB | 544.3KB | +535.8KB | +16.2KB | +8.2KB | +13.9KB | +18.4KB | -| net48 | 8.5KB | 544.3KB | +535.8KB | +16.2KB | +8.2KB | +13.9KB | +18.4KB | -| net481 | 8.5KB | 544.3KB | +535.8KB | +16.2KB | +8.2KB | +13.9KB | +18.4KB | -| netcoreapp2.0 | 9.0KB | 513.4KB | +504.4KB | +15.2KB | +8.2KB | +13.9KB | +18.9KB | +| net461 | 8.5KB | 547.5KB | +539.0KB | +16.2KB | +7.7KB | +13.4KB | +18.4KB | +| net462 | 7.0KB | 552.5KB | +545.5KB | +14.7KB | +8.2KB | +12.4KB | +16.9KB | +| net47 | 7.0KB | 551.7KB | +544.7KB | +15.2KB | +8.2KB | +12.4KB | +17.4KB | +| net471 | 8.5KB | 548.9KB | +540.4KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| net472 | 8.5KB | 546.8KB | +538.3KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | +| net48 | 8.5KB | 546.8KB | +538.3KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | +| net481 | 8.5KB | 546.8KB | +538.3KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | +| netcoreapp2.0 | 9.0KB | 515.9KB | +506.9KB | +15.2KB | +8.2KB | +13.9KB | +17.4KB | | netcoreapp2.1 | 9.0KB | 481.0KB | +472.0KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | | netcoreapp2.2 | 9.0KB | 481.0KB | +472.0KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | | netcoreapp3.0 | 9.5KB | 470.3KB | +460.8KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | @@ -46,7 +46,7 @@ | net5.0 | 9.5KB | 414.2KB | +404.7KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | | net6.0 | 10.0KB | 335.8KB | +325.8KB | +17.7KB | +8.7KB | +1.6KB | +4.2KB | | net7.0 | 10.0KB | 287.9KB | +277.9KB | +16.6KB | +6.9KB | +1.1KB | +3.7KB | -| net8.0 | 9.5KB | 243.6KB | +234.1KB | +16.0KB | +811bytes | +1.6KB | +4.2KB | +| net8.0 | 9.5KB | 244.1KB | +234.6KB | +15.5KB | +299bytes | +1.1KB | +3.7KB | | net9.0 | 9.5KB | 167.6KB | +158.1KB | +15.5KB | | +1.1KB | +3.7KB | | net10.0 | 10.0KB | 136.1KB | +126.1KB | +16.0KB | | +1.1KB | +3.7KB | | net11.0 | 10.0KB | 30.9KB | +20.9KB | +16.5KB | | +1.1KB | +4.2KB | diff --git a/readme.md b/readme.md index e296f168..755f878c 100644 --- a/readme.md +++ b/readme.md @@ -13,22 +13,22 @@ The package targets `netstandard2.0` and is designed to support the following ru * `uap10` -**API count: 1119** +**API count: 1139** ### Per Target Framework | Target | APIs | | -- | -- | -| `net461` | 1038 | -| `net462` | 1038 | -| `net47` | 1037 | -| `net471` | 1036 | -| `net472` | 1032 | -| `net48` | 1032 | -| `net481` | 1032 | -| `netstandard2.0` | 1034 | +| `net461` | 1058 | +| `net462` | 1058 | +| `net47` | 1057 | +| `net471` | 1056 | +| `net472` | 1052 | +| `net48` | 1052 | +| `net481` | 1052 | +| `netstandard2.0` | 1054 | | `netstandard2.1` | 887 | -| `netcoreapp2.0` | 957 | +| `netcoreapp2.0` | 977 | | `netcoreapp2.1` | 898 | | `netcoreapp2.2` | 898 | | `netcoreapp3.0` | 859 | @@ -40,7 +40,7 @@ The package targets `netstandard2.0` and is designed to support the following ru | `net9.0` | 238 | | `net10.0` | 182 | | `net11.0` | 58 | -| `uap10.0` | 1024 | +| `uap10.0` | 1044 | @@ -96,16 +96,16 @@ This project uses features from the newest stable SDK and C# language. As such c | | Empty Assembly | With Polyfill | Diff | Ensure | ArgumentExceptions | StringInterpolation | Nullability | |----------------|----------------|---------------|-----------|-----------|--------------------|---------------------|-------------| -| netstandard2.0 | 8.0KB | 371.5KB | +363.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| netstandard2.0 | 8.0KB | 373.5KB | +365.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | | netstandard2.1 | 8.5KB | 327.0KB | +318.5KB | +8.5KB | +6.5KB | +8.5KB | +13.5KB | -| net461 | 8.5KB | 370.0KB | +361.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | -| net462 | 7.0KB | 375.0KB | +368.0KB | +7.5KB | +6.5KB | +7.5KB | +12.0KB | -| net47 | 7.0KB | 375.0KB | +368.0KB | +7.5KB | +6.5KB | +7.5KB | +12.0KB | -| net471 | 8.5KB | 372.5KB | +364.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | -| net472 | 8.5KB | 371.5KB | +363.0KB | +8.5KB | +6.5KB | +9.0KB | +13.0KB | -| net48 | 8.5KB | 371.5KB | +363.0KB | +8.5KB | +6.5KB | +9.0KB | +13.0KB | -| net481 | 8.5KB | 371.5KB | +363.0KB | +8.5KB | +6.5KB | +9.0KB | +13.0KB | -| netcoreapp2.0 | 9.0KB | 350.5KB | +341.5KB | +7.5KB | +6.5KB | +9.0KB | +13.5KB | +| net461 | 8.5KB | 372.5KB | +364.0KB | +8.5KB | +6.0KB | +8.5KB | +13.0KB | +| net462 | 7.0KB | 377.5KB | +370.5KB | +7.0KB | +6.5KB | +7.5KB | +11.5KB | +| net47 | 7.0KB | 377.0KB | +370.0KB | +7.5KB | +6.5KB | +7.5KB | +12.0KB | +| net471 | 8.5KB | 374.5KB | +366.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| net472 | 8.5KB | 373.5KB | +365.0KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | +| net48 | 8.5KB | 373.5KB | +365.0KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | +| net481 | 8.5KB | 373.5KB | +365.0KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | +| netcoreapp2.0 | 9.0KB | 352.5KB | +343.5KB | +7.5KB | +6.5KB | +9.0KB | +12.0KB | | netcoreapp2.1 | 9.0KB | 330.5KB | +321.5KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | | netcoreapp2.2 | 9.0KB | 330.5KB | +321.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | | netcoreapp3.0 | 9.5KB | 326.5KB | +317.0KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | @@ -113,7 +113,7 @@ This project uses features from the newest stable SDK and C# language. As such c | net5.0 | 9.5KB | 288.5KB | +279.0KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | | net6.0 | 10.0KB | 230.0KB | +220.0KB | +10.0KB | +7.0KB | +1.0KB | +3.5KB | | net7.0 | 10.0KB | 199.0KB | +189.0KB | +9.0KB | +5.5KB | +512bytes | +3.0KB | -| net8.0 | 9.5KB | 168.5KB | +159.0KB | +8.5KB | +512bytes | +1.0KB | +3.5KB | +| net8.0 | 9.5KB | 169.0KB | +159.5KB | +8.0KB | | +512bytes | +3.0KB | | net9.0 | 9.5KB | 116.0KB | +106.5KB | +8.0KB | | +512bytes | +3.0KB | | net10.0 | 10.0KB | 93.5KB | +83.5KB | +8.5KB | | +512bytes | +3.0KB | | net11.0 | 10.0KB | 21.0KB | +11.0KB | +9.0KB | | +512bytes | +3.5KB | @@ -123,16 +123,16 @@ This project uses features from the newest stable SDK and C# language. As such c | | Empty Assembly | With Polyfill | Diff | Ensure | ArgumentExceptions | StringInterpolation | Nullability | |----------------|----------------|---------------|-----------|-----------|--------------------|---------------------|-------------| -| netstandard2.0 | 8.0KB | 544.9KB | +536.9KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| netstandard2.0 | 8.0KB | 547.4KB | +539.4KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | | netstandard2.1 | 8.5KB | 473.8KB | +465.3KB | +16.2KB | +8.2KB | +13.4KB | +18.9KB | -| net461 | 8.5KB | 544.5KB | +536.0KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | -| net462 | 7.0KB | 549.5KB | +542.5KB | +15.2KB | +8.2KB | +12.4KB | +17.4KB | -| net47 | 7.0KB | 549.2KB | +542.2KB | +15.2KB | +8.2KB | +12.4KB | +17.4KB | -| net471 | 8.5KB | 546.4KB | +537.9KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | -| net472 | 8.5KB | 544.3KB | +535.8KB | +16.2KB | +8.2KB | +13.9KB | +18.4KB | -| net48 | 8.5KB | 544.3KB | +535.8KB | +16.2KB | +8.2KB | +13.9KB | +18.4KB | -| net481 | 8.5KB | 544.3KB | +535.8KB | +16.2KB | +8.2KB | +13.9KB | +18.4KB | -| netcoreapp2.0 | 9.0KB | 513.4KB | +504.4KB | +15.2KB | +8.2KB | +13.9KB | +18.9KB | +| net461 | 8.5KB | 547.5KB | +539.0KB | +16.2KB | +7.7KB | +13.4KB | +18.4KB | +| net462 | 7.0KB | 552.5KB | +545.5KB | +14.7KB | +8.2KB | +12.4KB | +16.9KB | +| net47 | 7.0KB | 551.7KB | +544.7KB | +15.2KB | +8.2KB | +12.4KB | +17.4KB | +| net471 | 8.5KB | 548.9KB | +540.4KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| net472 | 8.5KB | 546.8KB | +538.3KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | +| net48 | 8.5KB | 546.8KB | +538.3KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | +| net481 | 8.5KB | 546.8KB | +538.3KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | +| netcoreapp2.0 | 9.0KB | 515.9KB | +506.9KB | +15.2KB | +8.2KB | +13.9KB | +17.4KB | | netcoreapp2.1 | 9.0KB | 481.0KB | +472.0KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | | netcoreapp2.2 | 9.0KB | 481.0KB | +472.0KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | | netcoreapp3.0 | 9.5KB | 470.3KB | +460.8KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | @@ -140,7 +140,7 @@ This project uses features from the newest stable SDK and C# language. As such c | net5.0 | 9.5KB | 414.2KB | +404.7KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | | net6.0 | 10.0KB | 335.8KB | +325.8KB | +17.7KB | +8.7KB | +1.6KB | +4.2KB | | net7.0 | 10.0KB | 287.9KB | +277.9KB | +16.6KB | +6.9KB | +1.1KB | +3.7KB | -| net8.0 | 9.5KB | 243.6KB | +234.1KB | +16.0KB | +811bytes | +1.6KB | +4.2KB | +| net8.0 | 9.5KB | 244.1KB | +234.6KB | +15.5KB | +299bytes | +1.1KB | +3.7KB | | net9.0 | 9.5KB | 167.6KB | +158.1KB | +15.5KB | | +1.1KB | +3.7KB | | net10.0 | 10.0KB | 136.1KB | +126.1KB | +16.0KB | | +1.1KB | +3.7KB | | net11.0 | 10.0KB | 30.9KB | +20.9KB | +16.5KB | | +1.1KB | +4.2KB | @@ -713,12 +713,32 @@ The class `Polyfill` includes the following extension methods: * `float Int32BitsToSingle(int)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.int32bitstosingle?view=net-11.0) * `int SingleToInt32Bits(float)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.singletoint32bits?view=net-11.0) * `uint SingleToUInt32Bits(float)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.singletouint32bits?view=net-11.0) + * `bool ToBoolean(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toboolean?view=net-11.0#system-bitconverter-toboolean(system-readonlyspan((system-byte)))) + * `char ToChar(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.tochar?view=net-11.0#system-bitconverter-tochar(system-readonlyspan((system-byte)))) + * `double ToDouble(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.todouble?view=net-11.0#system-bitconverter-todouble(system-readonlyspan((system-byte)))) * `Int128 ToInt128(byte[], int)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toint128?view=net-11.0#system-bitconverter-toint128(system-byte()-system-int32)) * `Int128 ToInt128(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toint128?view=net-11.0#system-bitconverter-toint128(system-readonlyspan((system-byte)))) + * `short ToInt16(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toint16?view=net-11.0#system-bitconverter-toint16(system-readonlyspan((system-byte)))) + * `int ToInt32(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toint32?view=net-11.0#system-bitconverter-toint32(system-readonlyspan((system-byte)))) + * `long ToInt64(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toint64?view=net-11.0#system-bitconverter-toint64(system-readonlyspan((system-byte)))) + * `float ToSingle(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.tosingle?view=net-11.0#system-bitconverter-tosingle(system-readonlyspan((system-byte)))) * `UInt128 ToUInt128(byte[], int)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint128?view=net-11.0#system-bitconverter-touint128(system-byte()-system-int32)) * `UInt128 ToUInt128(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint128?view=net-11.0#system-bitconverter-touint128(system-readonlyspan((system-byte)))) + * `ushort ToUInt16(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint16?view=net-11.0#system-bitconverter-touint16(system-readonlyspan((system-byte)))) + * `uint ToUInt32(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint32?view=net-11.0#system-bitconverter-touint32(system-readonlyspan((system-byte)))) + * `ulong ToUInt64(ReadOnlySpan)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint64?view=net-11.0#system-bitconverter-touint64(system-readonlyspan((system-byte)))) + * `bool TryWriteBytes(Span, bool)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-boolean)) + * `bool TryWriteBytes(Span, char)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-char)) + * `bool TryWriteBytes(Span, double)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-double)) + * `bool TryWriteBytes(Span, float)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-single)) + * `bool TryWriteBytes(Span, int)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-int32)) * `bool TryWriteBytes(Span, Int128)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-int128)) + * `bool TryWriteBytes(Span, long)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-int64)) + * `bool TryWriteBytes(Span, short)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-int16)) + * `bool TryWriteBytes(Span, uint)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-uint32)) * `bool TryWriteBytes(Span, UInt128)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-uint128)) + * `bool TryWriteBytes(Span, ulong)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-uint64)) + * `bool TryWriteBytes(Span, ushort)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-uint16)) * `float UInt32BitsToSingle(uint)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.uint32bitstosingle?view=net-11.0) * `double UInt64BitsToDouble(ulong)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.uint64bitstodouble?view=net-11.0) @@ -2513,7 +2533,7 @@ void ObjectDisposedExceptionExample(bool isDisposed) ObjectDisposedException.ThrowIf(isDisposed, typeof(Consume)); } ``` -snippet source | anchor +snippet source | anchor @@ -2532,7 +2552,7 @@ void EnsureExample(Order order, Customer customer, string customerId, string ema this.quantity = Ensure.NotNegativeOrZero(quantity); } ``` -snippet source | anchor +snippet source | anchor diff --git a/src/Consume/Consume.cs b/src/Consume/Consume.cs index 2c57787c..453631fe 100644 --- a/src/Consume/Consume.cs +++ b/src/Consume/Consume.cs @@ -326,6 +326,36 @@ void Base64Usage() } #endif +#if FeatureMemory + void BitConverter_Span_Methods() + { + var source = new byte[16]; + Span destination = stackalloc byte[16]; + + var boolean = BitConverter.ToBoolean(source.AsSpan()); + var character = BitConverter.ToChar(source.AsSpan()); + var int16 = BitConverter.ToInt16(source.AsSpan()); + var int32 = BitConverter.ToInt32(source.AsSpan()); + var int64 = BitConverter.ToInt64(source.AsSpan()); + var single = BitConverter.ToSingle(source.AsSpan()); + var doubleValue = BitConverter.ToDouble(source.AsSpan()); + var uint16 = BitConverter.ToUInt16(source.AsSpan()); + var uint32 = BitConverter.ToUInt32(source.AsSpan()); + var uint64 = BitConverter.ToUInt64(source.AsSpan()); + + var wroteBoolean = BitConverter.TryWriteBytes(destination, boolean); + var wroteChar = BitConverter.TryWriteBytes(destination, character); + var wroteInt16 = BitConverter.TryWriteBytes(destination, int16); + var wroteInt32 = BitConverter.TryWriteBytes(destination, int32); + var wroteInt64 = BitConverter.TryWriteBytes(destination, int64); + var wroteSingle = BitConverter.TryWriteBytes(destination, single); + var wroteDouble = BitConverter.TryWriteBytes(destination, doubleValue); + var wroteUInt16 = BitConverter.TryWriteBytes(destination, uint16); + var wroteUInt32 = BitConverter.TryWriteBytes(destination, uint32); + var wroteUInt64 = BitConverter.TryWriteBytes(destination, uint64); + } +#endif + #if NET7_0_OR_GREATER void BitConverter_Int128_Methods() { diff --git a/src/Polyfill/Polyfill_BitConverter.cs b/src/Polyfill/Polyfill_BitConverter.cs index 954793f5..c70e3387 100644 --- a/src/Polyfill/Polyfill_BitConverter.cs +++ b/src/Polyfill/Polyfill_BitConverter.cs @@ -127,6 +127,260 @@ public static ulong DoubleToUInt64Bits(double value) #endif +#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER + + /// + /// Converts a read-only byte span into a Boolean. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toboolean?view=net-11.0#system-bitconverter-toboolean(system-readonlyspan((system-byte))) + public static bool ToBoolean(ReadOnlySpan value) + { + GuardSpan(value, 1); + return value[0] != 0; + } + + /// + /// Converts a read-only byte span into a Char. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.tochar?view=net-11.0#system-bitconverter-tochar(system-readonlyspan((system-byte))) + public static char ToChar(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + + /// + /// Converts a read-only byte span into a 16-bit signed integer. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toint16?view=net-11.0#system-bitconverter-toint16(system-readonlyspan((system-byte))) + public static short ToInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + + /// + /// Converts a read-only byte span into a 32-bit signed integer. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toint32?view=net-11.0#system-bitconverter-toint32(system-readonlyspan((system-byte))) + public static int ToInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + + /// + /// Converts a read-only byte span into a 64-bit signed integer. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.toint64?view=net-11.0#system-bitconverter-toint64(system-readonlyspan((system-byte))) + public static long ToInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + + /// + /// Converts a read-only byte span into a single-precision floating point number. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.tosingle?view=net-11.0#system-bitconverter-tosingle(system-readonlyspan((system-byte))) + public static float ToSingle(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + + /// + /// Converts a read-only byte span into a double-precision floating point number. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.todouble?view=net-11.0#system-bitconverter-todouble(system-readonlyspan((system-byte))) + public static double ToDouble(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + + /// + /// Converts a read-only byte span into a 16-bit unsigned integer. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint16?view=net-11.0#system-bitconverter-touint16(system-readonlyspan((system-byte))) + public static ushort ToUInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + + /// + /// Converts a read-only byte span into a 32-bit unsigned integer. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint32?view=net-11.0#system-bitconverter-touint32(system-readonlyspan((system-byte))) + public static uint ToUInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + + /// + /// Converts a read-only byte span into a 64-bit unsigned integer. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint64?view=net-11.0#system-bitconverter-touint64(system-readonlyspan((system-byte))) + public static ulong ToUInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + + /// + /// Converts a Boolean into a span of bytes. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-boolean) + public static bool TryWriteBytes(Span destination, bool value) + { + if (destination.Length < 1) + { + return false; + } + + destination[0] = value ? (byte) 1 : (byte) 0; + return true; + } + + /// + /// Converts a Char into a span of bytes. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-char) + public static bool TryWriteBytes(Span destination, char value) + { + if (destination.Length < 2) + { + return false; + } + + MemoryMarshal.Write(destination, ref value); + return true; + } + + /// + /// Converts a 16-bit signed integer into a span of bytes. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-int16) + public static bool TryWriteBytes(Span destination, short value) + { + if (destination.Length < 2) + { + return false; + } + + MemoryMarshal.Write(destination, ref value); + return true; + } + + /// + /// Converts a 32-bit signed integer into a span of bytes. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-int32) + public static bool TryWriteBytes(Span destination, int value) + { + if (destination.Length < 4) + { + return false; + } + + MemoryMarshal.Write(destination, ref value); + return true; + } + + /// + /// Converts a 64-bit signed integer into a span of bytes. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-int64) + public static bool TryWriteBytes(Span destination, long value) + { + if (destination.Length < 8) + { + return false; + } + + MemoryMarshal.Write(destination, ref value); + return true; + } + + /// + /// Converts a single-precision floating point number into a span of bytes. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-single) + public static bool TryWriteBytes(Span destination, float value) + { + if (destination.Length < 4) + { + return false; + } + + MemoryMarshal.Write(destination, ref value); + return true; + } + + /// + /// Converts a double-precision floating point number into a span of bytes. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-double) + public static bool TryWriteBytes(Span destination, double value) + { + if (destination.Length < 8) + { + return false; + } + + MemoryMarshal.Write(destination, ref value); + return true; + } + + /// + /// Converts a 16-bit unsigned integer into a span of bytes. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-uint16) + public static bool TryWriteBytes(Span destination, ushort value) + { + if (destination.Length < 2) + { + return false; + } + + MemoryMarshal.Write(destination, ref value); + return true; + } + + /// + /// Converts a 32-bit unsigned integer into a span of bytes. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-uint32) + public static bool TryWriteBytes(Span destination, uint value) + { + if (destination.Length < 4) + { + return false; + } + + MemoryMarshal.Write(destination, ref value); + return true; + } + + /// + /// Converts a 64-bit unsigned integer into a span of bytes. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.trywritebytes?view=net-11.0#system-bitconverter-trywritebytes(system-span((system-byte))-system-uint64) + public static bool TryWriteBytes(Span destination, ulong value) + { + if (destination.Length < 8) + { + return false; + } + + MemoryMarshal.Write(destination, ref value); + return true; + } + +#endif + #if NET7_0_OR_GREATER && !NET9_0_OR_GREATER /// @@ -282,6 +536,20 @@ static void GuardSixteenBytes(ReadOnlySpan value) #endif +#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER + + // the BCL span overloads reject a short span with a plain ArgumentOutOfRangeException + // naming value, rather than the ArgumentException the array overloads use + static void GuardSpan(ReadOnlySpan value, int size) + { + if (value.Length < size) + { + throw new ArgumentOutOfRangeException(nameof(value)); + } + } + +#endif + } #endif diff --git a/src/Split/net461/Polyfill_BitConverter.cs b/src/Split/net461/Polyfill_BitConverter.cs index 9cb85b28..5beebc7f 100644 --- a/src/Split/net461/Polyfill_BitConverter.cs +++ b/src/Split/net461/Polyfill_BitConverter.cs @@ -85,6 +85,213 @@ public static ulong DoubleToUInt64Bits(double value) { return (ulong)BitConverter.DoubleToInt64Bits(value); } + /// + /// Converts a read-only byte span into a Boolean. + /// + public static bool ToBoolean(ReadOnlySpan value) + { + GuardSpan(value, 1); + return value[0] != 0; + } + /// + /// Converts a read-only byte span into a Char. + /// + public static char ToChar(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit signed integer. + /// + public static short ToInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit signed integer. + /// + public static int ToInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit signed integer. + /// + public static long ToInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a single-precision floating point number. + /// + public static float ToSingle(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a double-precision floating point number. + /// + public static double ToDouble(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit unsigned integer. + /// + public static ushort ToUInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit unsigned integer. + /// + public static uint ToUInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit unsigned integer. + /// + public static ulong ToUInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a Boolean into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, bool value) + { + if (destination.Length < 1) + { + return false; + } + destination[0] = value ? (byte) 1 : (byte) 0; + return true; + } + /// + /// Converts a Char into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, char value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, short value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, int value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, long value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a single-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, float value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a double-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, double value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ushort value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, uint value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ulong value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + } + static void GuardSpan(ReadOnlySpan value, int size) + { + if (value.Length < size) + { + throw new ArgumentOutOfRangeException(nameof(value)); + } } } #endif diff --git a/src/Split/net462/Polyfill_BitConverter.cs b/src/Split/net462/Polyfill_BitConverter.cs index 9cb85b28..5beebc7f 100644 --- a/src/Split/net462/Polyfill_BitConverter.cs +++ b/src/Split/net462/Polyfill_BitConverter.cs @@ -85,6 +85,213 @@ public static ulong DoubleToUInt64Bits(double value) { return (ulong)BitConverter.DoubleToInt64Bits(value); } + /// + /// Converts a read-only byte span into a Boolean. + /// + public static bool ToBoolean(ReadOnlySpan value) + { + GuardSpan(value, 1); + return value[0] != 0; + } + /// + /// Converts a read-only byte span into a Char. + /// + public static char ToChar(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit signed integer. + /// + public static short ToInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit signed integer. + /// + public static int ToInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit signed integer. + /// + public static long ToInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a single-precision floating point number. + /// + public static float ToSingle(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a double-precision floating point number. + /// + public static double ToDouble(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit unsigned integer. + /// + public static ushort ToUInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit unsigned integer. + /// + public static uint ToUInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit unsigned integer. + /// + public static ulong ToUInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a Boolean into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, bool value) + { + if (destination.Length < 1) + { + return false; + } + destination[0] = value ? (byte) 1 : (byte) 0; + return true; + } + /// + /// Converts a Char into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, char value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, short value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, int value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, long value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a single-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, float value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a double-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, double value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ushort value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, uint value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ulong value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + } + static void GuardSpan(ReadOnlySpan value, int size) + { + if (value.Length < size) + { + throw new ArgumentOutOfRangeException(nameof(value)); + } } } #endif diff --git a/src/Split/net47/Polyfill_BitConverter.cs b/src/Split/net47/Polyfill_BitConverter.cs index 9cb85b28..5beebc7f 100644 --- a/src/Split/net47/Polyfill_BitConverter.cs +++ b/src/Split/net47/Polyfill_BitConverter.cs @@ -85,6 +85,213 @@ public static ulong DoubleToUInt64Bits(double value) { return (ulong)BitConverter.DoubleToInt64Bits(value); } + /// + /// Converts a read-only byte span into a Boolean. + /// + public static bool ToBoolean(ReadOnlySpan value) + { + GuardSpan(value, 1); + return value[0] != 0; + } + /// + /// Converts a read-only byte span into a Char. + /// + public static char ToChar(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit signed integer. + /// + public static short ToInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit signed integer. + /// + public static int ToInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit signed integer. + /// + public static long ToInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a single-precision floating point number. + /// + public static float ToSingle(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a double-precision floating point number. + /// + public static double ToDouble(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit unsigned integer. + /// + public static ushort ToUInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit unsigned integer. + /// + public static uint ToUInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit unsigned integer. + /// + public static ulong ToUInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a Boolean into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, bool value) + { + if (destination.Length < 1) + { + return false; + } + destination[0] = value ? (byte) 1 : (byte) 0; + return true; + } + /// + /// Converts a Char into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, char value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, short value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, int value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, long value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a single-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, float value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a double-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, double value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ushort value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, uint value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ulong value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + } + static void GuardSpan(ReadOnlySpan value, int size) + { + if (value.Length < size) + { + throw new ArgumentOutOfRangeException(nameof(value)); + } } } #endif diff --git a/src/Split/net471/Polyfill_BitConverter.cs b/src/Split/net471/Polyfill_BitConverter.cs index 9cb85b28..5beebc7f 100644 --- a/src/Split/net471/Polyfill_BitConverter.cs +++ b/src/Split/net471/Polyfill_BitConverter.cs @@ -85,6 +85,213 @@ public static ulong DoubleToUInt64Bits(double value) { return (ulong)BitConverter.DoubleToInt64Bits(value); } + /// + /// Converts a read-only byte span into a Boolean. + /// + public static bool ToBoolean(ReadOnlySpan value) + { + GuardSpan(value, 1); + return value[0] != 0; + } + /// + /// Converts a read-only byte span into a Char. + /// + public static char ToChar(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit signed integer. + /// + public static short ToInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit signed integer. + /// + public static int ToInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit signed integer. + /// + public static long ToInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a single-precision floating point number. + /// + public static float ToSingle(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a double-precision floating point number. + /// + public static double ToDouble(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit unsigned integer. + /// + public static ushort ToUInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit unsigned integer. + /// + public static uint ToUInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit unsigned integer. + /// + public static ulong ToUInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a Boolean into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, bool value) + { + if (destination.Length < 1) + { + return false; + } + destination[0] = value ? (byte) 1 : (byte) 0; + return true; + } + /// + /// Converts a Char into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, char value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, short value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, int value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, long value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a single-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, float value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a double-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, double value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ushort value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, uint value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ulong value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + } + static void GuardSpan(ReadOnlySpan value, int size) + { + if (value.Length < size) + { + throw new ArgumentOutOfRangeException(nameof(value)); + } } } #endif diff --git a/src/Split/net472/Polyfill_BitConverter.cs b/src/Split/net472/Polyfill_BitConverter.cs index 9cb85b28..5beebc7f 100644 --- a/src/Split/net472/Polyfill_BitConverter.cs +++ b/src/Split/net472/Polyfill_BitConverter.cs @@ -85,6 +85,213 @@ public static ulong DoubleToUInt64Bits(double value) { return (ulong)BitConverter.DoubleToInt64Bits(value); } + /// + /// Converts a read-only byte span into a Boolean. + /// + public static bool ToBoolean(ReadOnlySpan value) + { + GuardSpan(value, 1); + return value[0] != 0; + } + /// + /// Converts a read-only byte span into a Char. + /// + public static char ToChar(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit signed integer. + /// + public static short ToInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit signed integer. + /// + public static int ToInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit signed integer. + /// + public static long ToInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a single-precision floating point number. + /// + public static float ToSingle(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a double-precision floating point number. + /// + public static double ToDouble(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit unsigned integer. + /// + public static ushort ToUInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit unsigned integer. + /// + public static uint ToUInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit unsigned integer. + /// + public static ulong ToUInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a Boolean into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, bool value) + { + if (destination.Length < 1) + { + return false; + } + destination[0] = value ? (byte) 1 : (byte) 0; + return true; + } + /// + /// Converts a Char into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, char value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, short value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, int value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, long value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a single-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, float value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a double-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, double value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ushort value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, uint value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ulong value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + } + static void GuardSpan(ReadOnlySpan value, int size) + { + if (value.Length < size) + { + throw new ArgumentOutOfRangeException(nameof(value)); + } } } #endif diff --git a/src/Split/net48/Polyfill_BitConverter.cs b/src/Split/net48/Polyfill_BitConverter.cs index 9cb85b28..5beebc7f 100644 --- a/src/Split/net48/Polyfill_BitConverter.cs +++ b/src/Split/net48/Polyfill_BitConverter.cs @@ -85,6 +85,213 @@ public static ulong DoubleToUInt64Bits(double value) { return (ulong)BitConverter.DoubleToInt64Bits(value); } + /// + /// Converts a read-only byte span into a Boolean. + /// + public static bool ToBoolean(ReadOnlySpan value) + { + GuardSpan(value, 1); + return value[0] != 0; + } + /// + /// Converts a read-only byte span into a Char. + /// + public static char ToChar(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit signed integer. + /// + public static short ToInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit signed integer. + /// + public static int ToInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit signed integer. + /// + public static long ToInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a single-precision floating point number. + /// + public static float ToSingle(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a double-precision floating point number. + /// + public static double ToDouble(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit unsigned integer. + /// + public static ushort ToUInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit unsigned integer. + /// + public static uint ToUInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit unsigned integer. + /// + public static ulong ToUInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a Boolean into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, bool value) + { + if (destination.Length < 1) + { + return false; + } + destination[0] = value ? (byte) 1 : (byte) 0; + return true; + } + /// + /// Converts a Char into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, char value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, short value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, int value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, long value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a single-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, float value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a double-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, double value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ushort value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, uint value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ulong value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + } + static void GuardSpan(ReadOnlySpan value, int size) + { + if (value.Length < size) + { + throw new ArgumentOutOfRangeException(nameof(value)); + } } } #endif diff --git a/src/Split/net481/Polyfill_BitConverter.cs b/src/Split/net481/Polyfill_BitConverter.cs index 9cb85b28..5beebc7f 100644 --- a/src/Split/net481/Polyfill_BitConverter.cs +++ b/src/Split/net481/Polyfill_BitConverter.cs @@ -85,6 +85,213 @@ public static ulong DoubleToUInt64Bits(double value) { return (ulong)BitConverter.DoubleToInt64Bits(value); } + /// + /// Converts a read-only byte span into a Boolean. + /// + public static bool ToBoolean(ReadOnlySpan value) + { + GuardSpan(value, 1); + return value[0] != 0; + } + /// + /// Converts a read-only byte span into a Char. + /// + public static char ToChar(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit signed integer. + /// + public static short ToInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit signed integer. + /// + public static int ToInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit signed integer. + /// + public static long ToInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a single-precision floating point number. + /// + public static float ToSingle(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a double-precision floating point number. + /// + public static double ToDouble(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit unsigned integer. + /// + public static ushort ToUInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit unsigned integer. + /// + public static uint ToUInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit unsigned integer. + /// + public static ulong ToUInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a Boolean into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, bool value) + { + if (destination.Length < 1) + { + return false; + } + destination[0] = value ? (byte) 1 : (byte) 0; + return true; + } + /// + /// Converts a Char into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, char value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, short value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, int value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, long value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a single-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, float value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a double-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, double value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ushort value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, uint value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ulong value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + } + static void GuardSpan(ReadOnlySpan value, int size) + { + if (value.Length < size) + { + throw new ArgumentOutOfRangeException(nameof(value)); + } } } #endif diff --git a/src/Split/netcoreapp2.0/Polyfill_BitConverter.cs b/src/Split/netcoreapp2.0/Polyfill_BitConverter.cs index f05be0bc..fd4cd7b8 100644 --- a/src/Split/netcoreapp2.0/Polyfill_BitConverter.cs +++ b/src/Split/netcoreapp2.0/Polyfill_BitConverter.cs @@ -41,6 +41,213 @@ public static ulong DoubleToUInt64Bits(double value) { return (ulong)BitConverter.DoubleToInt64Bits(value); } + /// + /// Converts a read-only byte span into a Boolean. + /// + public static bool ToBoolean(ReadOnlySpan value) + { + GuardSpan(value, 1); + return value[0] != 0; + } + /// + /// Converts a read-only byte span into a Char. + /// + public static char ToChar(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit signed integer. + /// + public static short ToInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit signed integer. + /// + public static int ToInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit signed integer. + /// + public static long ToInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a single-precision floating point number. + /// + public static float ToSingle(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a double-precision floating point number. + /// + public static double ToDouble(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit unsigned integer. + /// + public static ushort ToUInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit unsigned integer. + /// + public static uint ToUInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit unsigned integer. + /// + public static ulong ToUInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a Boolean into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, bool value) + { + if (destination.Length < 1) + { + return false; + } + destination[0] = value ? (byte) 1 : (byte) 0; + return true; + } + /// + /// Converts a Char into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, char value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, short value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, int value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, long value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a single-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, float value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a double-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, double value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ushort value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, uint value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ulong value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + } + static void GuardSpan(ReadOnlySpan value, int size) + { + if (value.Length < size) + { + throw new ArgumentOutOfRangeException(nameof(value)); + } } } #endif diff --git a/src/Split/netstandard2.0/Polyfill_BitConverter.cs b/src/Split/netstandard2.0/Polyfill_BitConverter.cs index 9cb85b28..5beebc7f 100644 --- a/src/Split/netstandard2.0/Polyfill_BitConverter.cs +++ b/src/Split/netstandard2.0/Polyfill_BitConverter.cs @@ -85,6 +85,213 @@ public static ulong DoubleToUInt64Bits(double value) { return (ulong)BitConverter.DoubleToInt64Bits(value); } + /// + /// Converts a read-only byte span into a Boolean. + /// + public static bool ToBoolean(ReadOnlySpan value) + { + GuardSpan(value, 1); + return value[0] != 0; + } + /// + /// Converts a read-only byte span into a Char. + /// + public static char ToChar(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit signed integer. + /// + public static short ToInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit signed integer. + /// + public static int ToInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit signed integer. + /// + public static long ToInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a single-precision floating point number. + /// + public static float ToSingle(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a double-precision floating point number. + /// + public static double ToDouble(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit unsigned integer. + /// + public static ushort ToUInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit unsigned integer. + /// + public static uint ToUInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit unsigned integer. + /// + public static ulong ToUInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a Boolean into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, bool value) + { + if (destination.Length < 1) + { + return false; + } + destination[0] = value ? (byte) 1 : (byte) 0; + return true; + } + /// + /// Converts a Char into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, char value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, short value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, int value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, long value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a single-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, float value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a double-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, double value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ushort value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, uint value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ulong value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + } + static void GuardSpan(ReadOnlySpan value, int size) + { + if (value.Length < size) + { + throw new ArgumentOutOfRangeException(nameof(value)); + } } } #endif diff --git a/src/Split/uap10.0/Polyfill_BitConverter.cs b/src/Split/uap10.0/Polyfill_BitConverter.cs index 9cb85b28..5beebc7f 100644 --- a/src/Split/uap10.0/Polyfill_BitConverter.cs +++ b/src/Split/uap10.0/Polyfill_BitConverter.cs @@ -85,6 +85,213 @@ public static ulong DoubleToUInt64Bits(double value) { return (ulong)BitConverter.DoubleToInt64Bits(value); } + /// + /// Converts a read-only byte span into a Boolean. + /// + public static bool ToBoolean(ReadOnlySpan value) + { + GuardSpan(value, 1); + return value[0] != 0; + } + /// + /// Converts a read-only byte span into a Char. + /// + public static char ToChar(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit signed integer. + /// + public static short ToInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit signed integer. + /// + public static int ToInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit signed integer. + /// + public static long ToInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a single-precision floating point number. + /// + public static float ToSingle(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a double-precision floating point number. + /// + public static double ToDouble(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 16-bit unsigned integer. + /// + public static ushort ToUInt16(ReadOnlySpan value) + { + GuardSpan(value, 2); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 32-bit unsigned integer. + /// + public static uint ToUInt32(ReadOnlySpan value) + { + GuardSpan(value, 4); + return MemoryMarshal.Read(value); + } + /// + /// Converts a read-only byte span into a 64-bit unsigned integer. + /// + public static ulong ToUInt64(ReadOnlySpan value) + { + GuardSpan(value, 8); + return MemoryMarshal.Read(value); + } + /// + /// Converts a Boolean into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, bool value) + { + if (destination.Length < 1) + { + return false; + } + destination[0] = value ? (byte) 1 : (byte) 0; + return true; + } + /// + /// Converts a Char into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, char value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, short value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, int value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit signed integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, long value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a single-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, float value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a double-precision floating point number into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, double value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 16-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ushort value) + { + if (destination.Length < 2) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 32-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, uint value) + { + if (destination.Length < 4) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + /// + /// Converts a 64-bit unsigned integer into a span of bytes. + /// + public static bool TryWriteBytes(Span destination, ulong value) + { + if (destination.Length < 8) + { + return false; + } + MemoryMarshal.Write(destination, ref value); + return true; + } + } + static void GuardSpan(ReadOnlySpan value, int size) + { + if (value.Length < size) + { + throw new ArgumentOutOfRangeException(nameof(value)); + } } } #endif diff --git a/src/Tests/BitConverterSpanTests.cs b/src/Tests/BitConverterSpanTests.cs new file mode 100644 index 00000000..1b495f1a --- /dev/null +++ b/src/Tests/BitConverterSpanTests.cs @@ -0,0 +1,177 @@ +#if FeatureMemory + +// Runs on every target, so netstandard2.1/netcoreapp2.1 and later validate the BCL and +// netstandard2.0, netcoreapp2.0 and .NET Framework validate the polyfill. +public class BitConverterSpanTests +{ + static byte[] source = BuildSource(); + + static byte[] BuildSource() + { + var bytes = new byte[24]; + for (var i = 0; i < bytes.Length; i++) + { + bytes[i] = (byte) (i + 1); + } + + return bytes; + } + + [Test] + public async Task ReadsMatchTheArrayOverloads() + { + // an odd offset, so an implementation that assumes alignment would fault or misread + foreach (var offset in new[] { 0, 1, 3, 5, 8 }) + { + await Assert.That(ReadBoolean(offset)).IsEqualTo(BitConverter.ToBoolean(source, offset)); + await Assert.That(ReadChar(offset)).IsEqualTo(BitConverter.ToChar(source, offset)); + await Assert.That(ReadInt16(offset)).IsEqualTo(BitConverter.ToInt16(source, offset)); + await Assert.That(ReadInt32(offset)).IsEqualTo(BitConverter.ToInt32(source, offset)); + await Assert.That(ReadInt64(offset)).IsEqualTo(BitConverter.ToInt64(source, offset)); + await Assert.That(ReadSingle(offset)).IsEqualTo(BitConverter.ToSingle(source, offset)); + await Assert.That(ReadDouble(offset)).IsEqualTo(BitConverter.ToDouble(source, offset)); + await Assert.That(ReadUInt16(offset)).IsEqualTo(BitConverter.ToUInt16(source, offset)); + await Assert.That(ReadUInt32(offset)).IsEqualTo(BitConverter.ToUInt32(source, offset)); + await Assert.That(ReadUInt64(offset)).IsEqualTo(BitConverter.ToUInt64(source, offset)); + } + } + + [Test] + public async Task ToBoolean_TreatsAnyNonZeroAsTrue() + { + await Assert.That(ReadBooleanOf(0)).IsFalse(); + await Assert.That(ReadBooleanOf(1)).IsTrue(); + await Assert.That(ReadBooleanOf(2)).IsTrue(); + await Assert.That(ReadBooleanOf(255)).IsTrue(); + } + + [Test] + public async Task ShortSpanThrows() + { + await Assert.That(Capture(() => ReadBoolean(source, 0))).IsEqualTo("ArgumentOutOfRangeException:value"); + await Assert.That(Capture(() => ReadChar(source, 1))).IsEqualTo("ArgumentOutOfRangeException:value"); + await Assert.That(Capture(() => ReadInt16(source, 1))).IsEqualTo("ArgumentOutOfRangeException:value"); + await Assert.That(Capture(() => ReadInt32(source, 3))).IsEqualTo("ArgumentOutOfRangeException:value"); + await Assert.That(Capture(() => ReadInt64(source, 7))).IsEqualTo("ArgumentOutOfRangeException:value"); + await Assert.That(Capture(() => ReadSingle(source, 3))).IsEqualTo("ArgumentOutOfRangeException:value"); + await Assert.That(Capture(() => ReadDouble(source, 7))).IsEqualTo("ArgumentOutOfRangeException:value"); + await Assert.That(Capture(() => ReadUInt16(source, 1))).IsEqualTo("ArgumentOutOfRangeException:value"); + await Assert.That(Capture(() => ReadUInt32(source, 3))).IsEqualTo("ArgumentOutOfRangeException:value"); + await Assert.That(Capture(() => ReadUInt64(source, 7))).IsEqualTo("ArgumentOutOfRangeException:value"); + + // exactly enough is accepted + await Assert.That(Capture(() => ReadInt32(source, 4))).IsEqualTo("none"); + await Assert.That(Capture(() => ReadInt64(source, 8))).IsEqualTo("none"); + } + + [Test] + public async Task TryWriteBytes_MatchesGetBytesAndSizing() + { + await Check(1, BitConverter.GetBytes(true), (buffer, _) => BitConverter.TryWriteBytes(buffer, true)); + await Check(2, BitConverter.GetBytes('A'), (buffer, _) => BitConverter.TryWriteBytes(buffer, 'A')); + await Check(2, BitConverter.GetBytes((short) 0x1234), (buffer, _) => BitConverter.TryWriteBytes(buffer, (short) 0x1234)); + await Check(4, BitConverter.GetBytes(0x12345678), (buffer, _) => BitConverter.TryWriteBytes(buffer, 0x12345678)); + await Check(8, BitConverter.GetBytes(0x1122334455667788L), (buffer, _) => BitConverter.TryWriteBytes(buffer, 0x1122334455667788L)); + await Check(4, BitConverter.GetBytes(1.5f), (buffer, _) => BitConverter.TryWriteBytes(buffer, 1.5f)); + await Check(8, BitConverter.GetBytes(1.5d), (buffer, _) => BitConverter.TryWriteBytes(buffer, 1.5d)); + await Check(2, BitConverter.GetBytes((ushort) 0xABCD), (buffer, _) => BitConverter.TryWriteBytes(buffer, (ushort) 0xABCD)); + await Check(4, BitConverter.GetBytes(0xDEADBEEFu), (buffer, _) => BitConverter.TryWriteBytes(buffer, 0xDEADBEEFu)); + await Check(8, BitConverter.GetBytes(0xFEEDFACECAFEBEEFuL), (buffer, _) => BitConverter.TryWriteBytes(buffer, 0xFEEDFACECAFEBEEFuL)); + } + + static async Task Check(int width, byte[] expected, Func write) + { + // one byte short: refused, and the destination is left alone + var small = Filled(width - 1); + var smallOk = write(small, 0); + await Assert.That(smallOk).IsFalse(); + await Assert.That(AllFill(small)).IsTrue(); + + var exact = Filled(width); + var exactOk = write(exact, 0); + await Assert.That(exactOk).IsTrue(); + await Assert.That(Hex(exact)).IsEqualTo(Hex(expected)); + + // a larger destination is written only up to the width of the value + var larger = Filled(width + 1); + var largerOk = write(larger, 0); + await Assert.That(largerOk).IsTrue(); + await Assert.That(Hex(larger)).IsEqualTo(Hex(expected) + "aa"); + } + + static byte[] Filled(int size) + { + var buffer = new byte[size]; + for (var i = 0; i < size; i++) + { + buffer[i] = 0xAA; + } + + return buffer; + } + + static bool AllFill(byte[] buffer) + { + foreach (var b in buffer) + { + if (b != 0xAA) + { + return false; + } + } + + return true; + } + + // the spans stay inside these helpers, so nothing ref struct shaped lives across an await + static bool ReadBoolean(int offset) => BitConverter.ToBoolean(source.AsSpan(offset)); + static char ReadChar(int offset) => BitConverter.ToChar(source.AsSpan(offset)); + static short ReadInt16(int offset) => BitConverter.ToInt16(source.AsSpan(offset)); + static int ReadInt32(int offset) => BitConverter.ToInt32(source.AsSpan(offset)); + static long ReadInt64(int offset) => BitConverter.ToInt64(source.AsSpan(offset)); + static float ReadSingle(int offset) => BitConverter.ToSingle(source.AsSpan(offset)); + static double ReadDouble(int offset) => BitConverter.ToDouble(source.AsSpan(offset)); + static ushort ReadUInt16(int offset) => BitConverter.ToUInt16(source.AsSpan(offset)); + static uint ReadUInt32(int offset) => BitConverter.ToUInt32(source.AsSpan(offset)); + static ulong ReadUInt64(int offset) => BitConverter.ToUInt64(source.AsSpan(offset)); + + // read from the tail of the buffer so that only `length` bytes remain + static bool ReadBoolean(byte[] buffer, int length) => BitConverter.ToBoolean(buffer.AsSpan(buffer.Length - length, length)); + static char ReadChar(byte[] buffer, int length) => BitConverter.ToChar(buffer.AsSpan(buffer.Length - length, length)); + static short ReadInt16(byte[] buffer, int length) => BitConverter.ToInt16(buffer.AsSpan(buffer.Length - length, length)); + static int ReadInt32(byte[] buffer, int length) => BitConverter.ToInt32(buffer.AsSpan(buffer.Length - length, length)); + static long ReadInt64(byte[] buffer, int length) => BitConverter.ToInt64(buffer.AsSpan(buffer.Length - length, length)); + static float ReadSingle(byte[] buffer, int length) => BitConverter.ToSingle(buffer.AsSpan(buffer.Length - length, length)); + static double ReadDouble(byte[] buffer, int length) => BitConverter.ToDouble(buffer.AsSpan(buffer.Length - length, length)); + static ushort ReadUInt16(byte[] buffer, int length) => BitConverter.ToUInt16(buffer.AsSpan(buffer.Length - length, length)); + static uint ReadUInt32(byte[] buffer, int length) => BitConverter.ToUInt32(buffer.AsSpan(buffer.Length - length, length)); + static ulong ReadUInt64(byte[] buffer, int length) => BitConverter.ToUInt64(buffer.AsSpan(buffer.Length - length, length)); + + static bool ReadBooleanOf(byte value) => BitConverter.ToBoolean(new[] { value }.AsSpan()); + + static string Hex(byte[] bytes) + { + var builder = new System.Text.StringBuilder(bytes.Length * 2); + foreach (var b in bytes) + { + builder.Append(b.ToString("x2")); + } + + return builder.ToString(); + } + + static string Capture(Action action) + { + try + { + action(); + return "none"; + } + catch (ArgumentException exception) + { + return $"{exception.GetType().Name}:{exception.ParamName}"; + } + } +} + +#endif