1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 /*
21  * Simple helpers for handling typical byte order-related issues.
22  */
23 module thrift.internal.endian;
24 
25 import core.bitop : bswap;
26 import std.traits : isIntegral;
27 
28 union IntBuf(T) {
29   ubyte[T.sizeof] bytes;
30   T value;
31 }
32 
33 T byteSwap(T)(T t) pure nothrow @trusted if (isIntegral!T) {
34   static if (T.sizeof == 2) {
35     return cast(T)((t & 0xff) << 8) | cast(T)((t & 0xff00) >> 8);
36   } else static if (T.sizeof == 4) {
37     return cast(T)bswap(cast(uint)t);
38   } else static if (T.sizeof == 8) {
39     return cast(T)byteSwap(cast(uint)(t & 0xffffffff)) << 32 |
40       cast(T)bswap(cast(uint)(t >> 32));
41   } else static assert(false, "Type of size " ~ to!string(T.sizeof) ~ " not supported.");
42 }
43 
44 T doNothing(T)(T val) { return val; }
45 
46 version (BigEndian) {
47   alias doNothing hostToNet;
48   alias doNothing netToHost;
49   alias byteSwap hostToLe;
50   alias byteSwap leToHost;
51 } else {
52   alias byteSwap hostToNet;
53   alias byteSwap netToHost;
54   alias doNothing hostToLe;
55   alias doNothing leToHost;
56 }
57 
58 unittest {
59   import std.exception;
60 
61   IntBuf!short s;
62   s.bytes = [1, 2];
63   s.value = byteSwap(s.value);
64   enforce(s.bytes == [2, 1]);
65 
66   IntBuf!int i;
67   i.bytes = [1, 2, 3, 4];
68   i.value = byteSwap(i.value);
69   enforce(i.bytes == [4, 3, 2, 1]);
70 
71   IntBuf!long l;
72   l.bytes = [1, 2, 3, 4, 5, 6, 7, 8];
73   l.value = byteSwap(l.value);
74   enforce(l.bytes == [8, 7, 6, 5, 4, 3, 2, 1]);
75 }