1
1
// Licensed to the .NET Foundation under one or more agreements.
2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
+ using System . Collections . Generic ;
5
+ using System . Linq ;
6
+ using System . Numerics ;
7
+ using System . Runtime . InteropServices ;
4
8
using Xunit ;
5
9
6
10
namespace System . Buffers . Binary . Tests
@@ -41,6 +45,13 @@ public void ReverseEndianness_Int32AndUInt32(uint a, uint b)
41
45
Assert . Equal ( ( int ) a , BinaryPrimitives . ReverseEndianness ( ( int ) b ) ) ;
42
46
Assert . Equal ( b , BinaryPrimitives . ReverseEndianness ( a ) ) ;
43
47
Assert . Equal ( a , BinaryPrimitives . ReverseEndianness ( b ) ) ;
48
+ if ( IntPtr . Size == 4 )
49
+ {
50
+ Assert . Equal ( ( nint ) b , BinaryPrimitives . ReverseEndianness ( ( nint ) a ) ) ;
51
+ Assert . Equal ( ( nint ) a , BinaryPrimitives . ReverseEndianness ( ( nint ) b ) ) ;
52
+ Assert . Equal ( ( nuint ) b , BinaryPrimitives . ReverseEndianness ( ( nuint ) a ) ) ;
53
+ Assert . Equal ( ( nuint ) a , BinaryPrimitives . ReverseEndianness ( ( nuint ) b ) ) ;
54
+ }
44
55
}
45
56
46
57
[ Theory ]
@@ -52,6 +63,129 @@ public void ReverseEndianness_Int64AndUInt64(ulong a, ulong b)
52
63
Assert . Equal ( ( long ) a , BinaryPrimitives . ReverseEndianness ( ( long ) b ) ) ;
53
64
Assert . Equal ( b , BinaryPrimitives . ReverseEndianness ( a ) ) ;
54
65
Assert . Equal ( a , BinaryPrimitives . ReverseEndianness ( b ) ) ;
66
+ if ( IntPtr . Size == 8 )
67
+ {
68
+ Assert . Equal ( ( nint ) b , BinaryPrimitives . ReverseEndianness ( ( nint ) a ) ) ;
69
+ Assert . Equal ( ( nint ) a , BinaryPrimitives . ReverseEndianness ( ( nint ) b ) ) ;
70
+ Assert . Equal ( ( nuint ) b , BinaryPrimitives . ReverseEndianness ( ( nuint ) a ) ) ;
71
+ Assert . Equal ( ( nuint ) a , BinaryPrimitives . ReverseEndianness ( ( nuint ) b ) ) ;
72
+ }
73
+ }
74
+
75
+ [ Theory ]
76
+ [ InlineData ( 0x0123456789ABCDEF , 0xABCDEF0123456789 ) ]
77
+ public void ReverseEndianness_Int128AndUInt128 ( ulong aLower , ulong aUpper )
78
+ {
79
+ Int128 original = new Int128 ( aLower , aUpper ) ;
80
+ Int128 reversed = new Int128 ( BinaryPrimitives . ReverseEndianness ( aUpper ) , BinaryPrimitives . ReverseEndianness ( aLower ) ) ;
81
+
82
+ Assert . Equal ( reversed , BinaryPrimitives . ReverseEndianness ( original ) ) ;
83
+ Assert . Equal ( ( UInt128 ) reversed , BinaryPrimitives . ReverseEndianness ( ( UInt128 ) original ) ) ;
84
+ }
85
+
86
+ public static IEnumerable < object [ ] > ReverseEndianness_Span_MemberData ( )
87
+ {
88
+ var r = new Random ( 42 ) ;
89
+ foreach ( int length in Enumerable . Range ( 0 , 36 ) )
90
+ {
91
+ yield return new object [ ] { Enumerable . Range ( 0 , length ) . Select ( _ => ( ushort ) r . Next ( int . MinValue , int . MaxValue ) ) . ToArray ( ) } ;
92
+ yield return new object [ ] { Enumerable . Range ( 0 , length ) . Select ( _ => ( short ) r . Next ( int . MinValue , int . MaxValue ) ) . ToArray ( ) } ;
93
+ yield return new object [ ] { Enumerable . Range ( 0 , length ) . Select ( _ => ( uint ) r . Next ( int . MinValue , int . MaxValue ) ) . ToArray ( ) } ;
94
+ yield return new object [ ] { Enumerable . Range ( 0 , length ) . Select ( _ => r . Next ( int . MinValue , int . MaxValue ) ) . ToArray ( ) } ;
95
+ yield return new object [ ] { Enumerable . Range ( 0 , length ) . Select ( _ => ( ulong ) r . NextInt64 ( long . MinValue , long . MaxValue ) ) . ToArray ( ) } ;
96
+ yield return new object [ ] { Enumerable . Range ( 0 , length ) . Select ( _ => r . NextInt64 ( long . MinValue , long . MaxValue ) ) . ToArray ( ) } ;
97
+ yield return new object [ ] { Enumerable . Range ( 0 , length ) . Select ( _ => ( nuint ) r . NextInt64 ( long . MinValue , long . MaxValue ) ) . ToArray ( ) } ;
98
+ yield return new object [ ] { Enumerable . Range ( 0 , length ) . Select ( _ => ( nint ) r . NextInt64 ( long . MinValue , long . MaxValue ) ) . ToArray ( ) } ;
99
+ yield return new object [ ] { Enumerable . Range ( 0 , length ) . Select ( _ => new UInt128 ( ( ulong ) r . NextInt64 ( long . MinValue , long . MaxValue ) , ( ulong ) r . NextInt64 ( long . MinValue , long . MaxValue ) ) ) . ToArray ( ) } ;
100
+ yield return new object [ ] { Enumerable . Range ( 0 , length ) . Select ( _ => new Int128 ( ( ulong ) r . NextInt64 ( long . MinValue , long . MaxValue ) , ( ulong ) r . NextInt64 ( long . MinValue , long . MaxValue ) ) ) . ToArray ( ) } ;
101
+ }
102
+ }
103
+
104
+ [ Theory ]
105
+ [ MemberData ( nameof ( ReverseEndianness_Span_MemberData ) ) ]
106
+ public void ReverseEndianness_Span_AllElementsReversed < T > ( T [ ] original ) where T : struct , INumber < T >
107
+ {
108
+ T [ ] expected = original . Select ( ReverseEndianness ) . ToArray ( ) ;
109
+ T [ ] originalCopy = ( T [ ] ) original . Clone ( ) ;
110
+
111
+ T [ ] actual1 = ( T [ ] ) original . Clone ( ) ;
112
+ T [ ] actual2 = new T [ original . Length ] ;
113
+ T [ ] actual3 = new T [ original . Length + 1 ] ;
114
+
115
+ // In-place
116
+ ReverseEndianness < T > ( actual1 , actual1 ) ;
117
+ Assert . Equal ( expected , actual1 ) ;
118
+
119
+ // Different destination
120
+ ReverseEndianness < T > ( original , actual2 ) ;
121
+ Assert . Equal ( originalCopy , original ) ;
122
+ Assert . Equal ( expected , actual2 ) ;
123
+
124
+ // Different larger destination
125
+ ReverseEndianness < T > ( original , actual3 ) ;
126
+ Assert . Equal ( originalCopy , original ) ;
127
+ Assert . Equal ( expected , actual3 [ 0 ..^ 1 ] ) ;
128
+ Assert . Equal ( default , actual3 [ ^ 1 ] ) ;
129
+
130
+ foreach ( int offset in new [ ] { 1 , 2 , 3 } )
131
+ {
132
+ if ( original . Length > offset )
133
+ {
134
+ // In-place shifted +offset
135
+ expected = original . AsSpan ( 0 , original . Length - offset ) . ToArray ( ) . Select ( ReverseEndianness ) . ToArray ( ) ;
136
+ actual1 = ( T [ ] ) original . Clone ( ) ;
137
+ ReverseEndianness ( actual1 . AsSpan ( 0 , actual1 . Length - offset ) , actual1 . AsSpan ( offset ) ) ;
138
+ Assert . Equal ( expected , actual1 . AsSpan ( offset ) . ToArray ( ) ) ;
139
+ for ( int i = 0 ; i < offset ; i ++ )
140
+ {
141
+ Assert . Equal ( original [ i ] , actual1 [ i ] ) ;
142
+ }
143
+
144
+ // In-place shifted -offset
145
+ expected = original . AsSpan ( offset ) . ToArray ( ) . Select ( ReverseEndianness ) . ToArray ( ) ;
146
+ actual2 = ( T [ ] ) original . Clone ( ) ;
147
+ ReverseEndianness ( actual2 . AsSpan ( offset ) , actual2 . AsSpan ( 0 , actual2 . Length - offset ) ) ;
148
+ Assert . Equal ( expected , actual2 . AsSpan ( 0 , actual2 . Length - offset ) . ToArray ( ) ) ;
149
+ Assert . Equal ( original [ ^ offset ] , actual2 [ ^ offset ] ) ;
150
+ }
151
+ }
152
+
153
+ // Throws if the destination is too short
154
+ if ( original . Length > 0 )
155
+ {
156
+ T [ ] destination = new T [ original . Length - 1 ] ;
157
+ AssertExtensions . Throws < ArgumentException > ( "destination" , ( ) => ReverseEndianness < T > ( original , destination ) ) ;
158
+ }
159
+ }
160
+
161
+ private static T ReverseEndianness < T > ( T value )
162
+ {
163
+ if ( typeof ( T ) == typeof ( ushort ) ) return ( T ) ( object ) BinaryPrimitives . ReverseEndianness ( ( ushort ) ( object ) value ) ;
164
+ if ( typeof ( T ) == typeof ( short ) ) return ( T ) ( object ) BinaryPrimitives . ReverseEndianness ( ( short ) ( object ) value ) ;
165
+ if ( typeof ( T ) == typeof ( uint ) ) return ( T ) ( object ) BinaryPrimitives . ReverseEndianness ( ( uint ) ( object ) value ) ;
166
+ if ( typeof ( T ) == typeof ( int ) ) return ( T ) ( object ) BinaryPrimitives . ReverseEndianness ( ( int ) ( object ) value ) ;
167
+ if ( typeof ( T ) == typeof ( ulong ) ) return ( T ) ( object ) BinaryPrimitives . ReverseEndianness ( ( ulong ) ( object ) value ) ;
168
+ if ( typeof ( T ) == typeof ( long ) ) return ( T ) ( object ) BinaryPrimitives . ReverseEndianness ( ( long ) ( object ) value ) ;
169
+ if ( typeof ( T ) == typeof ( nuint ) ) return ( T ) ( object ) BinaryPrimitives . ReverseEndianness ( ( nuint ) ( object ) value ) ;
170
+ if ( typeof ( T ) == typeof ( nint ) ) return ( T ) ( object ) BinaryPrimitives . ReverseEndianness ( ( nint ) ( object ) value ) ;
171
+ if ( typeof ( T ) == typeof ( UInt128 ) ) return ( T ) ( object ) BinaryPrimitives . ReverseEndianness ( ( UInt128 ) ( object ) value ) ;
172
+ if ( typeof ( T ) == typeof ( Int128 ) ) return ( T ) ( object ) BinaryPrimitives . ReverseEndianness ( ( Int128 ) ( object ) value ) ;
173
+ throw new Exception ( $ "Unexpected type { typeof ( T ) } ") ;
174
+ }
175
+
176
+ private static void ReverseEndianness < T > ( ReadOnlySpan < T > source , Span < T > destination ) where T : struct
177
+ {
178
+ if ( typeof ( T ) == typeof ( ushort ) ) { BinaryPrimitives . ReverseEndianness ( MemoryMarshal . Cast < T , ushort > ( source ) , MemoryMarshal . Cast < T , ushort > ( destination ) ) ; return ; }
179
+ if ( typeof ( T ) == typeof ( short ) ) { BinaryPrimitives . ReverseEndianness ( MemoryMarshal . Cast < T , short > ( source ) , MemoryMarshal . Cast < T , short > ( destination ) ) ; return ; }
180
+ if ( typeof ( T ) == typeof ( uint ) ) { BinaryPrimitives . ReverseEndianness ( MemoryMarshal . Cast < T , uint > ( source ) , MemoryMarshal . Cast < T , uint > ( destination ) ) ; return ; }
181
+ if ( typeof ( T ) == typeof ( int ) ) { BinaryPrimitives . ReverseEndianness ( MemoryMarshal . Cast < T , int > ( source ) , MemoryMarshal . Cast < T , int > ( destination ) ) ; return ; }
182
+ if ( typeof ( T ) == typeof ( ulong ) ) { BinaryPrimitives . ReverseEndianness ( MemoryMarshal . Cast < T , ulong > ( source ) , MemoryMarshal . Cast < T , ulong > ( destination ) ) ; return ; }
183
+ if ( typeof ( T ) == typeof ( long ) ) { BinaryPrimitives . ReverseEndianness ( MemoryMarshal . Cast < T , long > ( source ) , MemoryMarshal . Cast < T , long > ( destination ) ) ; return ; }
184
+ if ( typeof ( T ) == typeof ( nuint ) ) { BinaryPrimitives . ReverseEndianness ( MemoryMarshal . Cast < T , nuint > ( source ) , MemoryMarshal . Cast < T , nuint > ( destination ) ) ; return ; }
185
+ if ( typeof ( T ) == typeof ( nint ) ) { BinaryPrimitives . ReverseEndianness ( MemoryMarshal . Cast < T , nint > ( source ) , MemoryMarshal . Cast < T , nint > ( destination ) ) ; return ; }
186
+ if ( typeof ( T ) == typeof ( UInt128 ) ) { BinaryPrimitives . ReverseEndianness ( MemoryMarshal . Cast < T , UInt128 > ( source ) , MemoryMarshal . Cast < T , UInt128 > ( destination ) ) ; return ; }
187
+ if ( typeof ( T ) == typeof ( Int128 ) ) { BinaryPrimitives . ReverseEndianness ( MemoryMarshal . Cast < T , Int128 > ( source ) , MemoryMarshal . Cast < T , Int128 > ( destination ) ) ; return ; }
188
+ throw new Exception ( $ "Unexpected type { typeof ( T ) } ") ;
55
189
}
56
190
}
57
191
}
0 commit comments