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


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:14