1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Runtime.CompilerServices; 6 using System.Runtime.InteropServices; 7 using Xunit; 8 9 using static System.Buffers.Binary.BinaryPrimitives; 10 11 namespace System.Buffers.Binary.Tests 12 { 13 public class BinaryReaderUnitTests 14 { 15 [Fact] SpanRead()16 public void SpanRead() 17 { 18 Assert.True(BitConverter.IsLittleEndian); 19 20 ulong value = 0x8877665544332211; // [11 22 33 44 55 66 77 88] 21 Span<byte> span; 22 unsafe 23 { 24 span = new Span<byte>(&value, 8); 25 } 26 27 Assert.Equal<byte>(0x11, ReadMachineEndian<byte>(span)); 28 Assert.True(TryReadMachineEndian(span, out byte byteValue)); 29 Assert.Equal(0x11, byteValue); 30 31 Assert.Equal<sbyte>(0x11, ReadMachineEndian<sbyte>(span)); 32 Assert.True(TryReadMachineEndian(span, out byte sbyteValue)); 33 Assert.Equal(0x11, byteValue); 34 35 Assert.Equal<ushort>(0x1122, ReadUInt16BigEndian(span)); 36 Assert.True(TryReadUInt16BigEndian(span, out ushort ushortValue)); 37 Assert.Equal(0x1122, ushortValue); 38 39 Assert.Equal<ushort>(0x2211, ReadUInt16LittleEndian(span)); 40 Assert.True(TryReadUInt16LittleEndian(span, out ushortValue)); 41 Assert.Equal(0x2211, ushortValue); 42 43 Assert.Equal<short>(0x1122, ReadInt16BigEndian(span)); 44 Assert.True(TryReadInt16BigEndian(span, out short shortValue)); 45 Assert.Equal(0x1122, shortValue); 46 47 Assert.Equal<short>(0x2211, ReadInt16LittleEndian(span)); 48 Assert.True(TryReadInt16LittleEndian(span, out shortValue)); 49 Assert.Equal(0x2211, ushortValue); 50 51 Assert.Equal<uint>(0x11223344, ReadUInt32BigEndian(span)); 52 Assert.True(TryReadUInt32BigEndian(span, out uint uintValue)); 53 Assert.Equal<uint>(0x11223344, uintValue); 54 55 Assert.Equal<uint>(0x44332211, ReadUInt32LittleEndian(span)); 56 Assert.True(TryReadUInt32LittleEndian(span, out uintValue)); 57 Assert.Equal<uint>(0x44332211, uintValue); 58 59 Assert.Equal<int>(0x11223344, ReadInt32BigEndian(span)); 60 Assert.True(TryReadInt32BigEndian(span, out int intValue)); 61 Assert.Equal<int>(0x11223344, intValue); 62 63 Assert.Equal<int>(0x44332211, ReadInt32LittleEndian(span)); 64 Assert.True(TryReadInt32LittleEndian(span, out intValue)); 65 Assert.Equal<int>(0x44332211, intValue); 66 67 Assert.Equal<ulong>(0x1122334455667788, ReadUInt64BigEndian(span)); 68 Assert.True(TryReadUInt64BigEndian(span, out ulong ulongValue)); 69 Assert.Equal<ulong>(0x1122334455667788, ulongValue); 70 71 Assert.Equal<ulong>(0x8877665544332211, ReadUInt64LittleEndian(span)); 72 Assert.True(TryReadUInt64LittleEndian(span, out ulongValue)); 73 Assert.Equal<ulong>(0x8877665544332211, ulongValue); 74 75 Assert.Equal<long>(0x1122334455667788, ReadInt64BigEndian(span)); 76 Assert.True(TryReadInt64BigEndian(span, out long longValue)); 77 Assert.Equal<long>(0x1122334455667788, longValue); 78 79 Assert.Equal<long>(unchecked((long)0x8877665544332211), ReadInt64LittleEndian(span)); 80 Assert.True(TryReadInt64LittleEndian(span, out longValue)); 81 Assert.Equal<long>(unchecked((long)0x8877665544332211), longValue); 82 } 83 84 [Fact] ReadOnlySpanRead()85 public void ReadOnlySpanRead() 86 { 87 Assert.True(BitConverter.IsLittleEndian); 88 89 ulong value = 0x8877665544332211; // [11 22 33 44 55 66 77 88] 90 ReadOnlySpan<byte> span; 91 unsafe 92 { 93 span = new ReadOnlySpan<byte>(&value, 8); 94 } 95 96 Assert.Equal<byte>(0x11, ReadMachineEndian<byte>(span)); 97 Assert.True(TryReadMachineEndian(span, out byte byteValue)); 98 Assert.Equal(0x11, byteValue); 99 100 Assert.Equal<sbyte>(0x11, ReadMachineEndian<sbyte>(span)); 101 Assert.True(TryReadMachineEndian(span, out byte sbyteValue)); 102 Assert.Equal(0x11, byteValue); 103 104 Assert.Equal<ushort>(0x1122, ReadUInt16BigEndian(span)); 105 Assert.True(TryReadUInt16BigEndian(span, out ushort ushortValue)); 106 Assert.Equal(0x1122, ushortValue); 107 108 Assert.Equal<ushort>(0x2211, ReadUInt16LittleEndian(span)); 109 Assert.True(TryReadUInt16LittleEndian(span, out ushortValue)); 110 Assert.Equal(0x2211, ushortValue); 111 112 Assert.Equal<short>(0x1122, ReadInt16BigEndian(span)); 113 Assert.True(TryReadInt16BigEndian(span, out short shortValue)); 114 Assert.Equal(0x1122, shortValue); 115 116 Assert.Equal<short>(0x2211, ReadInt16LittleEndian(span)); 117 Assert.True(TryReadInt16LittleEndian(span, out shortValue)); 118 Assert.Equal(0x2211, ushortValue); 119 120 Assert.Equal<uint>(0x11223344, ReadUInt32BigEndian(span)); 121 Assert.True(TryReadUInt32BigEndian(span, out uint uintValue)); 122 Assert.Equal<uint>(0x11223344, uintValue); 123 124 Assert.Equal<uint>(0x44332211, ReadUInt32LittleEndian(span)); 125 Assert.True(TryReadUInt32LittleEndian(span, out uintValue)); 126 Assert.Equal<uint>(0x44332211, uintValue); 127 128 Assert.Equal<int>(0x11223344, ReadInt32BigEndian(span)); 129 Assert.True(TryReadInt32BigEndian(span, out int intValue)); 130 Assert.Equal<int>(0x11223344, intValue); 131 132 Assert.Equal<int>(0x44332211, ReadInt32LittleEndian(span)); 133 Assert.True(TryReadInt32LittleEndian(span, out intValue)); 134 Assert.Equal<int>(0x44332211, intValue); 135 136 Assert.Equal<ulong>(0x1122334455667788, ReadUInt64BigEndian(span)); 137 Assert.True(TryReadUInt64BigEndian(span, out ulong ulongValue)); 138 Assert.Equal<ulong>(0x1122334455667788, ulongValue); 139 140 Assert.Equal<ulong>(0x8877665544332211, ReadUInt64LittleEndian(span)); 141 Assert.True(TryReadUInt64LittleEndian(span, out ulongValue)); 142 Assert.Equal<ulong>(0x8877665544332211, ulongValue); 143 144 Assert.Equal<long>(0x1122334455667788, ReadInt64BigEndian(span)); 145 Assert.True(TryReadInt64BigEndian(span, out long longValue)); 146 Assert.Equal<long>(0x1122334455667788, longValue); 147 148 Assert.Equal<long>(unchecked((long)0x8877665544332211), ReadInt64LittleEndian(span)); 149 Assert.True(TryReadInt64LittleEndian(span, out longValue)); 150 Assert.Equal<long>(unchecked((long)0x8877665544332211), longValue); 151 } 152 153 [Fact] SpanReadFail()154 public void SpanReadFail() 155 { 156 Span<byte> span = new byte[] { 1 }; 157 158 Assert.Equal<byte>(1, ReadMachineEndian<byte>(span)); 159 Assert.True(TryReadMachineEndian(span, out byte byteValue)); 160 Assert.Equal(1, byteValue); 161 162 TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => ReadMachineEndian<short>(_span)); 163 Assert.False(TryReadMachineEndian(span, out short shortValue)); 164 TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => ReadMachineEndian<int>(_span)); 165 Assert.False(TryReadMachineEndian(span, out int intValue)); 166 TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => ReadMachineEndian<long>(_span)); 167 Assert.False(TryReadMachineEndian(span, out long longValue)); 168 169 TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => ReadMachineEndian<ushort>(_span)); 170 Assert.False(TryReadMachineEndian(span, out ushort ushortValue)); 171 TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => ReadMachineEndian<uint>(_span)); 172 Assert.False(TryReadMachineEndian(span, out uint uintValue)); 173 TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => ReadMachineEndian<ulong>(_span)); 174 Assert.False(TryReadMachineEndian(span, out ulong ulongValue)); 175 176 Span<byte> largeSpan = new byte[100]; 177 TestHelpers.AssertThrows<ArgumentException, byte>(largeSpan, (_span) => ReadMachineEndian<TestHelpers.TestValueTypeWithReference>(_span)); 178 TestHelpers.AssertThrows<ArgumentException, byte>(largeSpan, (_span) => TryReadMachineEndian(_span, out TestHelpers.TestValueTypeWithReference stringValue)); 179 } 180 181 [Fact] ReadOnlySpanReadFail()182 public void ReadOnlySpanReadFail() 183 { 184 ReadOnlySpan<byte> span = new byte[] { 1 }; 185 186 Assert.Equal<byte>(1, ReadMachineEndian<byte>(span)); 187 Assert.True(TryReadMachineEndian(span, out byte byteValue)); 188 Assert.Equal(1, byteValue); 189 190 TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => ReadMachineEndian<short>(_span)); 191 Assert.False(TryReadMachineEndian(span, out short shortValue)); 192 TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => ReadMachineEndian<int>(_span)); 193 Assert.False(TryReadMachineEndian(span, out int intValue)); 194 TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => ReadMachineEndian<long>(_span)); 195 Assert.False(TryReadMachineEndian(span, out long longValue)); 196 197 TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => ReadMachineEndian<ushort>(_span)); 198 Assert.False(TryReadMachineEndian(span, out ushort ushortValue)); 199 TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => ReadMachineEndian<uint>(_span)); 200 Assert.False(TryReadMachineEndian(span, out uint uintValue)); 201 TestHelpers.AssertThrows<ArgumentOutOfRangeException, byte>(span, (_span) => ReadMachineEndian<ulong>(_span)); 202 Assert.False(TryReadMachineEndian(span, out ulong ulongValue)); 203 204 ReadOnlySpan<byte> largeSpan = new byte[100]; 205 TestHelpers.AssertThrows<ArgumentException, byte>(largeSpan, (_span) => ReadMachineEndian<TestHelpers.TestValueTypeWithReference>(_span)); 206 TestHelpers.AssertThrows<ArgumentException, byte>(largeSpan, (_span) => TryReadMachineEndian(_span, out TestHelpers.TestValueTypeWithReference stringValue)); 207 } 208 209 [Fact] ReverseByteDoesNothing()210 public void ReverseByteDoesNothing() 211 { 212 byte valueMax = byte.MaxValue; 213 byte valueMin = byte.MinValue; 214 sbyte signedValueMax = sbyte.MaxValue; 215 sbyte signedValueMin = sbyte.MinValue; 216 217 Assert.Equal(valueMax, ReverseEndianness(valueMax)); 218 Assert.Equal(valueMin, ReverseEndianness(valueMin)); 219 Assert.Equal(signedValueMax, ReverseEndianness(signedValueMax)); 220 Assert.Equal(signedValueMin, ReverseEndianness(signedValueMin)); 221 } 222 223 [Fact] SpanWriteAndReadBigEndianHeterogeneousStruct()224 public void SpanWriteAndReadBigEndianHeterogeneousStruct() 225 { 226 Assert.True(BitConverter.IsLittleEndian); 227 228 Span<byte> spanBE = new byte[Unsafe.SizeOf<TestStruct>()]; 229 230 WriteInt16BigEndian(spanBE, s_testStruct.S0); 231 WriteInt32BigEndian(spanBE.Slice(2), s_testStruct.I0); 232 WriteInt64BigEndian(spanBE.Slice(6), s_testStruct.L0); 233 WriteUInt16BigEndian(spanBE.Slice(14), s_testStruct.US0); 234 WriteUInt32BigEndian(spanBE.Slice(16), s_testStruct.UI0); 235 WriteUInt64BigEndian(spanBE.Slice(20), s_testStruct.UL0); 236 WriteInt16BigEndian(spanBE.Slice(28), s_testStruct.S1); 237 WriteInt32BigEndian(spanBE.Slice(30), s_testStruct.I1); 238 WriteInt64BigEndian(spanBE.Slice(34), s_testStruct.L1); 239 WriteUInt16BigEndian(spanBE.Slice(42), s_testStruct.US1); 240 WriteUInt32BigEndian(spanBE.Slice(44), s_testStruct.UI1); 241 WriteUInt64BigEndian(spanBE.Slice(48), s_testStruct.UL1); 242 243 ReadOnlySpan<byte> readOnlySpanBE = new ReadOnlySpan<byte>(spanBE.ToArray()); 244 245 var readStruct = new TestStruct 246 { 247 S0 = ReadInt16BigEndian(spanBE), 248 I0 = ReadInt32BigEndian(spanBE.Slice(2)), 249 L0 = ReadInt64BigEndian(spanBE.Slice(6)), 250 US0 = ReadUInt16BigEndian(spanBE.Slice(14)), 251 UI0 = ReadUInt32BigEndian(spanBE.Slice(16)), 252 UL0 = ReadUInt64BigEndian(spanBE.Slice(20)), 253 S1 = ReadInt16BigEndian(spanBE.Slice(28)), 254 I1 = ReadInt32BigEndian(spanBE.Slice(30)), 255 L1 = ReadInt64BigEndian(spanBE.Slice(34)), 256 US1 = ReadUInt16BigEndian(spanBE.Slice(42)), 257 UI1 = ReadUInt32BigEndian(spanBE.Slice(44)), 258 UL1 = ReadUInt64BigEndian(spanBE.Slice(48)) 259 }; 260 261 var readStructFromReadOnlySpan = new TestStruct 262 { 263 S0 = ReadInt16BigEndian(readOnlySpanBE), 264 I0 = ReadInt32BigEndian(readOnlySpanBE.Slice(2)), 265 L0 = ReadInt64BigEndian(readOnlySpanBE.Slice(6)), 266 US0 = ReadUInt16BigEndian(readOnlySpanBE.Slice(14)), 267 UI0 = ReadUInt32BigEndian(readOnlySpanBE.Slice(16)), 268 UL0 = ReadUInt64BigEndian(readOnlySpanBE.Slice(20)), 269 S1 = ReadInt16BigEndian(readOnlySpanBE.Slice(28)), 270 I1 = ReadInt32BigEndian(readOnlySpanBE.Slice(30)), 271 L1 = ReadInt64BigEndian(readOnlySpanBE.Slice(34)), 272 US1 = ReadUInt16BigEndian(readOnlySpanBE.Slice(42)), 273 UI1 = ReadUInt32BigEndian(readOnlySpanBE.Slice(44)), 274 UL1 = ReadUInt64BigEndian(readOnlySpanBE.Slice(48)) 275 }; 276 277 Assert.Equal(s_testStruct, readStruct); 278 Assert.Equal(s_testStruct, readStructFromReadOnlySpan); 279 } 280 281 [Fact] SpanWriteAndReadLittleEndianHeterogeneousStruct()282 public void SpanWriteAndReadLittleEndianHeterogeneousStruct() 283 { 284 Assert.True(BitConverter.IsLittleEndian); 285 286 Span<byte> spanLE = new byte[Unsafe.SizeOf<TestStruct>()]; 287 288 WriteInt16LittleEndian(spanLE, s_testStruct.S0); 289 WriteInt32LittleEndian(spanLE.Slice(2), s_testStruct.I0); 290 WriteInt64LittleEndian(spanLE.Slice(6), s_testStruct.L0); 291 WriteUInt16LittleEndian(spanLE.Slice(14), s_testStruct.US0); 292 WriteUInt32LittleEndian(spanLE.Slice(16), s_testStruct.UI0); 293 WriteUInt64LittleEndian(spanLE.Slice(20), s_testStruct.UL0); 294 WriteInt16LittleEndian(spanLE.Slice(28), s_testStruct.S1); 295 WriteInt32LittleEndian(spanLE.Slice(30), s_testStruct.I1); 296 WriteInt64LittleEndian(spanLE.Slice(34), s_testStruct.L1); 297 WriteUInt16LittleEndian(spanLE.Slice(42), s_testStruct.US1); 298 WriteUInt32LittleEndian(spanLE.Slice(44), s_testStruct.UI1); 299 WriteUInt64LittleEndian(spanLE.Slice(48), s_testStruct.UL1); 300 301 ReadOnlySpan<byte> readOnlySpanLE = new ReadOnlySpan<byte>(spanLE.ToArray()); 302 303 var readStruct = new TestStruct 304 { 305 S0 = ReadInt16LittleEndian(spanLE), 306 I0 = ReadInt32LittleEndian(spanLE.Slice(2)), 307 L0 = ReadInt64LittleEndian(spanLE.Slice(6)), 308 US0 = ReadUInt16LittleEndian(spanLE.Slice(14)), 309 UI0 = ReadUInt32LittleEndian(spanLE.Slice(16)), 310 UL0 = ReadUInt64LittleEndian(spanLE.Slice(20)), 311 S1 = ReadInt16LittleEndian(spanLE.Slice(28)), 312 I1 = ReadInt32LittleEndian(spanLE.Slice(30)), 313 L1 = ReadInt64LittleEndian(spanLE.Slice(34)), 314 US1 = ReadUInt16LittleEndian(spanLE.Slice(42)), 315 UI1 = ReadUInt32LittleEndian(spanLE.Slice(44)), 316 UL1 = ReadUInt64LittleEndian(spanLE.Slice(48)) 317 }; 318 319 var readStructFromReadOnlySpan = new TestStruct 320 { 321 S0 = ReadInt16LittleEndian(readOnlySpanLE), 322 I0 = ReadInt32LittleEndian(readOnlySpanLE.Slice(2)), 323 L0 = ReadInt64LittleEndian(readOnlySpanLE.Slice(6)), 324 US0 = ReadUInt16LittleEndian(readOnlySpanLE.Slice(14)), 325 UI0 = ReadUInt32LittleEndian(readOnlySpanLE.Slice(16)), 326 UL0 = ReadUInt64LittleEndian(readOnlySpanLE.Slice(20)), 327 S1 = ReadInt16LittleEndian(readOnlySpanLE.Slice(28)), 328 I1 = ReadInt32LittleEndian(readOnlySpanLE.Slice(30)), 329 L1 = ReadInt64LittleEndian(readOnlySpanLE.Slice(34)), 330 US1 = ReadUInt16LittleEndian(readOnlySpanLE.Slice(42)), 331 UI1 = ReadUInt32LittleEndian(readOnlySpanLE.Slice(44)), 332 UL1 = ReadUInt64LittleEndian(readOnlySpanLE.Slice(48)) 333 }; 334 335 Assert.Equal(s_testStruct, readStruct); 336 Assert.Equal(s_testStruct, readStructFromReadOnlySpan); 337 } 338 339 [Fact] ReadingStructFieldByFieldOrReadAndReverseEndianness()340 public void ReadingStructFieldByFieldOrReadAndReverseEndianness() 341 { 342 Assert.True(BitConverter.IsLittleEndian); 343 Span<byte> spanBE = new byte[Unsafe.SizeOf<TestHelpers.TestStructExplicit>()]; 344 345 var testExplicitStruct = new TestHelpers.TestStructExplicit 346 { 347 S0 = short.MaxValue, 348 I0 = int.MaxValue, 349 L0 = long.MaxValue, 350 US0 = ushort.MaxValue, 351 UI0 = uint.MaxValue, 352 UL0 = ulong.MaxValue, 353 S1 = short.MinValue, 354 I1 = int.MinValue, 355 L1 = long.MinValue, 356 US1 = ushort.MinValue, 357 UI1 = uint.MinValue, 358 UL1 = ulong.MinValue 359 }; 360 361 WriteInt16BigEndian(spanBE, testExplicitStruct.S0); 362 WriteInt32BigEndian(spanBE.Slice(2), testExplicitStruct.I0); 363 WriteInt64BigEndian(spanBE.Slice(6), testExplicitStruct.L0); 364 WriteUInt16BigEndian(spanBE.Slice(14), testExplicitStruct.US0); 365 WriteUInt32BigEndian(spanBE.Slice(16), testExplicitStruct.UI0); 366 WriteUInt64BigEndian(spanBE.Slice(20), testExplicitStruct.UL0); 367 WriteInt16BigEndian(spanBE.Slice(28), testExplicitStruct.S1); 368 WriteInt32BigEndian(spanBE.Slice(30), testExplicitStruct.I1); 369 WriteInt64BigEndian(spanBE.Slice(34), testExplicitStruct.L1); 370 WriteUInt16BigEndian(spanBE.Slice(42), testExplicitStruct.US1); 371 WriteUInt32BigEndian(spanBE.Slice(44), testExplicitStruct.UI1); 372 WriteUInt64BigEndian(spanBE.Slice(48), testExplicitStruct.UL1); 373 374 Assert.Equal(56, spanBE.Length); 375 376 ReadOnlySpan<byte> readOnlySpanBE = new ReadOnlySpan<byte>(spanBE.ToArray()); 377 378 TestHelpers.TestStructExplicit readStructAndReverse = ReadMachineEndian<TestHelpers.TestStructExplicit>(spanBE); 379 if (BitConverter.IsLittleEndian) 380 { 381 readStructAndReverse.S0 = ReverseEndianness(readStructAndReverse.S0); 382 readStructAndReverse.I0 = ReverseEndianness(readStructAndReverse.I0); 383 readStructAndReverse.L0 = ReverseEndianness(readStructAndReverse.L0); 384 readStructAndReverse.US0 = ReverseEndianness(readStructAndReverse.US0); 385 readStructAndReverse.UI0 = ReverseEndianness(readStructAndReverse.UI0); 386 readStructAndReverse.UL0 = ReverseEndianness(readStructAndReverse.UL0); 387 readStructAndReverse.S1 = ReverseEndianness(readStructAndReverse.S1); 388 readStructAndReverse.I1 = ReverseEndianness(readStructAndReverse.I1); 389 readStructAndReverse.L1 = ReverseEndianness(readStructAndReverse.L1); 390 readStructAndReverse.US1 = ReverseEndianness(readStructAndReverse.US1); 391 readStructAndReverse.UI1 = ReverseEndianness(readStructAndReverse.UI1); 392 readStructAndReverse.UL1 = ReverseEndianness(readStructAndReverse.UL1); 393 } 394 395 var readStructFieldByField = new TestHelpers.TestStructExplicit 396 { 397 S0 = ReadInt16BigEndian(spanBE), 398 I0 = ReadInt32BigEndian(spanBE.Slice(2)), 399 L0 = ReadInt64BigEndian(spanBE.Slice(6)), 400 US0 = ReadUInt16BigEndian(spanBE.Slice(14)), 401 UI0 = ReadUInt32BigEndian(spanBE.Slice(16)), 402 UL0 = ReadUInt64BigEndian(spanBE.Slice(20)), 403 S1 = ReadInt16BigEndian(spanBE.Slice(28)), 404 I1 = ReadInt32BigEndian(spanBE.Slice(30)), 405 L1 = ReadInt64BigEndian(spanBE.Slice(34)), 406 US1 = ReadUInt16BigEndian(spanBE.Slice(42)), 407 UI1 = ReadUInt32BigEndian(spanBE.Slice(44)), 408 UL1 = ReadUInt64BigEndian(spanBE.Slice(48)) 409 }; 410 411 TestHelpers.TestStructExplicit readStructAndReverseFromReadOnlySpan = ReadMachineEndian<TestHelpers.TestStructExplicit>(readOnlySpanBE); 412 if (BitConverter.IsLittleEndian) 413 { 414 readStructAndReverseFromReadOnlySpan.S0 = ReverseEndianness(readStructAndReverseFromReadOnlySpan.S0); 415 readStructAndReverseFromReadOnlySpan.I0 = ReverseEndianness(readStructAndReverseFromReadOnlySpan.I0); 416 readStructAndReverseFromReadOnlySpan.L0 = ReverseEndianness(readStructAndReverseFromReadOnlySpan.L0); 417 readStructAndReverseFromReadOnlySpan.US0 = ReverseEndianness(readStructAndReverseFromReadOnlySpan.US0); 418 readStructAndReverseFromReadOnlySpan.UI0 = ReverseEndianness(readStructAndReverseFromReadOnlySpan.UI0); 419 readStructAndReverseFromReadOnlySpan.UL0 = ReverseEndianness(readStructAndReverseFromReadOnlySpan.UL0); 420 readStructAndReverseFromReadOnlySpan.S1 = ReverseEndianness(readStructAndReverseFromReadOnlySpan.S1); 421 readStructAndReverseFromReadOnlySpan.I1 = ReverseEndianness(readStructAndReverseFromReadOnlySpan.I1); 422 readStructAndReverseFromReadOnlySpan.L1 = ReverseEndianness(readStructAndReverseFromReadOnlySpan.L1); 423 readStructAndReverseFromReadOnlySpan.US1 = ReverseEndianness(readStructAndReverseFromReadOnlySpan.US1); 424 readStructAndReverseFromReadOnlySpan.UI1 = ReverseEndianness(readStructAndReverseFromReadOnlySpan.UI1); 425 readStructAndReverseFromReadOnlySpan.UL1 = ReverseEndianness(readStructAndReverseFromReadOnlySpan.UL1); 426 } 427 428 var readStructFieldByFieldFromReadOnlySpan = new TestHelpers.TestStructExplicit 429 { 430 S0 = ReadInt16BigEndian(readOnlySpanBE), 431 I0 = ReadInt32BigEndian(readOnlySpanBE.Slice(2)), 432 L0 = ReadInt64BigEndian(readOnlySpanBE.Slice(6)), 433 US0 = ReadUInt16BigEndian(readOnlySpanBE.Slice(14)), 434 UI0 = ReadUInt32BigEndian(readOnlySpanBE.Slice(16)), 435 UL0 = ReadUInt64BigEndian(readOnlySpanBE.Slice(20)), 436 S1 = ReadInt16BigEndian(readOnlySpanBE.Slice(28)), 437 I1 = ReadInt32BigEndian(readOnlySpanBE.Slice(30)), 438 L1 = ReadInt64BigEndian(readOnlySpanBE.Slice(34)), 439 US1 = ReadUInt16BigEndian(readOnlySpanBE.Slice(42)), 440 UI1 = ReadUInt32BigEndian(readOnlySpanBE.Slice(44)), 441 UL1 = ReadUInt64BigEndian(readOnlySpanBE.Slice(48)) 442 }; 443 444 Assert.Equal(testExplicitStruct, readStructAndReverse); 445 Assert.Equal(testExplicitStruct, readStructFieldByField); 446 447 Assert.Equal(testExplicitStruct, readStructAndReverseFromReadOnlySpan); 448 Assert.Equal(testExplicitStruct, readStructFieldByFieldFromReadOnlySpan); 449 } 450 451 private static TestStruct s_testStruct = new TestStruct 452 { 453 S0 = short.MaxValue, 454 I0 = int.MaxValue, 455 L0 = long.MaxValue, 456 US0 = ushort.MaxValue, 457 UI0 = uint.MaxValue, 458 UL0 = ulong.MaxValue, 459 S1 = short.MinValue, 460 I1 = int.MinValue, 461 L1 = long.MinValue, 462 US1 = ushort.MinValue, 463 UI1 = uint.MinValue, 464 UL1 = ulong.MinValue 465 }; 466 467 [StructLayout(LayoutKind.Sequential)] 468 private struct TestStruct 469 { 470 public short S0; 471 public int I0; 472 public long L0; 473 public ushort US0; 474 public uint UI0; 475 public ulong UL0; 476 public short S1; 477 public int I1; 478 public long L1; 479 public ushort US1; 480 public uint UI1; 481 public ulong UL1; 482 } 483 } 484 } 485