blob: 33b72bd372e345e7e64b11ed1ffa75e413285efe [file] [log] [blame]
Austin Schuh36244a12019-09-21 17:52:38 -07001// Copyright 2018 The Abseil Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "absl/container/internal/layout.h"
16
17// We need ::max_align_t because some libstdc++ versions don't provide
18// std::max_align_t
19#include <stddef.h>
20#include <cstdint>
21#include <memory>
22#include <sstream>
23#include <type_traits>
24
25#include "gmock/gmock.h"
26#include "gtest/gtest.h"
27#include "absl/base/internal/raw_logging.h"
28#include "absl/types/span.h"
29
30namespace absl {
31namespace container_internal {
32namespace {
33
34using ::absl::Span;
35using ::testing::ElementsAre;
36
37size_t Distance(const void* from, const void* to) {
38 ABSL_RAW_CHECK(from <= to, "Distance must be non-negative");
39 return static_cast<const char*>(to) - static_cast<const char*>(from);
40}
41
42template <class Expected, class Actual>
43Expected Type(Actual val) {
44 static_assert(std::is_same<Expected, Actual>(), "");
45 return val;
46}
47
48// Helper classes to test different size and alignments.
49struct alignas(8) Int128 {
50 uint64_t a, b;
51 friend bool operator==(Int128 lhs, Int128 rhs) {
52 return std::tie(lhs.a, lhs.b) == std::tie(rhs.a, rhs.b);
53 }
54
55 static std::string Name() {
56 return internal_layout::adl_barrier::TypeName<Int128>();
57 }
58};
59
60// int64_t is *not* 8-byte aligned on all platforms!
61struct alignas(8) Int64 {
62 int64_t a;
63 friend bool operator==(Int64 lhs, Int64 rhs) {
64 return lhs.a == rhs.a;
65 }
66};
67
68// Properties of types that this test relies on.
69static_assert(sizeof(int8_t) == 1, "");
70static_assert(alignof(int8_t) == 1, "");
71static_assert(sizeof(int16_t) == 2, "");
72static_assert(alignof(int16_t) == 2, "");
73static_assert(sizeof(int32_t) == 4, "");
74static_assert(alignof(int32_t) == 4, "");
75static_assert(sizeof(Int64) == 8, "");
76static_assert(alignof(Int64) == 8, "");
77static_assert(sizeof(Int128) == 16, "");
78static_assert(alignof(Int128) == 8, "");
79
80template <class Expected, class Actual>
81void SameType() {
82 static_assert(std::is_same<Expected, Actual>(), "");
83}
84
85TEST(Layout, ElementType) {
86 {
87 using L = Layout<int32_t>;
88 SameType<int32_t, L::ElementType<0>>();
89 SameType<int32_t, decltype(L::Partial())::ElementType<0>>();
90 SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>();
91 }
92 {
93 using L = Layout<int32_t, int32_t>;
94 SameType<int32_t, L::ElementType<0>>();
95 SameType<int32_t, L::ElementType<1>>();
96 SameType<int32_t, decltype(L::Partial())::ElementType<0>>();
97 SameType<int32_t, decltype(L::Partial())::ElementType<1>>();
98 SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>();
99 SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>();
100 }
101 {
102 using L = Layout<int8_t, int32_t, Int128>;
103 SameType<int8_t, L::ElementType<0>>();
104 SameType<int32_t, L::ElementType<1>>();
105 SameType<Int128, L::ElementType<2>>();
106 SameType<int8_t, decltype(L::Partial())::ElementType<0>>();
107 SameType<int8_t, decltype(L::Partial(0))::ElementType<0>>();
108 SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>();
109 SameType<int8_t, decltype(L::Partial(0, 0))::ElementType<0>>();
110 SameType<int32_t, decltype(L::Partial(0, 0))::ElementType<1>>();
111 SameType<Int128, decltype(L::Partial(0, 0))::ElementType<2>>();
112 SameType<int8_t, decltype(L::Partial(0, 0, 0))::ElementType<0>>();
113 SameType<int32_t, decltype(L::Partial(0, 0, 0))::ElementType<1>>();
114 SameType<Int128, decltype(L::Partial(0, 0, 0))::ElementType<2>>();
115 }
116}
117
118TEST(Layout, ElementTypes) {
119 {
120 using L = Layout<int32_t>;
121 SameType<std::tuple<int32_t>, L::ElementTypes>();
122 SameType<std::tuple<int32_t>, decltype(L::Partial())::ElementTypes>();
123 SameType<std::tuple<int32_t>, decltype(L::Partial(0))::ElementTypes>();
124 }
125 {
126 using L = Layout<int32_t, int32_t>;
127 SameType<std::tuple<int32_t, int32_t>, L::ElementTypes>();
128 SameType<std::tuple<int32_t, int32_t>, decltype(L::Partial())::ElementTypes>();
129 SameType<std::tuple<int32_t, int32_t>, decltype(L::Partial(0))::ElementTypes>();
130 }
131 {
132 using L = Layout<int8_t, int32_t, Int128>;
133 SameType<std::tuple<int8_t, int32_t, Int128>, L::ElementTypes>();
134 SameType<std::tuple<int8_t, int32_t, Int128>,
135 decltype(L::Partial())::ElementTypes>();
136 SameType<std::tuple<int8_t, int32_t, Int128>,
137 decltype(L::Partial(0))::ElementTypes>();
138 SameType<std::tuple<int8_t, int32_t, Int128>,
139 decltype(L::Partial(0, 0))::ElementTypes>();
140 SameType<std::tuple<int8_t, int32_t, Int128>,
141 decltype(L::Partial(0, 0, 0))::ElementTypes>();
142 }
143}
144
145TEST(Layout, OffsetByIndex) {
146 {
147 using L = Layout<int32_t>;
148 EXPECT_EQ(0, L::Partial().Offset<0>());
149 EXPECT_EQ(0, L::Partial(3).Offset<0>());
150 EXPECT_EQ(0, L(3).Offset<0>());
151 }
152 {
153 using L = Layout<int32_t, int32_t>;
154 EXPECT_EQ(0, L::Partial().Offset<0>());
155 EXPECT_EQ(0, L::Partial(3).Offset<0>());
156 EXPECT_EQ(12, L::Partial(3).Offset<1>());
157 EXPECT_EQ(0, L::Partial(3, 5).Offset<0>());
158 EXPECT_EQ(12, L::Partial(3, 5).Offset<1>());
159 EXPECT_EQ(0, L(3, 5).Offset<0>());
160 EXPECT_EQ(12, L(3, 5).Offset<1>());
161 }
162 {
163 using L = Layout<int8_t, int32_t, Int128>;
164 EXPECT_EQ(0, L::Partial().Offset<0>());
165 EXPECT_EQ(0, L::Partial(0).Offset<0>());
166 EXPECT_EQ(0, L::Partial(0).Offset<1>());
167 EXPECT_EQ(0, L::Partial(1).Offset<0>());
168 EXPECT_EQ(4, L::Partial(1).Offset<1>());
169 EXPECT_EQ(0, L::Partial(5).Offset<0>());
170 EXPECT_EQ(8, L::Partial(5).Offset<1>());
171 EXPECT_EQ(0, L::Partial(0, 0).Offset<0>());
172 EXPECT_EQ(0, L::Partial(0, 0).Offset<1>());
173 EXPECT_EQ(0, L::Partial(0, 0).Offset<2>());
174 EXPECT_EQ(0, L::Partial(1, 0).Offset<0>());
175 EXPECT_EQ(4, L::Partial(1, 0).Offset<1>());
176 EXPECT_EQ(8, L::Partial(1, 0).Offset<2>());
177 EXPECT_EQ(0, L::Partial(5, 3).Offset<0>());
178 EXPECT_EQ(8, L::Partial(5, 3).Offset<1>());
179 EXPECT_EQ(24, L::Partial(5, 3).Offset<2>());
180 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<0>());
181 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<1>());
182 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<2>());
183 EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<0>());
184 EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<1>());
185 EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<2>());
186 EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<0>());
187 EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<2>());
188 EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<1>());
189 EXPECT_EQ(0, L(5, 3, 1).Offset<0>());
190 EXPECT_EQ(24, L(5, 3, 1).Offset<2>());
191 EXPECT_EQ(8, L(5, 3, 1).Offset<1>());
192 }
193}
194
195TEST(Layout, OffsetByType) {
196 {
197 using L = Layout<int32_t>;
198 EXPECT_EQ(0, L::Partial().Offset<int32_t>());
199 EXPECT_EQ(0, L::Partial(3).Offset<int32_t>());
200 EXPECT_EQ(0, L(3).Offset<int32_t>());
201 }
202 {
203 using L = Layout<int8_t, int32_t, Int128>;
204 EXPECT_EQ(0, L::Partial().Offset<int8_t>());
205 EXPECT_EQ(0, L::Partial(0).Offset<int8_t>());
206 EXPECT_EQ(0, L::Partial(0).Offset<int32_t>());
207 EXPECT_EQ(0, L::Partial(1).Offset<int8_t>());
208 EXPECT_EQ(4, L::Partial(1).Offset<int32_t>());
209 EXPECT_EQ(0, L::Partial(5).Offset<int8_t>());
210 EXPECT_EQ(8, L::Partial(5).Offset<int32_t>());
211 EXPECT_EQ(0, L::Partial(0, 0).Offset<int8_t>());
212 EXPECT_EQ(0, L::Partial(0, 0).Offset<int32_t>());
213 EXPECT_EQ(0, L::Partial(0, 0).Offset<Int128>());
214 EXPECT_EQ(0, L::Partial(1, 0).Offset<int8_t>());
215 EXPECT_EQ(4, L::Partial(1, 0).Offset<int32_t>());
216 EXPECT_EQ(8, L::Partial(1, 0).Offset<Int128>());
217 EXPECT_EQ(0, L::Partial(5, 3).Offset<int8_t>());
218 EXPECT_EQ(8, L::Partial(5, 3).Offset<int32_t>());
219 EXPECT_EQ(24, L::Partial(5, 3).Offset<Int128>());
220 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int8_t>());
221 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int32_t>());
222 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<Int128>());
223 EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<int8_t>());
224 EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<int32_t>());
225 EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<Int128>());
226 EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<int8_t>());
227 EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<Int128>());
228 EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<int32_t>());
229 EXPECT_EQ(0, L(5, 3, 1).Offset<int8_t>());
230 EXPECT_EQ(24, L(5, 3, 1).Offset<Int128>());
231 EXPECT_EQ(8, L(5, 3, 1).Offset<int32_t>());
232 }
233}
234
235TEST(Layout, Offsets) {
236 {
237 using L = Layout<int32_t>;
238 EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
239 EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0));
240 EXPECT_THAT(L(3).Offsets(), ElementsAre(0));
241 }
242 {
243 using L = Layout<int32_t, int32_t>;
244 EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
245 EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0, 12));
246 EXPECT_THAT(L::Partial(3, 5).Offsets(), ElementsAre(0, 12));
247 EXPECT_THAT(L(3, 5).Offsets(), ElementsAre(0, 12));
248 }
249 {
250 using L = Layout<int8_t, int32_t, Int128>;
251 EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
252 EXPECT_THAT(L::Partial(1).Offsets(), ElementsAre(0, 4));
253 EXPECT_THAT(L::Partial(5).Offsets(), ElementsAre(0, 8));
254 EXPECT_THAT(L::Partial(0, 0).Offsets(), ElementsAre(0, 0, 0));
255 EXPECT_THAT(L::Partial(1, 0).Offsets(), ElementsAre(0, 4, 8));
256 EXPECT_THAT(L::Partial(5, 3).Offsets(), ElementsAre(0, 8, 24));
257 EXPECT_THAT(L::Partial(0, 0, 0).Offsets(), ElementsAre(0, 0, 0));
258 EXPECT_THAT(L::Partial(1, 0, 0).Offsets(), ElementsAre(0, 4, 8));
259 EXPECT_THAT(L::Partial(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
260 EXPECT_THAT(L(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
261 }
262}
263
264TEST(Layout, AllocSize) {
265 {
266 using L = Layout<int32_t>;
267 EXPECT_EQ(0, L::Partial(0).AllocSize());
268 EXPECT_EQ(12, L::Partial(3).AllocSize());
269 EXPECT_EQ(12, L(3).AllocSize());
270 }
271 {
272 using L = Layout<int32_t, int32_t>;
273 EXPECT_EQ(32, L::Partial(3, 5).AllocSize());
274 EXPECT_EQ(32, L(3, 5).AllocSize());
275 }
276 {
277 using L = Layout<int8_t, int32_t, Int128>;
278 EXPECT_EQ(0, L::Partial(0, 0, 0).AllocSize());
279 EXPECT_EQ(8, L::Partial(1, 0, 0).AllocSize());
280 EXPECT_EQ(8, L::Partial(0, 1, 0).AllocSize());
281 EXPECT_EQ(16, L::Partial(0, 0, 1).AllocSize());
282 EXPECT_EQ(24, L::Partial(1, 1, 1).AllocSize());
283 EXPECT_EQ(136, L::Partial(3, 5, 7).AllocSize());
284 EXPECT_EQ(136, L(3, 5, 7).AllocSize());
285 }
286}
287
288TEST(Layout, SizeByIndex) {
289 {
290 using L = Layout<int32_t>;
291 EXPECT_EQ(0, L::Partial(0).Size<0>());
292 EXPECT_EQ(3, L::Partial(3).Size<0>());
293 EXPECT_EQ(3, L(3).Size<0>());
294 }
295 {
296 using L = Layout<int32_t, int32_t>;
297 EXPECT_EQ(0, L::Partial(0).Size<0>());
298 EXPECT_EQ(3, L::Partial(3).Size<0>());
299 EXPECT_EQ(3, L::Partial(3, 5).Size<0>());
300 EXPECT_EQ(5, L::Partial(3, 5).Size<1>());
301 EXPECT_EQ(3, L(3, 5).Size<0>());
302 EXPECT_EQ(5, L(3, 5).Size<1>());
303 }
304 {
305 using L = Layout<int8_t, int32_t, Int128>;
306 EXPECT_EQ(3, L::Partial(3).Size<0>());
307 EXPECT_EQ(3, L::Partial(3, 5).Size<0>());
308 EXPECT_EQ(5, L::Partial(3, 5).Size<1>());
309 EXPECT_EQ(3, L::Partial(3, 5, 7).Size<0>());
310 EXPECT_EQ(5, L::Partial(3, 5, 7).Size<1>());
311 EXPECT_EQ(7, L::Partial(3, 5, 7).Size<2>());
312 EXPECT_EQ(3, L(3, 5, 7).Size<0>());
313 EXPECT_EQ(5, L(3, 5, 7).Size<1>());
314 EXPECT_EQ(7, L(3, 5, 7).Size<2>());
315 }
316}
317
318TEST(Layout, SizeByType) {
319 {
320 using L = Layout<int32_t>;
321 EXPECT_EQ(0, L::Partial(0).Size<int32_t>());
322 EXPECT_EQ(3, L::Partial(3).Size<int32_t>());
323 EXPECT_EQ(3, L(3).Size<int32_t>());
324 }
325 {
326 using L = Layout<int8_t, int32_t, Int128>;
327 EXPECT_EQ(3, L::Partial(3).Size<int8_t>());
328 EXPECT_EQ(3, L::Partial(3, 5).Size<int8_t>());
329 EXPECT_EQ(5, L::Partial(3, 5).Size<int32_t>());
330 EXPECT_EQ(3, L::Partial(3, 5, 7).Size<int8_t>());
331 EXPECT_EQ(5, L::Partial(3, 5, 7).Size<int32_t>());
332 EXPECT_EQ(7, L::Partial(3, 5, 7).Size<Int128>());
333 EXPECT_EQ(3, L(3, 5, 7).Size<int8_t>());
334 EXPECT_EQ(5, L(3, 5, 7).Size<int32_t>());
335 EXPECT_EQ(7, L(3, 5, 7).Size<Int128>());
336 }
337}
338
339TEST(Layout, Sizes) {
340 {
341 using L = Layout<int32_t>;
342 EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
343 EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
344 EXPECT_THAT(L(3).Sizes(), ElementsAre(3));
345 }
346 {
347 using L = Layout<int32_t, int32_t>;
348 EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
349 EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
350 EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5));
351 EXPECT_THAT(L(3, 5).Sizes(), ElementsAre(3, 5));
352 }
353 {
354 using L = Layout<int8_t, int32_t, Int128>;
355 EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
356 EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
357 EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5));
358 EXPECT_THAT(L::Partial(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
359 EXPECT_THAT(L(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
360 }
361}
362
363TEST(Layout, PointerByIndex) {
364 alignas(max_align_t) const unsigned char p[100] = {};
365 {
366 using L = Layout<int32_t>;
367 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
368 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
369 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<0>(p))));
370 }
371 {
372 using L = Layout<int32_t, int32_t>;
373 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
374 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
375 EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p))));
376 EXPECT_EQ(0,
377 Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
378 EXPECT_EQ(12,
379 Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
380 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<0>(p))));
381 EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<1>(p))));
382 }
383 {
384 using L = Layout<int8_t, int32_t, Int128>;
385 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<0>(p))));
386 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<0>(p))));
387 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p))));
388 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<0>(p))));
389 EXPECT_EQ(4, Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p))));
390 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<0>(p))));
391 EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p))));
392 EXPECT_EQ(0,
393 Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
394 EXPECT_EQ(0,
395 Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
396 EXPECT_EQ(0,
397 Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<2>(p))));
398 EXPECT_EQ(0,
399 Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
400 EXPECT_EQ(4,
401 Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
402 EXPECT_EQ(8,
403 Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<2>(p))));
404 EXPECT_EQ(0,
405 Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
406 EXPECT_EQ(8,
407 Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
408 EXPECT_EQ(24,
409 Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<2>(p))));
410 EXPECT_EQ(
411 0, Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
412 EXPECT_EQ(
413 0, Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
414 EXPECT_EQ(
415 0, Distance(p, Type<const Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
416 EXPECT_EQ(
417 0, Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
418 EXPECT_EQ(
419 4, Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
420 EXPECT_EQ(
421 8, Distance(p, Type<const Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
422 EXPECT_EQ(
423 0, Distance(p, Type<const int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
424 EXPECT_EQ(
425 24,
426 Distance(p, Type<const Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
427 EXPECT_EQ(
428 8, Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
429 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L(5, 3, 1).Pointer<0>(p))));
430 EXPECT_EQ(24, Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<2>(p))));
431 EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<1>(p))));
432 }
433}
434
435TEST(Layout, PointerByType) {
436 alignas(max_align_t) const unsigned char p[100] = {};
437 {
438 using L = Layout<int32_t>;
439 EXPECT_EQ(0,
440 Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p))));
441 EXPECT_EQ(0,
442 Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
443 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<int32_t>(p))));
444 }
445 {
446 using L = Layout<int8_t, int32_t, Int128>;
447 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p))));
448 EXPECT_EQ(0,
449 Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
450 EXPECT_EQ(0,
451 Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
452 EXPECT_EQ(0,
453 Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
454 EXPECT_EQ(4,
455 Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
456 EXPECT_EQ(0,
457 Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
458 EXPECT_EQ(8,
459 Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
460 EXPECT_EQ(
461 0, Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
462 EXPECT_EQ(
463 0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
464 EXPECT_EQ(
465 0,
466 Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
467 EXPECT_EQ(
468 0, Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
469 EXPECT_EQ(
470 4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
471 EXPECT_EQ(
472 8,
473 Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
474 EXPECT_EQ(
475 0, Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
476 EXPECT_EQ(
477 8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
478 EXPECT_EQ(
479 24,
480 Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
481 EXPECT_EQ(
482 0,
483 Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
484 EXPECT_EQ(
485 0,
486 Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
487 EXPECT_EQ(0, Distance(p, Type<const Int128*>(
488 L::Partial(0, 0, 0).Pointer<Int128>(p))));
489 EXPECT_EQ(
490 0,
491 Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
492 EXPECT_EQ(
493 4,
494 Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
495 EXPECT_EQ(8, Distance(p, Type<const Int128*>(
496 L::Partial(1, 0, 0).Pointer<Int128>(p))));
497 EXPECT_EQ(
498 0,
499 Distance(p, Type<const int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
500 EXPECT_EQ(24, Distance(p, Type<const Int128*>(
501 L::Partial(5, 3, 1).Pointer<Int128>(p))));
502 EXPECT_EQ(
503 8,
504 Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
505 EXPECT_EQ(24,
506 Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
507 EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
508 }
509}
510
511TEST(Layout, MutablePointerByIndex) {
512 alignas(max_align_t) unsigned char p[100];
513 {
514 using L = Layout<int32_t>;
515 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p))));
516 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p))));
517 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<0>(p))));
518 }
519 {
520 using L = Layout<int32_t, int32_t>;
521 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p))));
522 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p))));
523 EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<1>(p))));
524 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
525 EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
526 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3, 5).Pointer<0>(p))));
527 EXPECT_EQ(12, Distance(p, Type<int32_t*>(L(3, 5).Pointer<1>(p))));
528 }
529 {
530 using L = Layout<int8_t, int32_t, Int128>;
531 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<0>(p))));
532 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<0>(p))));
533 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0).Pointer<1>(p))));
534 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<0>(p))));
535 EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1).Pointer<1>(p))));
536 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<0>(p))));
537 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5).Pointer<1>(p))));
538 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
539 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
540 EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<2>(p))));
541 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
542 EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
543 EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<2>(p))));
544 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
545 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
546 EXPECT_EQ(24, Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<2>(p))));
547 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
548 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
549 EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
550 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
551 EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
552 EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
553 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
554 EXPECT_EQ(24,
555 Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
556 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
557 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<0>(p))));
558 EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<2>(p))));
559 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<1>(p))));
560 }
561}
562
563TEST(Layout, MutablePointerByType) {
564 alignas(max_align_t) unsigned char p[100];
565 {
566 using L = Layout<int32_t>;
567 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<int32_t>(p))));
568 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
569 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<int32_t>(p))));
570 }
571 {
572 using L = Layout<int8_t, int32_t, Int128>;
573 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<int8_t>(p))));
574 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
575 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
576 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
577 EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
578 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
579 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
580 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
581 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
582 EXPECT_EQ(0,
583 Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
584 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
585 EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
586 EXPECT_EQ(8,
587 Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
588 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
589 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
590 EXPECT_EQ(24,
591 Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
592 EXPECT_EQ(0,
593 Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
594 EXPECT_EQ(0,
595 Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
596 EXPECT_EQ(
597 0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<Int128>(p))));
598 EXPECT_EQ(0,
599 Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
600 EXPECT_EQ(4,
601 Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
602 EXPECT_EQ(
603 8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<Int128>(p))));
604 EXPECT_EQ(0,
605 Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
606 EXPECT_EQ(
607 24, Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<Int128>(p))));
608 EXPECT_EQ(8,
609 Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
610 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<int8_t>(p))));
611 EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
612 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
613 }
614}
615
616TEST(Layout, Pointers) {
617 alignas(max_align_t) const unsigned char p[100] = {};
618 using L = Layout<int8_t, int8_t, Int128>;
619 {
620 const auto x = L::Partial();
621 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),
622 Type<std::tuple<const int8_t*>>(x.Pointers(p)));
623 }
624 {
625 const auto x = L::Partial(1);
626 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
627 (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p))));
628 }
629 {
630 const auto x = L::Partial(1, 2);
631 EXPECT_EQ(
632 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
633 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
634 x.Pointers(p))));
635 }
636 {
637 const auto x = L::Partial(1, 2, 3);
638 EXPECT_EQ(
639 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
640 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
641 x.Pointers(p))));
642 }
643 {
644 const L x(1, 2, 3);
645 EXPECT_EQ(
646 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
647 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
648 x.Pointers(p))));
649 }
650}
651
652TEST(Layout, MutablePointers) {
653 alignas(max_align_t) unsigned char p[100];
654 using L = Layout<int8_t, int8_t, Int128>;
655 {
656 const auto x = L::Partial();
657 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),
658 Type<std::tuple<int8_t*>>(x.Pointers(p)));
659 }
660 {
661 const auto x = L::Partial(1);
662 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
663 (Type<std::tuple<int8_t*, int8_t*>>(x.Pointers(p))));
664 }
665 {
666 const auto x = L::Partial(1, 2);
667 EXPECT_EQ(
668 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
669 (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
670 }
671 {
672 const auto x = L::Partial(1, 2, 3);
673 EXPECT_EQ(
674 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
675 (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
676 }
677 {
678 const L x(1, 2, 3);
679 EXPECT_EQ(
680 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
681 (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
682 }
683}
684
685TEST(Layout, SliceByIndexSize) {
686 alignas(max_align_t) const unsigned char p[100] = {};
687 {
688 using L = Layout<int32_t>;
689 EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size());
690 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
691 EXPECT_EQ(3, L(3).Slice<0>(p).size());
692 }
693 {
694 using L = Layout<int32_t, int32_t>;
695 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
696 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
697 EXPECT_EQ(5, L(3, 5).Slice<1>(p).size());
698 }
699 {
700 using L = Layout<int8_t, int32_t, Int128>;
701 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
702 EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size());
703 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
704 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size());
705 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size());
706 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size());
707 EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size());
708 EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size());
709 EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size());
710 }
711}
712
713TEST(Layout, SliceByTypeSize) {
714 alignas(max_align_t) const unsigned char p[100] = {};
715 {
716 using L = Layout<int32_t>;
717 EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size());
718 EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size());
719 EXPECT_EQ(3, L(3).Slice<int32_t>(p).size());
720 }
721 {
722 using L = Layout<int8_t, int32_t, Int128>;
723 EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size());
724 EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size());
725 EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size());
726 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size());
727 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size());
728 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size());
729 EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size());
730 EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size());
731 EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size());
732 }
733}
734
735TEST(Layout, MutableSliceByIndexSize) {
736 alignas(max_align_t) unsigned char p[100];
737 {
738 using L = Layout<int32_t>;
739 EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size());
740 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
741 EXPECT_EQ(3, L(3).Slice<0>(p).size());
742 }
743 {
744 using L = Layout<int32_t, int32_t>;
745 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
746 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
747 EXPECT_EQ(5, L(3, 5).Slice<1>(p).size());
748 }
749 {
750 using L = Layout<int8_t, int32_t, Int128>;
751 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
752 EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size());
753 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
754 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size());
755 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size());
756 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size());
757 EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size());
758 EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size());
759 EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size());
760 }
761}
762
763TEST(Layout, MutableSliceByTypeSize) {
764 alignas(max_align_t) unsigned char p[100];
765 {
766 using L = Layout<int32_t>;
767 EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size());
768 EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size());
769 EXPECT_EQ(3, L(3).Slice<int32_t>(p).size());
770 }
771 {
772 using L = Layout<int8_t, int32_t, Int128>;
773 EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size());
774 EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size());
775 EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size());
776 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size());
777 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size());
778 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size());
779 EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size());
780 EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size());
781 EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size());
782 }
783}
784
785TEST(Layout, SliceByIndexData) {
786 alignas(max_align_t) const unsigned char p[100] = {};
787 {
788 using L = Layout<int32_t>;
789 EXPECT_EQ(
790 0,
791 Distance(p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data()));
792 EXPECT_EQ(
793 0,
794 Distance(p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
795 EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data()));
796 }
797 {
798 using L = Layout<int32_t, int32_t>;
799 EXPECT_EQ(
800 0,
801 Distance(p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
802 EXPECT_EQ(
803 0,
804 Distance(p,
805 Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
806 EXPECT_EQ(
807 12,
808 Distance(p,
809 Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
810 EXPECT_EQ(0,
811 Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data()));
812 EXPECT_EQ(12,
813 Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data()));
814 }
815 {
816 using L = Layout<int8_t, int32_t, Int128>;
817 EXPECT_EQ(
818 0,
819 Distance(p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data()));
820 EXPECT_EQ(
821 0,
822 Distance(p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data()));
823 EXPECT_EQ(
824 0,
825 Distance(p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data()));
826 EXPECT_EQ(
827 0, Distance(
828 p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
829 EXPECT_EQ(
830 0,
831 Distance(p,
832 Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
833 EXPECT_EQ(
834 0, Distance(
835 p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
836 EXPECT_EQ(
837 4,
838 Distance(p,
839 Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
840 EXPECT_EQ(
841 0, Distance(
842 p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
843 EXPECT_EQ(
844 8,
845 Distance(p,
846 Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
847 EXPECT_EQ(
848 0,
849 Distance(
850 p, Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
851 EXPECT_EQ(
852 0,
853 Distance(
854 p,
855 Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
856 EXPECT_EQ(
857 0,
858 Distance(
859 p,
860 Type<Span<const Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
861 EXPECT_EQ(
862 0,
863 Distance(
864 p, Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
865 EXPECT_EQ(
866 4,
867 Distance(
868 p,
869 Type<Span<const int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
870 EXPECT_EQ(
871 8,
872 Distance(
873 p,
874 Type<Span<const Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
875 EXPECT_EQ(
876 0,
877 Distance(
878 p, Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
879 EXPECT_EQ(
880 24,
881 Distance(
882 p,
883 Type<Span<const Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
884 EXPECT_EQ(
885 8,
886 Distance(
887 p,
888 Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
889 EXPECT_EQ(
890 0, Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
891 EXPECT_EQ(
892 24,
893 Distance(p, Type<Span<const Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
894 EXPECT_EQ(
895 8, Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
896 }
897}
898
899TEST(Layout, SliceByTypeData) {
900 alignas(max_align_t) const unsigned char p[100] = {};
901 {
902 using L = Layout<int32_t>;
903 EXPECT_EQ(
904 0,
905 Distance(
906 p, Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
907 EXPECT_EQ(
908 0,
909 Distance(
910 p, Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
911 EXPECT_EQ(
912 0, Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data()));
913 }
914 {
915 using L = Layout<int8_t, int32_t, Int128>;
916 EXPECT_EQ(
917 0, Distance(
918 p, Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
919 EXPECT_EQ(
920 0, Distance(
921 p, Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
922 EXPECT_EQ(
923 0, Distance(
924 p, Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
925 EXPECT_EQ(
926 0,
927 Distance(
928 p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
929 EXPECT_EQ(
930 0,
931 Distance(
932 p,
933 Type<Span<const int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
934 EXPECT_EQ(
935 0,
936 Distance(
937 p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
938 EXPECT_EQ(
939 4,
940 Distance(
941 p,
942 Type<Span<const int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
943 EXPECT_EQ(
944 0,
945 Distance(
946 p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
947 EXPECT_EQ(
948 8,
949 Distance(
950 p,
951 Type<Span<const int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
952 EXPECT_EQ(
953 0,
954 Distance(
955 p,
956 Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
957 EXPECT_EQ(
958 0,
959 Distance(p, Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p))
960 .data()));
961 EXPECT_EQ(0, Distance(p, Type<Span<const Int128>>(
962 L::Partial(0, 0, 0).Slice<Int128>(p))
963 .data()));
964 EXPECT_EQ(
965 0,
966 Distance(
967 p,
968 Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
969 EXPECT_EQ(
970 4,
971 Distance(p, Type<Span<const int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p))
972 .data()));
973 EXPECT_EQ(8, Distance(p, Type<Span<const Int128>>(
974 L::Partial(1, 0, 0).Slice<Int128>(p))
975 .data()));
976 EXPECT_EQ(
977 0,
978 Distance(
979 p,
980 Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
981 EXPECT_EQ(24, Distance(p, Type<Span<const Int128>>(
982 L::Partial(5, 3, 1).Slice<Int128>(p))
983 .data()));
984 EXPECT_EQ(
985 8,
986 Distance(p, Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p))
987 .data()));
988 EXPECT_EQ(
989 0,
990 Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
991 EXPECT_EQ(
992 24,
993 Distance(p,
994 Type<Span<const Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
995 EXPECT_EQ(
996 8, Distance(
997 p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
998 }
999}
1000
1001TEST(Layout, MutableSliceByIndexData) {
1002 alignas(max_align_t) unsigned char p[100];
1003 {
1004 using L = Layout<int32_t>;
1005 EXPECT_EQ(0,
1006 Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data()));
1007 EXPECT_EQ(0,
1008 Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
1009 EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<0>(p)).data()));
1010 }
1011 {
1012 using L = Layout<int32_t, int32_t>;
1013 EXPECT_EQ(0,
1014 Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
1015 EXPECT_EQ(
1016 0, Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
1017 EXPECT_EQ(
1018 12,
1019 Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
1020 EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<0>(p)).data()));
1021 EXPECT_EQ(12, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<1>(p)).data()));
1022 }
1023 {
1024 using L = Layout<int8_t, int32_t, Int128>;
1025 EXPECT_EQ(0,
1026 Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data()));
1027 EXPECT_EQ(0,
1028 Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data()));
1029 EXPECT_EQ(0,
1030 Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data()));
1031 EXPECT_EQ(
1032 0, Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
1033 EXPECT_EQ(
1034 0, Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
1035 EXPECT_EQ(
1036 0, Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
1037 EXPECT_EQ(
1038 4, Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
1039 EXPECT_EQ(
1040 0, Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
1041 EXPECT_EQ(
1042 8, Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
1043 EXPECT_EQ(
1044 0,
1045 Distance(p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
1046 EXPECT_EQ(
1047 0,
1048 Distance(p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
1049 EXPECT_EQ(
1050 0, Distance(
1051 p, Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
1052 EXPECT_EQ(
1053 0,
1054 Distance(p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
1055 EXPECT_EQ(
1056 4,
1057 Distance(p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
1058 EXPECT_EQ(
1059 8, Distance(
1060 p, Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
1061 EXPECT_EQ(
1062 0,
1063 Distance(p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
1064 EXPECT_EQ(
1065 24, Distance(
1066 p, Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
1067 EXPECT_EQ(
1068 8,
1069 Distance(p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
1070 EXPECT_EQ(0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
1071 EXPECT_EQ(24,
1072 Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
1073 EXPECT_EQ(8, Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
1074 }
1075}
1076
1077TEST(Layout, MutableSliceByTypeData) {
1078 alignas(max_align_t) unsigned char p[100];
1079 {
1080 using L = Layout<int32_t>;
1081 EXPECT_EQ(
1082 0,
1083 Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
1084 EXPECT_EQ(
1085 0,
1086 Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
1087 EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data()));
1088 }
1089 {
1090 using L = Layout<int8_t, int32_t, Int128>;
1091 EXPECT_EQ(
1092 0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
1093 EXPECT_EQ(
1094 0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
1095 EXPECT_EQ(
1096 0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
1097 EXPECT_EQ(
1098 0,
1099 Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
1100 EXPECT_EQ(
1101 0, Distance(
1102 p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
1103 EXPECT_EQ(
1104 0,
1105 Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
1106 EXPECT_EQ(
1107 4, Distance(
1108 p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
1109 EXPECT_EQ(
1110 0,
1111 Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
1112 EXPECT_EQ(
1113 8, Distance(
1114 p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
1115 EXPECT_EQ(
1116 0, Distance(
1117 p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
1118 EXPECT_EQ(
1119 0,
1120 Distance(
1121 p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data()));
1122 EXPECT_EQ(
1123 0,
1124 Distance(
1125 p,
1126 Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<Int128>(p)).data()));
1127 EXPECT_EQ(
1128 0, Distance(
1129 p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
1130 EXPECT_EQ(
1131 4,
1132 Distance(
1133 p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data()));
1134 EXPECT_EQ(
1135 8,
1136 Distance(
1137 p,
1138 Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<Int128>(p)).data()));
1139 EXPECT_EQ(
1140 0, Distance(
1141 p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
1142 EXPECT_EQ(
1143 24,
1144 Distance(
1145 p,
1146 Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<Int128>(p)).data()));
1147 EXPECT_EQ(
1148 8,
1149 Distance(
1150 p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data()));
1151 EXPECT_EQ(0,
1152 Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
1153 EXPECT_EQ(
1154 24,
1155 Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
1156 EXPECT_EQ(
1157 8, Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
1158 }
1159}
1160
1161MATCHER_P(IsSameSlice, slice, "") {
1162 return arg.size() == slice.size() && arg.data() == slice.data();
1163}
1164
1165template <typename... M>
1166class TupleMatcher {
1167 public:
1168 explicit TupleMatcher(M... matchers) : matchers_(std::move(matchers)...) {}
1169
1170 template <typename Tuple>
1171 bool MatchAndExplain(const Tuple& p,
1172 testing::MatchResultListener* /* listener */) const {
1173 static_assert(std::tuple_size<Tuple>::value == sizeof...(M), "");
1174 return MatchAndExplainImpl(
1175 p, absl::make_index_sequence<std::tuple_size<Tuple>::value>{});
1176 }
1177
1178 // For the matcher concept. Left empty as we don't really need the diagnostics
1179 // right now.
1180 void DescribeTo(::std::ostream* os) const {}
1181 void DescribeNegationTo(::std::ostream* os) const {}
1182
1183 private:
1184 template <typename Tuple, size_t... Is>
1185 bool MatchAndExplainImpl(const Tuple& p, absl::index_sequence<Is...>) const {
1186 // Using std::min as a simple variadic "and".
1187 return std::min(
1188 {true, testing::SafeMatcherCast<
1189 const typename std::tuple_element<Is, Tuple>::type&>(
1190 std::get<Is>(matchers_))
1191 .Matches(std::get<Is>(p))...});
1192 }
1193
1194 std::tuple<M...> matchers_;
1195};
1196
1197template <typename... M>
1198testing::PolymorphicMatcher<TupleMatcher<M...>> Tuple(M... matchers) {
1199 return testing::MakePolymorphicMatcher(
1200 TupleMatcher<M...>(std::move(matchers)...));
1201}
1202
1203TEST(Layout, Slices) {
1204 alignas(max_align_t) const unsigned char p[100] = {};
1205 using L = Layout<int8_t, int8_t, Int128>;
1206 {
1207 const auto x = L::Partial();
1208 EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple());
1209 }
1210 {
1211 const auto x = L::Partial(1);
1212 EXPECT_THAT(Type<std::tuple<Span<const int8_t>>>(x.Slices(p)),
1213 Tuple(IsSameSlice(x.Slice<0>(p))));
1214 }
1215 {
1216 const auto x = L::Partial(1, 2);
1217 EXPECT_THAT(
1218 (Type<std::tuple<Span<const int8_t>, Span<const int8_t>>>(x.Slices(p))),
1219 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));
1220 }
1221 {
1222 const auto x = L::Partial(1, 2, 3);
1223 EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
1224 Span<const Int128>>>(x.Slices(p))),
1225 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1226 IsSameSlice(x.Slice<2>(p))));
1227 }
1228 {
1229 const L x(1, 2, 3);
1230 EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
1231 Span<const Int128>>>(x.Slices(p))),
1232 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1233 IsSameSlice(x.Slice<2>(p))));
1234 }
1235}
1236
1237TEST(Layout, MutableSlices) {
1238 alignas(max_align_t) unsigned char p[100] = {};
1239 using L = Layout<int8_t, int8_t, Int128>;
1240 {
1241 const auto x = L::Partial();
1242 EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple());
1243 }
1244 {
1245 const auto x = L::Partial(1);
1246 EXPECT_THAT(Type<std::tuple<Span<int8_t>>>(x.Slices(p)),
1247 Tuple(IsSameSlice(x.Slice<0>(p))));
1248 }
1249 {
1250 const auto x = L::Partial(1, 2);
1251 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>>>(x.Slices(p))),
1252 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));
1253 }
1254 {
1255 const auto x = L::Partial(1, 2, 3);
1256 EXPECT_THAT(
1257 (Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(x.Slices(p))),
1258 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1259 IsSameSlice(x.Slice<2>(p))));
1260 }
1261 {
1262 const L x(1, 2, 3);
1263 EXPECT_THAT(
1264 (Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(x.Slices(p))),
1265 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1266 IsSameSlice(x.Slice<2>(p))));
1267 }
1268}
1269
1270TEST(Layout, UnalignedTypes) {
1271 constexpr Layout<unsigned char, unsigned char, unsigned char> x(1, 2, 3);
1272 alignas(max_align_t) unsigned char p[x.AllocSize() + 1];
1273 EXPECT_THAT(x.Pointers(p + 1), Tuple(p + 1, p + 2, p + 4));
1274}
1275
1276TEST(Layout, CustomAlignment) {
1277 constexpr Layout<unsigned char, Aligned<unsigned char, 8>> x(1, 2);
1278 alignas(max_align_t) unsigned char p[x.AllocSize()];
1279 EXPECT_EQ(10, x.AllocSize());
1280 EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 8));
1281}
1282
1283TEST(Layout, OverAligned) {
1284 constexpr size_t M = alignof(max_align_t);
1285 constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3);
1286 alignas(2 * M) unsigned char p[x.AllocSize()];
1287 EXPECT_EQ(2 * M + 3, x.AllocSize());
1288 EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 2 * M));
1289}
1290
1291TEST(Layout, Alignment) {
1292 static_assert(Layout<int8_t>::Alignment() == 1, "");
1293 static_assert(Layout<int32_t>::Alignment() == 4, "");
1294 static_assert(Layout<Int64>::Alignment() == 8, "");
1295 static_assert(Layout<Aligned<int8_t, 64>>::Alignment() == 64, "");
1296 static_assert(Layout<int8_t, int32_t, Int64>::Alignment() == 8, "");
1297 static_assert(Layout<int8_t, Int64, int32_t>::Alignment() == 8, "");
1298 static_assert(Layout<int32_t, int8_t, Int64>::Alignment() == 8, "");
1299 static_assert(Layout<int32_t, Int64, int8_t>::Alignment() == 8, "");
1300 static_assert(Layout<Int64, int8_t, int32_t>::Alignment() == 8, "");
1301 static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, "");
1302}
1303
1304TEST(Layout, ConstexprPartial) {
1305 constexpr size_t M = alignof(max_align_t);
1306 constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3);
1307 static_assert(x.Partial(1).template Offset<1>() == 2 * M, "");
1308}
1309// [from, to)
1310struct Region {
1311 size_t from;
1312 size_t to;
1313};
1314
1315void ExpectRegionPoisoned(const unsigned char* p, size_t n, bool poisoned) {
1316#ifdef ADDRESS_SANITIZER
1317 for (size_t i = 0; i != n; ++i) {
1318 EXPECT_EQ(poisoned, __asan_address_is_poisoned(p + i));
1319 }
1320#endif
1321}
1322
1323template <size_t N>
1324void ExpectPoisoned(const unsigned char (&buf)[N],
1325 std::initializer_list<Region> reg) {
1326 size_t prev = 0;
1327 for (const Region& r : reg) {
1328 ExpectRegionPoisoned(buf + prev, r.from - prev, false);
1329 ExpectRegionPoisoned(buf + r.from, r.to - r.from, true);
1330 prev = r.to;
1331 }
1332 ExpectRegionPoisoned(buf + prev, N - prev, false);
1333}
1334
1335TEST(Layout, PoisonPadding) {
1336 using L = Layout<int8_t, Int64, int32_t, Int128>;
1337
1338 constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize();
1339 {
1340 constexpr auto x = L::Partial();
1341 alignas(max_align_t) const unsigned char c[n] = {};
1342 x.PoisonPadding(c);
1343 EXPECT_EQ(x.Slices(c), x.Slices(c));
1344 ExpectPoisoned(c, {});
1345 }
1346 {
1347 constexpr auto x = L::Partial(1);
1348 alignas(max_align_t) const unsigned char c[n] = {};
1349 x.PoisonPadding(c);
1350 EXPECT_EQ(x.Slices(c), x.Slices(c));
1351 ExpectPoisoned(c, {{1, 8}});
1352 }
1353 {
1354 constexpr auto x = L::Partial(1, 2);
1355 alignas(max_align_t) const unsigned char c[n] = {};
1356 x.PoisonPadding(c);
1357 EXPECT_EQ(x.Slices(c), x.Slices(c));
1358 ExpectPoisoned(c, {{1, 8}});
1359 }
1360 {
1361 constexpr auto x = L::Partial(1, 2, 3);
1362 alignas(max_align_t) const unsigned char c[n] = {};
1363 x.PoisonPadding(c);
1364 EXPECT_EQ(x.Slices(c), x.Slices(c));
1365 ExpectPoisoned(c, {{1, 8}, {36, 40}});
1366 }
1367 {
1368 constexpr auto x = L::Partial(1, 2, 3, 4);
1369 alignas(max_align_t) const unsigned char c[n] = {};
1370 x.PoisonPadding(c);
1371 EXPECT_EQ(x.Slices(c), x.Slices(c));
1372 ExpectPoisoned(c, {{1, 8}, {36, 40}});
1373 }
1374 {
1375 constexpr L x(1, 2, 3, 4);
1376 alignas(max_align_t) const unsigned char c[n] = {};
1377 x.PoisonPadding(c);
1378 EXPECT_EQ(x.Slices(c), x.Slices(c));
1379 ExpectPoisoned(c, {{1, 8}, {36, 40}});
1380 }
1381}
1382
1383TEST(Layout, DebugString) {
1384 {
1385 constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial();
1386 EXPECT_EQ("@0<signed char>(1)", x.DebugString());
1387 }
1388 {
1389 constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1);
1390 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)", x.DebugString());
1391 }
1392 {
1393 constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2);
1394 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)",
1395 x.DebugString());
1396 }
1397 {
1398 constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
1399 EXPECT_EQ(
1400 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1401 "@16" +
1402 Int128::Name() + "(16)",
1403 x.DebugString());
1404 }
1405 {
1406 constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
1407 EXPECT_EQ(
1408 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1409 "@16" +
1410 Int128::Name() + "(16)[4]",
1411 x.DebugString());
1412 }
1413 {
1414 constexpr Layout<int8_t, int32_t, int8_t, Int128> x(1, 2, 3, 4);
1415 EXPECT_EQ(
1416 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1417 "@16" +
1418 Int128::Name() + "(16)[4]",
1419 x.DebugString());
1420 }
1421}
1422
1423TEST(Layout, CharTypes) {
1424 constexpr Layout<int32_t> x(1);
1425 alignas(max_align_t) char c[x.AllocSize()] = {};
1426 alignas(max_align_t) unsigned char uc[x.AllocSize()] = {};
1427 alignas(max_align_t) signed char sc[x.AllocSize()] = {};
1428 alignas(max_align_t) const char cc[x.AllocSize()] = {};
1429 alignas(max_align_t) const unsigned char cuc[x.AllocSize()] = {};
1430 alignas(max_align_t) const signed char csc[x.AllocSize()] = {};
1431
1432 Type<int32_t*>(x.Pointer<0>(c));
1433 Type<int32_t*>(x.Pointer<0>(uc));
1434 Type<int32_t*>(x.Pointer<0>(sc));
1435 Type<const int32_t*>(x.Pointer<0>(cc));
1436 Type<const int32_t*>(x.Pointer<0>(cuc));
1437 Type<const int32_t*>(x.Pointer<0>(csc));
1438
1439 Type<int32_t*>(x.Pointer<int32_t>(c));
1440 Type<int32_t*>(x.Pointer<int32_t>(uc));
1441 Type<int32_t*>(x.Pointer<int32_t>(sc));
1442 Type<const int32_t*>(x.Pointer<int32_t>(cc));
1443 Type<const int32_t*>(x.Pointer<int32_t>(cuc));
1444 Type<const int32_t*>(x.Pointer<int32_t>(csc));
1445
1446 Type<std::tuple<int32_t*>>(x.Pointers(c));
1447 Type<std::tuple<int32_t*>>(x.Pointers(uc));
1448 Type<std::tuple<int32_t*>>(x.Pointers(sc));
1449 Type<std::tuple<const int32_t*>>(x.Pointers(cc));
1450 Type<std::tuple<const int32_t*>>(x.Pointers(cuc));
1451 Type<std::tuple<const int32_t*>>(x.Pointers(csc));
1452
1453 Type<Span<int32_t>>(x.Slice<0>(c));
1454 Type<Span<int32_t>>(x.Slice<0>(uc));
1455 Type<Span<int32_t>>(x.Slice<0>(sc));
1456 Type<Span<const int32_t>>(x.Slice<0>(cc));
1457 Type<Span<const int32_t>>(x.Slice<0>(cuc));
1458 Type<Span<const int32_t>>(x.Slice<0>(csc));
1459
1460 Type<std::tuple<Span<int32_t>>>(x.Slices(c));
1461 Type<std::tuple<Span<int32_t>>>(x.Slices(uc));
1462 Type<std::tuple<Span<int32_t>>>(x.Slices(sc));
1463 Type<std::tuple<Span<const int32_t>>>(x.Slices(cc));
1464 Type<std::tuple<Span<const int32_t>>>(x.Slices(cuc));
1465 Type<std::tuple<Span<const int32_t>>>(x.Slices(csc));
1466}
1467
1468TEST(Layout, ConstElementType) {
1469 constexpr Layout<const int32_t> x(1);
1470 alignas(int32_t) char c[x.AllocSize()] = {};
1471 const char* cc = c;
1472 const int32_t* p = reinterpret_cast<const int32_t*>(cc);
1473
1474 EXPECT_EQ(alignof(int32_t), x.Alignment());
1475
1476 EXPECT_EQ(0, x.Offset<0>());
1477 EXPECT_EQ(0, x.Offset<const int32_t>());
1478
1479 EXPECT_THAT(x.Offsets(), ElementsAre(0));
1480
1481 EXPECT_EQ(1, x.Size<0>());
1482 EXPECT_EQ(1, x.Size<const int32_t>());
1483
1484 EXPECT_THAT(x.Sizes(), ElementsAre(1));
1485
1486 EXPECT_EQ(sizeof(int32_t), x.AllocSize());
1487
1488 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(c)));
1489 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(cc)));
1490
1491 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(c)));
1492 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(cc)));
1493
1494 EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(c)), Tuple(p));
1495 EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(cc)), Tuple(p));
1496
1497 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(c)),
1498 IsSameSlice(Span<const int32_t>(p, 1)));
1499 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(cc)),
1500 IsSameSlice(Span<const int32_t>(p, 1)));
1501
1502 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(c)),
1503 IsSameSlice(Span<const int32_t>(p, 1)));
1504 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(cc)),
1505 IsSameSlice(Span<const int32_t>(p, 1)));
1506
1507 EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(c)),
1508 Tuple(IsSameSlice(Span<const int32_t>(p, 1))));
1509 EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(cc)),
1510 Tuple(IsSameSlice(Span<const int32_t>(p, 1))));
1511}
1512
1513namespace example {
1514
1515// Immutable move-only string with sizeof equal to sizeof(void*). The string
1516// size and the characters are kept in the same heap allocation.
1517class CompactString {
1518 public:
1519 CompactString(const char* s = "") { // NOLINT
1520 const size_t size = strlen(s);
1521 // size_t[1], followed by char[size + 1].
1522 // This statement doesn't allocate memory.
1523 const L layout(1, size + 1);
1524 // AllocSize() tells us how much memory we need to allocate for all our
1525 // data.
1526 p_.reset(new unsigned char[layout.AllocSize()]);
1527 // If running under ASAN, mark the padding bytes, if any, to catch memory
1528 // errors.
1529 layout.PoisonPadding(p_.get());
1530 // Store the size in the allocation.
1531 // Pointer<size_t>() is a synonym for Pointer<0>().
1532 *layout.Pointer<size_t>(p_.get()) = size;
1533 // Store the characters in the allocation.
1534 memcpy(layout.Pointer<char>(p_.get()), s, size + 1);
1535 }
1536
1537 size_t size() const {
1538 // Equivalent to reinterpret_cast<size_t&>(*p).
1539 return *L::Partial().Pointer<size_t>(p_.get());
1540 }
1541
1542 const char* c_str() const {
1543 // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)).
1544 // The argument in Partial(1) specifies that we have size_t[1] in front of
1545 // the characters.
1546 return L::Partial(1).Pointer<char>(p_.get());
1547 }
1548
1549 private:
1550 // Our heap allocation contains a size_t followed by an array of chars.
1551 using L = Layout<size_t, char>;
1552 std::unique_ptr<unsigned char[]> p_;
1553};
1554
1555TEST(CompactString, Works) {
1556 CompactString s = "hello";
1557 EXPECT_EQ(5, s.size());
1558 EXPECT_STREQ("hello", s.c_str());
1559}
1560
1561} // namespace example
1562
1563} // namespace
1564} // namespace container_internal
1565} // namespace absl