Coverage Report

Created: 2026-09-28 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capnproto/c++/src/capnp/endian.h
Line
Count
Source
1
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
2
// Licensed under the MIT License:
3
//
4
// Permission is hereby granted, free of charge, to any person obtaining a copy
5
// of this software and associated documentation files (the "Software"), to deal
6
// in the Software without restriction, including without limitation the rights
7
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
// copies of the Software, and to permit persons to whom the Software is
9
// furnished to do so, subject to the following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included in
12
// all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
// THE SOFTWARE.
21
22
#pragma once
23
24
#include "common.h"
25
#include <inttypes.h>
26
#include <string.h>  // memcpy
27
28
CAPNP_BEGIN_HEADER
29
30
namespace capnp {
31
namespace _ {  // private
32
33
// WireValue
34
//
35
// Wraps a primitive value as it appears on the wire.  Namely, values are little-endian on the
36
// wire, because little-endian is the most common endianness in modern CPUs.
37
//
38
// Note:  In general, code that depends cares about byte ordering is bad.  See:
39
//     http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
40
//   Cap'n Proto is special because it is essentially doing compiler-like things, fussing over
41
//   allocation and layout of memory, in order to squeeze out every last drop of performance.
42
43
#if _MSC_VER
44
// Assume Windows is little-endian.
45
//
46
// TODO(msvc): This is ugly. Maybe refactor later checks to be based on CAPNP_BYTE_ORDER or
47
//   CAPNP_SWAP_BYTES or something, and define that in turn based on _MSC_VER or the GCC
48
//   intrinsics.
49
50
#ifndef __ORDER_BIG_ENDIAN__
51
#define __ORDER_BIG_ENDIAN__ 4321
52
#endif
53
#ifndef __ORDER_LITTLE_ENDIAN__
54
#define __ORDER_LITTLE_ENDIAN__ 1234
55
#endif
56
#ifndef __BYTE_ORDER__
57
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
58
#endif
59
#endif
60
61
#if CAPNP_REVERSE_ENDIAN
62
#define CAPNP_WIRE_BYTE_ORDER __ORDER_BIG_ENDIAN__
63
#define CAPNP_OPPOSITE_OF_WIRE_BYTE_ORDER __ORDER_LITTLE_ENDIAN__
64
#else
65
#define CAPNP_WIRE_BYTE_ORDER __ORDER_LITTLE_ENDIAN__
66
#define CAPNP_OPPOSITE_OF_WIRE_BYTE_ORDER __ORDER_BIG_ENDIAN__
67
#endif
68
69
#if defined(__BYTE_ORDER__) && \
70
    __BYTE_ORDER__ == CAPNP_WIRE_BYTE_ORDER && \
71
    !CAPNP_DISABLE_ENDIAN_DETECTION
72
// CPU is little-endian.  We can just read/write the memory directly.
73
74
template <typename T>
75
class DirectWireValue {
76
public:
77
594k
  KJ_ALWAYS_INLINE(T get() const) { return value; }
capnp::_::DirectWireValue<signed char>::get() const
Line
Count
Source
77
5.32k
  KJ_ALWAYS_INLINE(T get() const) { return value; }
capnp::_::DirectWireValue<short>::get() const
Line
Count
Source
77
5.13k
  KJ_ALWAYS_INLINE(T get() const) { return value; }
capnp::_::DirectWireValue<int>::get() const
Line
Count
Source
77
4.96k
  KJ_ALWAYS_INLINE(T get() const) { return value; }
capnp::_::DirectWireValue<long>::get() const
Line
Count
Source
77
4.44k
  KJ_ALWAYS_INLINE(T get() const) { return value; }
capnp::_::DirectWireValue<unsigned char>::get() const
Line
Count
Source
77
3.81k
  KJ_ALWAYS_INLINE(T get() const) { return value; }
capnp::_::DirectWireValue<unsigned short>::get() const
Line
Count
Source
77
143k
  KJ_ALWAYS_INLINE(T get() const) { return value; }
capnp::_::DirectWireValue<unsigned int>::get() const
Line
Count
Source
77
396k
  KJ_ALWAYS_INLINE(T get() const) { return value; }
capnp::_::DirectWireValue<unsigned long>::get() const
Line
Count
Source
77
3.28k
  KJ_ALWAYS_INLINE(T get() const) { return value; }
capnp::_::DirectWireValue<float>::get() const
Line
Count
Source
77
4.08k
  KJ_ALWAYS_INLINE(T get() const) { return value; }
capnp::_::DirectWireValue<double>::get() const
Line
Count
Source
77
3.17k
  KJ_ALWAYS_INLINE(T get() const) { return value; }
capnp::_::DirectWireValue<capnp::schemas::TestEnum_9c8e9318b29d9cd3>::get() const
Line
Count
Source
77
1.04k
  KJ_ALWAYS_INLINE(T get() const) { return value; }
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestUnion::Union0::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestUnion::Union1::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestUnion::Union2::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestUnion::Union3::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestUnnamedUnion::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestUnionInUnion::Outer::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestUnionInUnion::Outer::Inner::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestGroups::Groups::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestInterleavedGroups::Group1::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestInterleavedGroups::Group2::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestLateUnion::TheUnion::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestLateUnion::AnotherUnion::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestOldUnionVersion::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestNewUnionVersion::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestNewUnionVersion::A::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestStructUnion::Un::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::RenamedStruct::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schemas::RenamedEnum_f610d1deb4c9e84a>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::RenamedStruct::RenamedUnion::Which>::get() const
capnp::_::DirectWireValue<capnp::schema::Node::Which>::get() const
Line
Count
Source
77
6.77k
  KJ_ALWAYS_INLINE(T get() const) { return value; }
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schemas::ElementSize_d1958f7dba521926>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Field::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Field::Ordinal::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Type::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Type::AnyPointer::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Type::AnyPointer::Unconstrained::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Brand::Scope::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Brand::Binding::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Value::Which>::get() const
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Which>::get() const
capnp::_::DirectWireValue<kj::Id<unsigned int, capnp::_::Segment> >::get() const
Line
Count
Source
77
12.5k
  KJ_ALWAYS_INLINE(T get() const) { return value; }
78
0
  KJ_ALWAYS_INLINE(void set(T newValue)) { value = newValue; }
Unexecuted instantiation: capnp::_::DirectWireValue<signed char>::set(signed char)
Unexecuted instantiation: capnp::_::DirectWireValue<short>::set(short)
Unexecuted instantiation: capnp::_::DirectWireValue<int>::set(int)
Unexecuted instantiation: capnp::_::DirectWireValue<long>::set(long)
Unexecuted instantiation: capnp::_::DirectWireValue<unsigned char>::set(unsigned char)
Unexecuted instantiation: capnp::_::DirectWireValue<unsigned short>::set(unsigned short)
Unexecuted instantiation: capnp::_::DirectWireValue<unsigned int>::set(unsigned int)
Unexecuted instantiation: capnp::_::DirectWireValue<unsigned long>::set(unsigned long)
Unexecuted instantiation: capnp::_::DirectWireValue<float>::set(float)
Unexecuted instantiation: capnp::_::DirectWireValue<double>::set(double)
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schemas::TestEnum_9c8e9318b29d9cd3>::set(capnp::schemas::TestEnum_9c8e9318b29d9cd3)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestUnion::Union0::Which>::set(capnproto_test::capnp::test::TestUnion::Union0::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestUnion::Union1::Which>::set(capnproto_test::capnp::test::TestUnion::Union1::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestUnion::Union2::Which>::set(capnproto_test::capnp::test::TestUnion::Union2::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestUnion::Union3::Which>::set(capnproto_test::capnp::test::TestUnion::Union3::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestUnnamedUnion::Which>::set(capnproto_test::capnp::test::TestUnnamedUnion::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestUnionInUnion::Outer::Which>::set(capnproto_test::capnp::test::TestUnionInUnion::Outer::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestUnionInUnion::Outer::Inner::Which>::set(capnproto_test::capnp::test::TestUnionInUnion::Outer::Inner::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestGroups::Groups::Which>::set(capnproto_test::capnp::test::TestGroups::Groups::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestInterleavedGroups::Group1::Which>::set(capnproto_test::capnp::test::TestInterleavedGroups::Group1::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestInterleavedGroups::Group2::Which>::set(capnproto_test::capnp::test::TestInterleavedGroups::Group2::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestLateUnion::TheUnion::Which>::set(capnproto_test::capnp::test::TestLateUnion::TheUnion::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestLateUnion::AnotherUnion::Which>::set(capnproto_test::capnp::test::TestLateUnion::AnotherUnion::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestOldUnionVersion::Which>::set(capnproto_test::capnp::test::TestOldUnionVersion::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestNewUnionVersion::Which>::set(capnproto_test::capnp::test::TestNewUnionVersion::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestNewUnionVersion::A::Which>::set(capnproto_test::capnp::test::TestNewUnionVersion::A::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::TestStructUnion::Un::Which>::set(capnproto_test::capnp::test::TestStructUnion::Un::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::RenamedStruct::Which>::set(capnproto_test::capnp::test::RenamedStruct::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schemas::RenamedEnum_f610d1deb4c9e84a>::set(capnp::schemas::RenamedEnum_f610d1deb4c9e84a)
Unexecuted instantiation: capnp::_::DirectWireValue<capnproto_test::capnp::test::RenamedStruct::RenamedUnion::Which>::set(capnproto_test::capnp::test::RenamedStruct::RenamedUnion::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Node::Which>::set(capnp::schema::Node::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schemas::ElementSize_d1958f7dba521926>::set(capnp::schemas::ElementSize_d1958f7dba521926)
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Field::Which>::set(capnp::schema::Field::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Field::Ordinal::Which>::set(capnp::schema::Field::Ordinal::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Type::Which>::set(capnp::schema::Type::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Type::AnyPointer::Which>::set(capnp::schema::Type::AnyPointer::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Type::AnyPointer::Unconstrained::Which>::set(capnp::schema::Type::AnyPointer::Unconstrained::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Brand::Scope::Which>::set(capnp::schema::Brand::Scope::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Brand::Binding::Which>::set(capnp::schema::Brand::Binding::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::Value::Which>::set(capnp::schema::Value::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Which>::set(capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Which)
Unexecuted instantiation: capnp::_::DirectWireValue<kj::Id<unsigned int, capnp::_::Segment> >::set(kj::Id<unsigned int, capnp::_::Segment>)
79
80
private:
81
  T value;
82
};
83
84
template <typename T>
85
using WireValue = DirectWireValue<T>;
86
// To prevent ODR problems when endian-test, endian-reverse-test, and endian-fallback-test are
87
// linked together, we define each implementation with a different name and define an alias to the
88
// one we want to use.
89
90
#elif defined(__BYTE_ORDER__) && \
91
      __BYTE_ORDER__ == CAPNP_OPPOSITE_OF_WIRE_BYTE_ORDER && \
92
      defined(__GNUC__) && !CAPNP_DISABLE_ENDIAN_DETECTION
93
// Big-endian, but GCC's __builtin_bswap() is available.
94
95
// TODO(perf):  Use dedicated instructions to read little-endian data on big-endian CPUs that have
96
//   them.
97
98
// TODO(perf):  Verify that this code optimizes reasonably.  In particular, ensure that the
99
//   compiler optimizes away the byte copies and keeps everything in registers.
100
101
template <typename T, size_t size = sizeof(T)>
102
class SwappingWireValue;
103
104
template <typename T>
105
class SwappingWireValue<T, 1> {
106
public:
107
  KJ_ALWAYS_INLINE(T get() const) { return value; }
108
  KJ_ALWAYS_INLINE(void set(T newValue)) { value = newValue; }
109
110
private:
111
  T value;
112
};
113
114
template <typename T>
115
class SwappingWireValue<T, 2> {
116
public:
117
  KJ_ALWAYS_INLINE(T get() const) {
118
    // Not all platforms have __builtin_bswap16() for some reason.  In particular, it is missing
119
    // on gcc-4.7.3-cygwin32 (but present on gcc-4.8.1-cygwin64).
120
    uint16_t swapped = (value << 8) | (value >> 8);
121
    T result;
122
    kj::asBytes(result).copyFrom(kj::asBytes(swapped));
123
    return result;
124
  }
125
  KJ_ALWAYS_INLINE(void set(T newValue)) {
126
    uint16_t raw;
127
    kj::asBytes(raw).copyFrom(kj::asBytes(newValue));
128
    // Not all platforms have __builtin_bswap16() for some reason.  In particular, it is missing
129
    // on gcc-4.7.3-cygwin32 (but present on gcc-4.8.1-cygwin64).
130
    value = (raw << 8) | (raw >> 8);
131
  }
132
133
private:
134
  uint16_t value;
135
};
136
137
template <typename T>
138
class SwappingWireValue<T, 4> {
139
public:
140
  KJ_ALWAYS_INLINE(T get() const) {
141
    uint32_t swapped = __builtin_bswap32(value);
142
    T result;
143
    kj::asBytes(result).copyFrom(kj::asBytes(swapped));
144
    return result;
145
  }
146
  KJ_ALWAYS_INLINE(void set(T newValue)) {
147
    uint32_t raw;
148
    kj::asBytes(raw).copyFrom(kj::asBytes(newValue));
149
    value = __builtin_bswap32(raw);
150
  }
151
152
private:
153
  uint32_t value;
154
};
155
156
template <typename T>
157
class SwappingWireValue<T, 8> {
158
public:
159
  KJ_ALWAYS_INLINE(T get() const) {
160
    uint64_t swapped = __builtin_bswap64(value);
161
    T result;
162
    kj::asBytes(result).copyFrom(kj::asBytes(swapped));
163
    return result;
164
  }
165
  KJ_ALWAYS_INLINE(void set(T newValue)) {
166
    uint64_t raw;
167
    kj::asBytes(raw).copyFrom(kj::asBytes(newValue));
168
    value = __builtin_bswap64(raw);
169
  }
170
171
private:
172
  uint64_t value;
173
};
174
175
template <typename T>
176
using WireValue = SwappingWireValue<T>;
177
// To prevent ODR problems when endian-test, endian-reverse-test, and endian-fallback-test are
178
// linked together, we define each implementation with a different name and define an alias to the
179
// one we want to use.
180
181
#else
182
// Unknown endianness.  Fall back to bit shifts.
183
184
#if !CAPNP_DISABLE_ENDIAN_DETECTION
185
#if _MSC_VER
186
#pragma message("Couldn't detect endianness of your platform.  Using unoptimized fallback implementation.")
187
#pragma message("Consider changing this code to detect your platform and send us a patch!")
188
#else
189
#warning "Couldn't detect endianness of your platform.  Using unoptimized fallback implementation."
190
#warning "Consider changing this code to detect your platform and send us a patch!"
191
#endif
192
#endif  // !CAPNP_DISABLE_ENDIAN_DETECTION
193
194
template <typename T, size_t size = sizeof(T)>
195
class ShiftingWireValue;
196
197
template <typename T>
198
class ShiftingWireValue<T, 1> {
199
public:
200
  KJ_ALWAYS_INLINE(T get() const) { return value; }
201
  KJ_ALWAYS_INLINE(void set(T newValue)) { value = newValue; }
202
203
private:
204
  T value;
205
};
206
207
template <typename T>
208
class ShiftingWireValue<T, 2> {
209
public:
210
  KJ_ALWAYS_INLINE(T get() const) {
211
    uint16_t raw = (static_cast<uint16_t>(bytes[0])     ) |
212
                   (static_cast<uint16_t>(bytes[1]) << 8);
213
    T result;
214
    kj::asBytes(result).copyFrom(kj::asBytes(raw));
215
    return result;
216
  }
217
  KJ_ALWAYS_INLINE(void set(T newValue)) {
218
    uint16_t raw;
219
    kj::asBytes(raw).copyFrom(kj::asBytes(newValue));
220
    bytes[0] = raw;
221
    bytes[1] = raw >> 8;
222
  }
223
224
private:
225
  union {
226
    byte bytes[2];
227
    uint16_t align;
228
  };
229
};
230
231
template <typename T>
232
class ShiftingWireValue<T, 4> {
233
public:
234
  KJ_ALWAYS_INLINE(T get() const) {
235
    uint32_t raw = (static_cast<uint32_t>(bytes[0])      ) |
236
                   (static_cast<uint32_t>(bytes[1]) <<  8) |
237
                   (static_cast<uint32_t>(bytes[2]) << 16) |
238
                   (static_cast<uint32_t>(bytes[3]) << 24);
239
    T result;
240
    kj::asBytes(result).copyFrom(kj::asBytes(raw));
241
    return result;
242
  }
243
  KJ_ALWAYS_INLINE(void set(T newValue)) {
244
    uint32_t raw;
245
    kj::asBytes(raw).copyFrom(kj::asBytes(newValue));
246
    bytes[0] = raw;
247
    bytes[1] = raw >> 8;
248
    bytes[2] = raw >> 16;
249
    bytes[3] = raw >> 24;
250
  }
251
252
private:
253
  union {
254
    byte bytes[4];
255
    uint32_t align;
256
  };
257
};
258
259
template <typename T>
260
class ShiftingWireValue<T, 8> {
261
public:
262
  KJ_ALWAYS_INLINE(T get() const) {
263
    uint64_t raw = (static_cast<uint64_t>(bytes[0])      ) |
264
                   (static_cast<uint64_t>(bytes[1]) <<  8) |
265
                   (static_cast<uint64_t>(bytes[2]) << 16) |
266
                   (static_cast<uint64_t>(bytes[3]) << 24) |
267
                   (static_cast<uint64_t>(bytes[4]) << 32) |
268
                   (static_cast<uint64_t>(bytes[5]) << 40) |
269
                   (static_cast<uint64_t>(bytes[6]) << 48) |
270
                   (static_cast<uint64_t>(bytes[7]) << 56);
271
    T result;
272
    kj::asBytes(result).copyFrom(kj::asBytes(raw));
273
    return result;
274
  }
275
  KJ_ALWAYS_INLINE(void set(T newValue)) {
276
    uint64_t raw;
277
    kj::asBytes(raw).copyFrom(kj::asBytes(newValue));
278
    bytes[0] = raw;
279
    bytes[1] = raw >> 8;
280
    bytes[2] = raw >> 16;
281
    bytes[3] = raw >> 24;
282
    bytes[4] = raw >> 32;
283
    bytes[5] = raw >> 40;
284
    bytes[6] = raw >> 48;
285
    bytes[7] = raw >> 56;
286
  }
287
288
private:
289
  union {
290
    byte bytes[8];
291
    uint64_t align;
292
  };
293
};
294
295
template <typename T>
296
using WireValue = ShiftingWireValue<T>;
297
// To prevent ODR problems when endian-test, endian-reverse-test, and endian-fallback-test are
298
// linked together, we define each implementation with a different name and define an alias to the
299
// one we want to use.
300
301
#endif
302
303
}  // namespace _ (private)
304
}  // namespace capnp
305
306
CAPNP_END_HEADER