1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "mozilla/Assertions.h"
8 #include "mozilla/EndianUtils.h"
9 
10 #include <stddef.h>
11 
12 using mozilla::BigEndian;
13 using mozilla::LittleEndian;
14 using mozilla::NativeEndian;
15 
16 template <typename T>
TestSingleSwap(T aValue,T aSwappedValue)17 void TestSingleSwap(T aValue, T aSwappedValue) {
18 #if MOZ_LITTLE_ENDIAN()
19   MOZ_RELEASE_ASSERT(NativeEndian::swapToBigEndian(aValue) == aSwappedValue);
20   MOZ_RELEASE_ASSERT(NativeEndian::swapFromBigEndian(aValue) == aSwappedValue);
21   MOZ_RELEASE_ASSERT(NativeEndian::swapToNetworkOrder(aValue) == aSwappedValue);
22   MOZ_RELEASE_ASSERT(NativeEndian::swapFromNetworkOrder(aValue) ==
23                      aSwappedValue);
24 #else
25   MOZ_RELEASE_ASSERT(NativeEndian::swapToLittleEndian(aValue) == aSwappedValue);
26   MOZ_RELEASE_ASSERT(NativeEndian::swapFromLittleEndian(aValue) ==
27                      aSwappedValue);
28 #endif
29 }
30 
31 template <typename T>
TestSingleNoSwap(T aValue,T aUnswappedValue)32 void TestSingleNoSwap(T aValue, T aUnswappedValue) {
33 #if MOZ_LITTLE_ENDIAN()
34   MOZ_RELEASE_ASSERT(NativeEndian::swapToLittleEndian(aValue) ==
35                      aUnswappedValue);
36   MOZ_RELEASE_ASSERT(NativeEndian::swapFromLittleEndian(aValue) ==
37                      aUnswappedValue);
38 #else
39   MOZ_RELEASE_ASSERT(NativeEndian::swapToBigEndian(aValue) == aUnswappedValue);
40   MOZ_RELEASE_ASSERT(NativeEndian::swapFromBigEndian(aValue) ==
41                      aUnswappedValue);
42   MOZ_RELEASE_ASSERT(NativeEndian::swapToNetworkOrder(aValue) ==
43                      aUnswappedValue);
44   MOZ_RELEASE_ASSERT(NativeEndian::swapFromNetworkOrder(aValue) ==
45                      aUnswappedValue);
46 #endif
47 }
48 
49 // EndianUtils.h functions are declared as protected in a base class and
50 // then re-exported as public in public derived classes.  The
51 // standardese around explicit instantiation of templates is not clear
52 // in such cases.  Provide these wrappers to make things more explicit.
53 // For your own enlightenment, you may wish to peruse:
54 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56152 and subsequently
55 // http://j.mp/XosS6S .
56 #define WRAP_COPYTO(NAME)                               \
57   template <typename T>                                 \
58   void NAME(void* aDst, const T* aSrc, size_t aCount) { \
59     NativeEndian::NAME<T>(aDst, aSrc, aCount);          \
60   }
61 
62 WRAP_COPYTO(copyAndSwapToLittleEndian)
63 WRAP_COPYTO(copyAndSwapToBigEndian)
64 WRAP_COPYTO(copyAndSwapToNetworkOrder)
65 
66 #define WRAP_COPYFROM(NAME)                             \
67   template <typename T>                                 \
68   void NAME(T* aDst, const void* aSrc, size_t aCount) { \
69     NativeEndian::NAME<T>(aDst, aSrc, aCount);          \
70   }
71 
72 WRAP_COPYFROM(copyAndSwapFromLittleEndian)
73 WRAP_COPYFROM(copyAndSwapFromBigEndian)
74 WRAP_COPYFROM(copyAndSwapFromNetworkOrder)
75 
76 #define WRAP_IN_PLACE(NAME)            \
77   template <typename T>                \
78   void NAME(T* aP, size_t aCount) {    \
79     NativeEndian::NAME<T>(aP, aCount); \
80   }
81 WRAP_IN_PLACE(swapToLittleEndianInPlace)
82 WRAP_IN_PLACE(swapFromLittleEndianInPlace)
83 WRAP_IN_PLACE(swapToBigEndianInPlace)
84 WRAP_IN_PLACE(swapFromBigEndianInPlace)
85 WRAP_IN_PLACE(swapToNetworkOrderInPlace)
86 WRAP_IN_PLACE(swapFromNetworkOrderInPlace)
87 
88 enum SwapExpectation { Swap, NoSwap };
89 
90 template <typename T, size_t Count>
TestBulkSwapToSub(enum SwapExpectation aExpectSwap,const T (& aValues)[Count],void (* aSwapperFunc)(void *,const T *,size_t),T (* aReaderFunc)(const void *))91 void TestBulkSwapToSub(enum SwapExpectation aExpectSwap,
92                        const T (&aValues)[Count],
93                        void (*aSwapperFunc)(void*, const T*, size_t),
94                        T (*aReaderFunc)(const void*)) {
95   const size_t arraySize = 2 * Count;
96   const size_t bufferSize = arraySize * sizeof(T);
97   static uint8_t buffer[bufferSize];
98   const uint8_t fillValue = 0xa5;
99   static uint8_t checkBuffer[bufferSize];
100 
101   MOZ_RELEASE_ASSERT(bufferSize > 2 * sizeof(T));
102 
103   memset(checkBuffer, fillValue, bufferSize);
104 
105   for (size_t startPosition = 0; startPosition < sizeof(T); ++startPosition) {
106     for (size_t nValues = 0; nValues < Count; ++nValues) {
107       memset(buffer, fillValue, bufferSize);
108       aSwapperFunc(buffer + startPosition, aValues, nValues);
109 
110       MOZ_RELEASE_ASSERT(memcmp(buffer, checkBuffer, startPosition) == 0);
111       size_t valuesEndPosition = startPosition + sizeof(T) * nValues;
112       MOZ_RELEASE_ASSERT(memcmp(buffer + valuesEndPosition,
113                                 checkBuffer + valuesEndPosition,
114                                 bufferSize - valuesEndPosition) == 0);
115       if (aExpectSwap == NoSwap) {
116         MOZ_RELEASE_ASSERT(
117             memcmp(buffer + startPosition, aValues, nValues * sizeof(T)) == 0);
118       }
119       for (size_t i = 0; i < nValues; ++i) {
120         MOZ_RELEASE_ASSERT(
121             aReaderFunc(buffer + startPosition + sizeof(T) * i) == aValues[i]);
122       }
123     }
124   }
125 }
126 
127 template <typename T, size_t Count>
TestBulkSwapFromSub(enum SwapExpectation aExpectSwap,const T (& aValues)[Count],void (* aSwapperFunc)(T *,const void *,size_t),T (* aReaderFunc)(const void *))128 void TestBulkSwapFromSub(enum SwapExpectation aExpectSwap,
129                          const T (&aValues)[Count],
130                          void (*aSwapperFunc)(T*, const void*, size_t),
131                          T (*aReaderFunc)(const void*)) {
132   const size_t arraySize = 2 * Count;
133   const size_t bufferSize = arraySize * sizeof(T);
134   static T buffer[arraySize];
135   const uint8_t fillValue = 0xa5;
136   static T checkBuffer[arraySize];
137 
138   memset(checkBuffer, fillValue, bufferSize);
139 
140   for (size_t startPosition = 0; startPosition < Count; ++startPosition) {
141     for (size_t nValues = 0; nValues < (Count - startPosition); ++nValues) {
142       memset(buffer, fillValue, bufferSize);
143       aSwapperFunc(buffer + startPosition, aValues, nValues);
144 
145       MOZ_RELEASE_ASSERT(
146           memcmp(buffer, checkBuffer, startPosition * sizeof(T)) == 0);
147       size_t valuesEndPosition = startPosition + nValues;
148       MOZ_RELEASE_ASSERT(
149           memcmp(buffer + valuesEndPosition, checkBuffer + valuesEndPosition,
150                  (arraySize - valuesEndPosition) * sizeof(T)) == 0);
151       if (aExpectSwap == NoSwap) {
152         MOZ_RELEASE_ASSERT(
153             memcmp(buffer + startPosition, aValues, nValues * sizeof(T)) == 0);
154       }
155       for (size_t i = 0; i < nValues; ++i) {
156         MOZ_RELEASE_ASSERT(aReaderFunc(buffer + startPosition + i) ==
157                            aValues[i]);
158       }
159     }
160   }
161 }
162 
163 template <typename T, size_t Count>
TestBulkInPlaceSub(enum SwapExpectation aExpectSwap,const T (& aValues)[Count],void (* aSwapperFunc)(T *,size_t),T (* aReaderFunc)(const void *))164 void TestBulkInPlaceSub(enum SwapExpectation aExpectSwap,
165                         const T (&aValues)[Count],
166                         void (*aSwapperFunc)(T*, size_t),
167                         T (*aReaderFunc)(const void*)) {
168   const size_t bufferCount = 4 * Count;
169   const size_t bufferSize = bufferCount * sizeof(T);
170   static T buffer[bufferCount];
171   const T fillValue = 0xa5;
172   static T checkBuffer[bufferCount];
173 
174   MOZ_RELEASE_ASSERT(bufferSize > 2 * sizeof(T));
175 
176   memset(checkBuffer, fillValue, bufferSize);
177 
178   for (size_t startPosition = 0; startPosition < Count; ++startPosition) {
179     for (size_t nValues = 0; nValues < Count; ++nValues) {
180       memset(buffer, fillValue, bufferSize);
181       memcpy(buffer + startPosition, aValues, nValues * sizeof(T));
182       aSwapperFunc(buffer + startPosition, nValues);
183 
184       MOZ_RELEASE_ASSERT(
185           memcmp(buffer, checkBuffer, startPosition * sizeof(T)) == 0);
186       size_t valuesEndPosition = startPosition + nValues;
187       MOZ_RELEASE_ASSERT(
188           memcmp(buffer + valuesEndPosition, checkBuffer + valuesEndPosition,
189                  bufferSize - valuesEndPosition * sizeof(T)) == 0);
190       if (aExpectSwap == NoSwap) {
191         MOZ_RELEASE_ASSERT(
192             memcmp(buffer + startPosition, aValues, nValues * sizeof(T)) == 0);
193       }
194       for (size_t i = 0; i < nValues; ++i) {
195         MOZ_RELEASE_ASSERT(aReaderFunc(buffer + startPosition + i) ==
196                            aValues[i]);
197       }
198     }
199   }
200 }
201 
202 template <typename T>
203 struct Reader {};
204 
205 #define SPECIALIZE_READER(TYPE, READ_FUNC)                                     \
206   template <>                                                                  \
207   struct Reader<TYPE> {                                                        \
208     static TYPE readLE(const void* aP) { return LittleEndian::READ_FUNC(aP); } \
209     static TYPE readBE(const void* aP) { return BigEndian::READ_FUNC(aP); }    \
210   };
211 
SPECIALIZE_READER(uint16_t,readUint16)212 SPECIALIZE_READER(uint16_t, readUint16)
213 SPECIALIZE_READER(uint32_t, readUint32)
214 SPECIALIZE_READER(uint64_t, readUint64)
215 SPECIALIZE_READER(int16_t, readInt16)
216 SPECIALIZE_READER(int32_t, readInt32)
217 SPECIALIZE_READER(int64_t, readInt64)
218 
219 template <typename T, size_t Count>
220 void TestBulkSwap(const T (&aBytes)[Count]) {
221 #if MOZ_LITTLE_ENDIAN()
222   TestBulkSwapToSub(Swap, aBytes, copyAndSwapToBigEndian<T>, Reader<T>::readBE);
223   TestBulkSwapFromSub(Swap, aBytes, copyAndSwapFromBigEndian<T>,
224                       Reader<T>::readBE);
225   TestBulkSwapToSub(Swap, aBytes, copyAndSwapToNetworkOrder<T>,
226                     Reader<T>::readBE);
227   TestBulkSwapFromSub(Swap, aBytes, copyAndSwapFromNetworkOrder<T>,
228                       Reader<T>::readBE);
229 #else
230   TestBulkSwapToSub(Swap, aBytes, copyAndSwapToLittleEndian<T>,
231                     Reader<T>::readLE);
232   TestBulkSwapFromSub(Swap, aBytes, copyAndSwapFromLittleEndian<T>,
233                       Reader<T>::readLE);
234 #endif
235 }
236 
237 template <typename T, size_t Count>
TestBulkNoSwap(const T (& aBytes)[Count])238 void TestBulkNoSwap(const T (&aBytes)[Count]) {
239 #if MOZ_LITTLE_ENDIAN()
240   TestBulkSwapToSub(NoSwap, aBytes, copyAndSwapToLittleEndian<T>,
241                     Reader<T>::readLE);
242   TestBulkSwapFromSub(NoSwap, aBytes, copyAndSwapFromLittleEndian<T>,
243                       Reader<T>::readLE);
244 #else
245   TestBulkSwapToSub(NoSwap, aBytes, copyAndSwapToBigEndian<T>,
246                     Reader<T>::readBE);
247   TestBulkSwapFromSub(NoSwap, aBytes, copyAndSwapFromBigEndian<T>,
248                       Reader<T>::readBE);
249   TestBulkSwapToSub(NoSwap, aBytes, copyAndSwapToNetworkOrder<T>,
250                     Reader<T>::readBE);
251   TestBulkSwapFromSub(NoSwap, aBytes, copyAndSwapFromNetworkOrder<T>,
252                       Reader<T>::readBE);
253 #endif
254 }
255 
256 template <typename T, size_t Count>
TestBulkInPlaceSwap(const T (& aBytes)[Count])257 void TestBulkInPlaceSwap(const T (&aBytes)[Count]) {
258 #if MOZ_LITTLE_ENDIAN()
259   TestBulkInPlaceSub(Swap, aBytes, swapToBigEndianInPlace<T>,
260                      Reader<T>::readBE);
261   TestBulkInPlaceSub(Swap, aBytes, swapFromBigEndianInPlace<T>,
262                      Reader<T>::readBE);
263   TestBulkInPlaceSub(Swap, aBytes, swapToNetworkOrderInPlace<T>,
264                      Reader<T>::readBE);
265   TestBulkInPlaceSub(Swap, aBytes, swapFromNetworkOrderInPlace<T>,
266                      Reader<T>::readBE);
267 #else
268   TestBulkInPlaceSub(Swap, aBytes, swapToLittleEndianInPlace<T>,
269                      Reader<T>::readLE);
270   TestBulkInPlaceSub(Swap, aBytes, swapFromLittleEndianInPlace<T>,
271                      Reader<T>::readLE);
272 #endif
273 }
274 
275 template <typename T, size_t Count>
TestBulkInPlaceNoSwap(const T (& aBytes)[Count])276 void TestBulkInPlaceNoSwap(const T (&aBytes)[Count]) {
277 #if MOZ_LITTLE_ENDIAN()
278   TestBulkInPlaceSub(NoSwap, aBytes, swapToLittleEndianInPlace<T>,
279                      Reader<T>::readLE);
280   TestBulkInPlaceSub(NoSwap, aBytes, swapFromLittleEndianInPlace<T>,
281                      Reader<T>::readLE);
282 #else
283   TestBulkInPlaceSub(NoSwap, aBytes, swapToBigEndianInPlace<T>,
284                      Reader<T>::readBE);
285   TestBulkInPlaceSub(NoSwap, aBytes, swapFromBigEndianInPlace<T>,
286                      Reader<T>::readBE);
287   TestBulkInPlaceSub(NoSwap, aBytes, swapToNetworkOrderInPlace<T>,
288                      Reader<T>::readBE);
289   TestBulkInPlaceSub(NoSwap, aBytes, swapFromNetworkOrderInPlace<T>,
290                      Reader<T>::readBE);
291 #endif
292 }
293 
main()294 int main() {
295   static const uint8_t unsigned_bytes[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
296                                              0x07, 0x08, 0x01, 0x02, 0x03, 0x04,
297                                              0x05, 0x06, 0x07, 0x08};
298   static const int8_t signed_bytes[16] = {
299       -0x0f, -0x0e, -0x0d, -0x0c, -0x0b, -0x0a, -0x09, -0x08,
300       -0x0f, -0x0e, -0x0d, -0x0c, -0x0b, -0x0a, -0x09, -0x08};
301   static const uint16_t uint16_values[8] = {0x0102, 0x0304, 0x0506, 0x0708,
302                                             0x0102, 0x0304, 0x0506, 0x0708};
303   static const int16_t int16_values[8] = {
304       int16_t(0xf1f2), int16_t(0xf3f4), int16_t(0xf5f6), int16_t(0xf7f8),
305       int16_t(0xf1f2), int16_t(0xf3f4), int16_t(0xf5f6), int16_t(0xf7f8)};
306   static const uint32_t uint32_values[4] = {0x01020304, 0x05060708, 0x01020304,
307                                             0x05060708};
308   static const int32_t int32_values[4] = {
309       int32_t(0xf1f2f3f4), int32_t(0xf5f6f7f8), int32_t(0xf1f2f3f4),
310       int32_t(0xf5f6f7f8)};
311   static const uint64_t uint64_values[2] = {0x0102030405060708,
312                                             0x0102030405060708};
313   static const int64_t int64_values[2] = {int64_t(0xf1f2f3f4f5f6f7f8),
314                                           int64_t(0xf1f2f3f4f5f6f7f8)};
315   uint8_t buffer[8];
316 
317   MOZ_RELEASE_ASSERT(LittleEndian::readUint16(&unsigned_bytes[0]) == 0x0201);
318   MOZ_RELEASE_ASSERT(BigEndian::readUint16(&unsigned_bytes[0]) == 0x0102);
319 
320   MOZ_RELEASE_ASSERT(LittleEndian::readUint32(&unsigned_bytes[0]) ==
321                      0x04030201U);
322   MOZ_RELEASE_ASSERT(BigEndian::readUint32(&unsigned_bytes[0]) == 0x01020304U);
323 
324   MOZ_RELEASE_ASSERT(LittleEndian::readUint64(&unsigned_bytes[0]) ==
325                      0x0807060504030201ULL);
326   MOZ_RELEASE_ASSERT(BigEndian::readUint64(&unsigned_bytes[0]) ==
327                      0x0102030405060708ULL);
328 
329   if (sizeof(uintptr_t) == 8) {
330     // MSVC warning C4309 is "'static_cast': truncation of constant value" and
331     // will hit for the literal casts below in 32-bit builds -- in dead code,
332     // because only the other arm of this |if| runs.  Turn off the warning for
333     // these two uses in dead code.
334 #ifdef _MSC_VER
335 #  pragma warning(push)
336 #  pragma warning(disable : 4309)
337 #endif
338     MOZ_RELEASE_ASSERT(LittleEndian::readUintptr(&unsigned_bytes[0]) ==
339                        static_cast<uintptr_t>(0x0807060504030201ULL));
340     MOZ_RELEASE_ASSERT(BigEndian::readUintptr(&unsigned_bytes[0]) ==
341                        static_cast<uintptr_t>(0x0102030405060708ULL));
342 #ifdef _MSC_VER
343 #  pragma warning(pop)
344 #endif
345   } else {
346     MOZ_RELEASE_ASSERT(LittleEndian::readUintptr(&unsigned_bytes[0]) ==
347                        0x04030201U);
348     MOZ_RELEASE_ASSERT(BigEndian::readUintptr(&unsigned_bytes[0]) ==
349                        0x01020304U);
350   }
351 
352   LittleEndian::writeUint16(&buffer[0], 0x0201);
353   MOZ_RELEASE_ASSERT(memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint16_t)) ==
354                      0);
355   BigEndian::writeUint16(&buffer[0], 0x0102);
356   MOZ_RELEASE_ASSERT(memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint16_t)) ==
357                      0);
358 
359   LittleEndian::writeUint32(&buffer[0], 0x04030201U);
360   MOZ_RELEASE_ASSERT(memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint32_t)) ==
361                      0);
362   BigEndian::writeUint32(&buffer[0], 0x01020304U);
363   MOZ_RELEASE_ASSERT(memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint32_t)) ==
364                      0);
365 
366   LittleEndian::writeUint64(&buffer[0], 0x0807060504030201ULL);
367   MOZ_RELEASE_ASSERT(memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint64_t)) ==
368                      0);
369   BigEndian::writeUint64(&buffer[0], 0x0102030405060708ULL);
370   MOZ_RELEASE_ASSERT(memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint64_t)) ==
371                      0);
372 
373   memset(&buffer[0], 0xff, sizeof(buffer));
374   LittleEndian::writeUintptr(&buffer[0], uintptr_t(0x0807060504030201ULL));
375   MOZ_RELEASE_ASSERT(
376       memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uintptr_t)) == 0);
377   if (sizeof(uintptr_t) == 4) {
378     MOZ_RELEASE_ASSERT(LittleEndian::readUint32(&buffer[4]) == 0xffffffffU);
379   }
380 
381   memset(&buffer[0], 0xff, sizeof(buffer));
382   if (sizeof(uintptr_t) == 8) {
383     BigEndian::writeUintptr(&buffer[0], uintptr_t(0x0102030405060708ULL));
384   } else {
385     BigEndian::writeUintptr(&buffer[0], uintptr_t(0x01020304U));
386     MOZ_RELEASE_ASSERT(LittleEndian::readUint32(&buffer[4]) == 0xffffffffU);
387   }
388   MOZ_RELEASE_ASSERT(
389       memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uintptr_t)) == 0);
390 
391   MOZ_RELEASE_ASSERT(LittleEndian::readInt16(&signed_bytes[0]) ==
392                      int16_t(0xf2f1));
393   MOZ_RELEASE_ASSERT(BigEndian::readInt16(&signed_bytes[0]) == int16_t(0xf1f2));
394 
395   MOZ_RELEASE_ASSERT(LittleEndian::readInt32(&signed_bytes[0]) ==
396                      int32_t(0xf4f3f2f1));
397   MOZ_RELEASE_ASSERT(BigEndian::readInt32(&signed_bytes[0]) ==
398                      int32_t(0xf1f2f3f4));
399 
400   MOZ_RELEASE_ASSERT(LittleEndian::readInt64(&signed_bytes[0]) ==
401                      int64_t(0xf8f7f6f5f4f3f2f1LL));
402   MOZ_RELEASE_ASSERT(BigEndian::readInt64(&signed_bytes[0]) ==
403                      int64_t(0xf1f2f3f4f5f6f7f8LL));
404 
405   if (sizeof(uintptr_t) == 8) {
406     MOZ_RELEASE_ASSERT(LittleEndian::readIntptr(&signed_bytes[0]) ==
407                        intptr_t(0xf8f7f6f5f4f3f2f1LL));
408     MOZ_RELEASE_ASSERT(BigEndian::readIntptr(&signed_bytes[0]) ==
409                        intptr_t(0xf1f2f3f4f5f6f7f8LL));
410   } else {
411     MOZ_RELEASE_ASSERT(LittleEndian::readIntptr(&signed_bytes[0]) ==
412                        intptr_t(0xf4f3f2f1));
413     MOZ_RELEASE_ASSERT(BigEndian::readIntptr(&signed_bytes[0]) ==
414                        intptr_t(0xf1f2f3f4));
415   }
416 
417   LittleEndian::writeInt16(&buffer[0], int16_t(0xf2f1));
418   MOZ_RELEASE_ASSERT(memcmp(&signed_bytes[0], &buffer[0], sizeof(int16_t)) ==
419                      0);
420   BigEndian::writeInt16(&buffer[0], int16_t(0xf1f2));
421   MOZ_RELEASE_ASSERT(memcmp(&signed_bytes[0], &buffer[0], sizeof(int16_t)) ==
422                      0);
423 
424   LittleEndian::writeInt32(&buffer[0], 0xf4f3f2f1);
425   MOZ_RELEASE_ASSERT(memcmp(&signed_bytes[0], &buffer[0], sizeof(int32_t)) ==
426                      0);
427   BigEndian::writeInt32(&buffer[0], 0xf1f2f3f4);
428   MOZ_RELEASE_ASSERT(memcmp(&signed_bytes[0], &buffer[0], sizeof(int32_t)) ==
429                      0);
430 
431   LittleEndian::writeInt64(&buffer[0], 0xf8f7f6f5f4f3f2f1LL);
432   MOZ_RELEASE_ASSERT(memcmp(&signed_bytes[0], &buffer[0], sizeof(int64_t)) ==
433                      0);
434   BigEndian::writeInt64(&buffer[0], 0xf1f2f3f4f5f6f7f8LL);
435   MOZ_RELEASE_ASSERT(memcmp(&signed_bytes[0], &buffer[0], sizeof(int64_t)) ==
436                      0);
437 
438   memset(&buffer[0], 0xff, sizeof(buffer));
439   LittleEndian::writeIntptr(&buffer[0], intptr_t(0xf8f7f6f5f4f3f2f1LL));
440   MOZ_RELEASE_ASSERT(memcmp(&signed_bytes[0], &buffer[0], sizeof(intptr_t)) ==
441                      0);
442   if (sizeof(intptr_t) == 4) {
443     MOZ_RELEASE_ASSERT(LittleEndian::readUint32(&buffer[4]) == 0xffffffffU);
444   }
445 
446   memset(&buffer[0], 0xff, sizeof(buffer));
447   if (sizeof(intptr_t) == 8) {
448     BigEndian::writeIntptr(&buffer[0], intptr_t(0xf1f2f3f4f5f6f7f8LL));
449   } else {
450     BigEndian::writeIntptr(&buffer[0], intptr_t(0xf1f2f3f4));
451     MOZ_RELEASE_ASSERT(LittleEndian::readUint32(&buffer[4]) == 0xffffffffU);
452   }
453   MOZ_RELEASE_ASSERT(memcmp(&signed_bytes[0], &buffer[0], sizeof(intptr_t)) ==
454                      0);
455 
456   TestSingleSwap(uint16_t(0xf2f1), uint16_t(0xf1f2));
457   TestSingleSwap(uint32_t(0xf4f3f2f1), uint32_t(0xf1f2f3f4));
458   TestSingleSwap(uint64_t(0xf8f7f6f5f4f3f2f1), uint64_t(0xf1f2f3f4f5f6f7f8));
459 
460   TestSingleSwap(int16_t(0xf2f1), int16_t(0xf1f2));
461   TestSingleSwap(int32_t(0xf4f3f2f1), int32_t(0xf1f2f3f4));
462   TestSingleSwap(int64_t(0xf8f7f6f5f4f3f2f1), int64_t(0xf1f2f3f4f5f6f7f8));
463 
464   TestSingleNoSwap(uint16_t(0xf2f1), uint16_t(0xf2f1));
465   TestSingleNoSwap(uint32_t(0xf4f3f2f1), uint32_t(0xf4f3f2f1));
466   TestSingleNoSwap(uint64_t(0xf8f7f6f5f4f3f2f1), uint64_t(0xf8f7f6f5f4f3f2f1));
467 
468   TestSingleNoSwap(int16_t(0xf2f1), int16_t(0xf2f1));
469   TestSingleNoSwap(int32_t(0xf4f3f2f1), int32_t(0xf4f3f2f1));
470   TestSingleNoSwap(int64_t(0xf8f7f6f5f4f3f2f1), int64_t(0xf8f7f6f5f4f3f2f1));
471 
472   TestBulkSwap(uint16_values);
473   TestBulkSwap(int16_values);
474   TestBulkSwap(uint32_values);
475   TestBulkSwap(int32_values);
476   TestBulkSwap(uint64_values);
477   TestBulkSwap(int64_values);
478 
479   TestBulkNoSwap(uint16_values);
480   TestBulkNoSwap(int16_values);
481   TestBulkNoSwap(uint32_values);
482   TestBulkNoSwap(int32_values);
483   TestBulkNoSwap(uint64_values);
484   TestBulkNoSwap(int64_values);
485 
486   TestBulkInPlaceSwap(uint16_values);
487   TestBulkInPlaceSwap(int16_values);
488   TestBulkInPlaceSwap(uint32_values);
489   TestBulkInPlaceSwap(int32_values);
490   TestBulkInPlaceSwap(uint64_values);
491   TestBulkInPlaceSwap(int64_values);
492 
493   TestBulkInPlaceNoSwap(uint16_values);
494   TestBulkInPlaceNoSwap(int16_values);
495   TestBulkInPlaceNoSwap(uint32_values);
496   TestBulkInPlaceNoSwap(int32_values);
497   TestBulkInPlaceNoSwap(uint64_values);
498   TestBulkInPlaceNoSwap(int64_values);
499 
500   return 0;
501 }
502