xref: /aosp_15_r20/external/abseil-cpp/absl/container/internal/layout_test.cc (revision 9356374a3709195abf420251b3e825997ff56c0f)
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 <cstring>
23 #include <initializer_list>
24 #include <memory>
25 #include <ostream>
26 #include <string>
27 #include <tuple>
28 #include <type_traits>
29 
30 #include "gmock/gmock.h"
31 #include "gtest/gtest.h"
32 #include "absl/base/config.h"
33 #include "absl/log/check.h"
34 #include "absl/types/span.h"
35 #include "absl/utility/utility.h"
36 
37 namespace absl {
38 ABSL_NAMESPACE_BEGIN
39 namespace container_internal {
40 namespace {
41 
42 using ::absl::Span;
43 using ::testing::ElementsAre;
44 
Distance(const void * from,const void * to)45 size_t Distance(const void* from, const void* to) {
46   CHECK_LE(from, to) << "Distance must be non-negative";
47   return static_cast<const char*>(to) - static_cast<const char*>(from);
48 }
49 
50 template <class Expected, class Actual>
Type(Actual val)51 Expected Type(Actual val) {
52   static_assert(std::is_same<Expected, Actual>(), "");
53   return val;
54 }
55 
56 // Helper classes to test different size and alignments.
57 struct alignas(8) Int128 {
58   uint64_t a, b;
operator ==(Int128 lhs,Int128 rhs)59   friend bool operator==(Int128 lhs, Int128 rhs) {
60     return std::tie(lhs.a, lhs.b) == std::tie(rhs.a, rhs.b);
61   }
62 
Nameabsl::container_internal::__anonbf23a5d60111::Int12863   static std::string Name() {
64     return internal_layout::adl_barrier::TypeName<Int128>();
65   }
66 };
67 
68 // int64_t is *not* 8-byte aligned on all platforms!
69 struct alignas(8) Int64 {
70   int64_t a;
operator ==(Int64 lhs,Int64 rhs)71   friend bool operator==(Int64 lhs, Int64 rhs) { return lhs.a == rhs.a; }
72 };
73 
74 // Properties of types that this test relies on.
75 static_assert(sizeof(int8_t) == 1, "");
76 static_assert(alignof(int8_t) == 1, "");
77 static_assert(sizeof(int16_t) == 2, "");
78 static_assert(alignof(int16_t) == 2, "");
79 static_assert(sizeof(int32_t) == 4, "");
80 static_assert(alignof(int32_t) == 4, "");
81 static_assert(sizeof(Int64) == 8, "");
82 static_assert(alignof(Int64) == 8, "");
83 static_assert(sizeof(Int128) == 16, "");
84 static_assert(alignof(Int128) == 8, "");
85 
86 template <class Expected, class Actual>
SameType()87 void SameType() {
88   static_assert(std::is_same<Expected, Actual>(), "");
89 }
90 
TEST(Layout,ElementType)91 TEST(Layout, ElementType) {
92   {
93     using L = Layout<int32_t>;
94     SameType<int32_t, L::ElementType<0>>();
95     SameType<int32_t, decltype(L::Partial())::ElementType<0>>();
96     SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>();
97   }
98   {
99     using L = Layout<int32_t, int32_t>;
100     SameType<int32_t, L::ElementType<0>>();
101     SameType<int32_t, L::ElementType<1>>();
102     SameType<int32_t, decltype(L::Partial())::ElementType<0>>();
103     SameType<int32_t, decltype(L::Partial())::ElementType<1>>();
104     SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>();
105     SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>();
106   }
107   {
108     using L = Layout<int8_t, int32_t, Int128>;
109     SameType<int8_t, L::ElementType<0>>();
110     SameType<int32_t, L::ElementType<1>>();
111     SameType<Int128, L::ElementType<2>>();
112     SameType<int8_t, decltype(L::Partial())::ElementType<0>>();
113     SameType<int8_t, decltype(L::Partial(0))::ElementType<0>>();
114     SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>();
115     SameType<int8_t, decltype(L::Partial(0, 0))::ElementType<0>>();
116     SameType<int32_t, decltype(L::Partial(0, 0))::ElementType<1>>();
117     SameType<Int128, decltype(L::Partial(0, 0))::ElementType<2>>();
118     SameType<int8_t, decltype(L::Partial(0, 0, 0))::ElementType<0>>();
119     SameType<int32_t, decltype(L::Partial(0, 0, 0))::ElementType<1>>();
120     SameType<Int128, decltype(L::Partial(0, 0, 0))::ElementType<2>>();
121   }
122 }
123 
TEST(Layout,ElementTypes)124 TEST(Layout, ElementTypes) {
125   {
126     using L = Layout<int32_t>;
127     SameType<std::tuple<int32_t>, L::ElementTypes>();
128     SameType<std::tuple<int32_t>, decltype(L::Partial())::ElementTypes>();
129     SameType<std::tuple<int32_t>, decltype(L::Partial(0))::ElementTypes>();
130   }
131   {
132     using L = Layout<int32_t, int32_t>;
133     SameType<std::tuple<int32_t, int32_t>, L::ElementTypes>();
134     SameType<std::tuple<int32_t, int32_t>,
135              decltype(L::Partial())::ElementTypes>();
136     SameType<std::tuple<int32_t, int32_t>,
137              decltype(L::Partial(0))::ElementTypes>();
138   }
139   {
140     using L = Layout<int8_t, int32_t, Int128>;
141     SameType<std::tuple<int8_t, int32_t, Int128>, L::ElementTypes>();
142     SameType<std::tuple<int8_t, int32_t, Int128>,
143              decltype(L::Partial())::ElementTypes>();
144     SameType<std::tuple<int8_t, int32_t, Int128>,
145              decltype(L::Partial(0))::ElementTypes>();
146     SameType<std::tuple<int8_t, int32_t, Int128>,
147              decltype(L::Partial(0, 0))::ElementTypes>();
148     SameType<std::tuple<int8_t, int32_t, Int128>,
149              decltype(L::Partial(0, 0, 0))::ElementTypes>();
150   }
151 }
152 
TEST(Layout,OffsetByIndex)153 TEST(Layout, OffsetByIndex) {
154   {
155     using L = Layout<int32_t>;
156     EXPECT_EQ(0, L::Partial().Offset<0>());
157     EXPECT_EQ(0, L::Partial(3).Offset<0>());
158     EXPECT_EQ(0, L(3).Offset<0>());
159   }
160   {
161     using L = Layout<int32_t, int32_t>;
162     EXPECT_EQ(0, L::Partial().Offset<0>());
163     EXPECT_EQ(0, L::Partial(3).Offset<0>());
164     EXPECT_EQ(12, L::Partial(3).Offset<1>());
165     EXPECT_EQ(0, L::Partial(3, 5).Offset<0>());
166     EXPECT_EQ(12, L::Partial(3, 5).Offset<1>());
167     EXPECT_EQ(0, L(3, 5).Offset<0>());
168     EXPECT_EQ(12, L(3, 5).Offset<1>());
169   }
170   {
171     using L = Layout<int8_t, int32_t, Int128>;
172     EXPECT_EQ(0, L::Partial().Offset<0>());
173     EXPECT_EQ(0, L::Partial(0).Offset<0>());
174     EXPECT_EQ(0, L::Partial(0).Offset<1>());
175     EXPECT_EQ(0, L::Partial(1).Offset<0>());
176     EXPECT_EQ(4, L::Partial(1).Offset<1>());
177     EXPECT_EQ(0, L::Partial(5).Offset<0>());
178     EXPECT_EQ(8, L::Partial(5).Offset<1>());
179     EXPECT_EQ(0, L::Partial(0, 0).Offset<0>());
180     EXPECT_EQ(0, L::Partial(0, 0).Offset<1>());
181     EXPECT_EQ(0, L::Partial(0, 0).Offset<2>());
182     EXPECT_EQ(0, L::Partial(1, 0).Offset<0>());
183     EXPECT_EQ(4, L::Partial(1, 0).Offset<1>());
184     EXPECT_EQ(8, L::Partial(1, 0).Offset<2>());
185     EXPECT_EQ(0, L::Partial(5, 3).Offset<0>());
186     EXPECT_EQ(8, L::Partial(5, 3).Offset<1>());
187     EXPECT_EQ(24, L::Partial(5, 3).Offset<2>());
188     EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<0>());
189     EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<1>());
190     EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<2>());
191     EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<0>());
192     EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<1>());
193     EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<2>());
194     EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<0>());
195     EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<2>());
196     EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<1>());
197     EXPECT_EQ(0, L(5, 3, 1).Offset<0>());
198     EXPECT_EQ(24, L(5, 3, 1).Offset<2>());
199     EXPECT_EQ(8, L(5, 3, 1).Offset<1>());
200   }
201 }
202 
TEST(Layout,OffsetByType)203 TEST(Layout, OffsetByType) {
204   {
205     using L = Layout<int32_t>;
206     EXPECT_EQ(0, L::Partial().Offset<int32_t>());
207     EXPECT_EQ(0, L::Partial(3).Offset<int32_t>());
208     EXPECT_EQ(0, L(3).Offset<int32_t>());
209   }
210   {
211     using L = Layout<int8_t, int32_t, Int128>;
212     EXPECT_EQ(0, L::Partial().Offset<int8_t>());
213     EXPECT_EQ(0, L::Partial(0).Offset<int8_t>());
214     EXPECT_EQ(0, L::Partial(0).Offset<int32_t>());
215     EXPECT_EQ(0, L::Partial(1).Offset<int8_t>());
216     EXPECT_EQ(4, L::Partial(1).Offset<int32_t>());
217     EXPECT_EQ(0, L::Partial(5).Offset<int8_t>());
218     EXPECT_EQ(8, L::Partial(5).Offset<int32_t>());
219     EXPECT_EQ(0, L::Partial(0, 0).Offset<int8_t>());
220     EXPECT_EQ(0, L::Partial(0, 0).Offset<int32_t>());
221     EXPECT_EQ(0, L::Partial(0, 0).Offset<Int128>());
222     EXPECT_EQ(0, L::Partial(1, 0).Offset<int8_t>());
223     EXPECT_EQ(4, L::Partial(1, 0).Offset<int32_t>());
224     EXPECT_EQ(8, L::Partial(1, 0).Offset<Int128>());
225     EXPECT_EQ(0, L::Partial(5, 3).Offset<int8_t>());
226     EXPECT_EQ(8, L::Partial(5, 3).Offset<int32_t>());
227     EXPECT_EQ(24, L::Partial(5, 3).Offset<Int128>());
228     EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int8_t>());
229     EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int32_t>());
230     EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<Int128>());
231     EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<int8_t>());
232     EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<int32_t>());
233     EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<Int128>());
234     EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<int8_t>());
235     EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<Int128>());
236     EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<int32_t>());
237     EXPECT_EQ(0, L(5, 3, 1).Offset<int8_t>());
238     EXPECT_EQ(24, L(5, 3, 1).Offset<Int128>());
239     EXPECT_EQ(8, L(5, 3, 1).Offset<int32_t>());
240   }
241 }
242 
TEST(Layout,Offsets)243 TEST(Layout, Offsets) {
244   {
245     using L = Layout<int32_t>;
246     EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
247     EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0));
248     EXPECT_THAT(L(3).Offsets(), ElementsAre(0));
249   }
250   {
251     using L = Layout<int32_t, int32_t>;
252     EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
253     EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0, 12));
254     EXPECT_THAT(L::Partial(3, 5).Offsets(), ElementsAre(0, 12));
255     EXPECT_THAT(L(3, 5).Offsets(), ElementsAre(0, 12));
256   }
257   {
258     using L = Layout<int8_t, int32_t, Int128>;
259     EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
260     EXPECT_THAT(L::Partial(1).Offsets(), ElementsAre(0, 4));
261     EXPECT_THAT(L::Partial(5).Offsets(), ElementsAre(0, 8));
262     EXPECT_THAT(L::Partial(0, 0).Offsets(), ElementsAre(0, 0, 0));
263     EXPECT_THAT(L::Partial(1, 0).Offsets(), ElementsAre(0, 4, 8));
264     EXPECT_THAT(L::Partial(5, 3).Offsets(), ElementsAre(0, 8, 24));
265     EXPECT_THAT(L::Partial(0, 0, 0).Offsets(), ElementsAre(0, 0, 0));
266     EXPECT_THAT(L::Partial(1, 0, 0).Offsets(), ElementsAre(0, 4, 8));
267     EXPECT_THAT(L::Partial(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
268     EXPECT_THAT(L(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
269   }
270 }
271 
TEST(Layout,StaticOffsets)272 TEST(Layout, StaticOffsets) {
273   using L = Layout<int8_t, int32_t, Int128>;
274   {
275     using SL = L::WithStaticSizes<>;
276     EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0));
277     EXPECT_THAT(SL::Partial(5).Offsets(), ElementsAre(0, 8));
278     EXPECT_THAT(SL::Partial(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
279     EXPECT_THAT(SL(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
280   }
281   {
282     using SL = L::WithStaticSizes<5>;
283     EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0, 8));
284     EXPECT_THAT(SL::Partial(3).Offsets(), ElementsAre(0, 8, 24));
285     EXPECT_THAT(SL::Partial(3, 1).Offsets(), ElementsAre(0, 8, 24));
286     EXPECT_THAT(SL(3, 1).Offsets(), ElementsAre(0, 8, 24));
287   }
288   {
289     using SL = L::WithStaticSizes<5, 3>;
290     EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0, 8, 24));
291     EXPECT_THAT(SL::Partial(1).Offsets(), ElementsAre(0, 8, 24));
292     EXPECT_THAT(SL(1).Offsets(), ElementsAre(0, 8, 24));
293   }
294   {
295     using SL = L::WithStaticSizes<5, 3, 1>;
296     EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0, 8, 24));
297     EXPECT_THAT(SL().Offsets(), ElementsAre(0, 8, 24));
298   }
299 }
300 
TEST(Layout,AllocSize)301 TEST(Layout, AllocSize) {
302   {
303     using L = Layout<int32_t>;
304     EXPECT_EQ(0, L::Partial(0).AllocSize());
305     EXPECT_EQ(12, L::Partial(3).AllocSize());
306     EXPECT_EQ(12, L(3).AllocSize());
307   }
308   {
309     using L = Layout<int32_t, int32_t>;
310     EXPECT_EQ(32, L::Partial(3, 5).AllocSize());
311     EXPECT_EQ(32, L(3, 5).AllocSize());
312   }
313   {
314     using L = Layout<int8_t, int32_t, Int128>;
315     EXPECT_EQ(0, L::Partial(0, 0, 0).AllocSize());
316     EXPECT_EQ(8, L::Partial(1, 0, 0).AllocSize());
317     EXPECT_EQ(8, L::Partial(0, 1, 0).AllocSize());
318     EXPECT_EQ(16, L::Partial(0, 0, 1).AllocSize());
319     EXPECT_EQ(24, L::Partial(1, 1, 1).AllocSize());
320     EXPECT_EQ(136, L::Partial(3, 5, 7).AllocSize());
321     EXPECT_EQ(136, L(3, 5, 7).AllocSize());
322   }
323 }
324 
TEST(Layout,StaticAllocSize)325 TEST(Layout, StaticAllocSize) {
326   using L = Layout<int8_t, int32_t, Int128>;
327   {
328     using SL = L::WithStaticSizes<>;
329     EXPECT_EQ(136, SL::Partial(3, 5, 7).AllocSize());
330     EXPECT_EQ(136, SL(3, 5, 7).AllocSize());
331   }
332   {
333     using SL = L::WithStaticSizes<3>;
334     EXPECT_EQ(136, SL::Partial(5, 7).AllocSize());
335     EXPECT_EQ(136, SL(5, 7).AllocSize());
336   }
337   {
338     using SL = L::WithStaticSizes<3, 5>;
339     EXPECT_EQ(136, SL::Partial(7).AllocSize());
340     EXPECT_EQ(136, SL(7).AllocSize());
341   }
342   {
343     using SL = L::WithStaticSizes<3, 5, 7>;
344     EXPECT_EQ(136, SL::Partial().AllocSize());
345     EXPECT_EQ(136, SL().AllocSize());
346   }
347 }
348 
TEST(Layout,SizeByIndex)349 TEST(Layout, SizeByIndex) {
350   {
351     using L = Layout<int32_t>;
352     EXPECT_EQ(0, L::Partial(0).Size<0>());
353     EXPECT_EQ(3, L::Partial(3).Size<0>());
354     EXPECT_EQ(3, L(3).Size<0>());
355   }
356   {
357     using L = Layout<int32_t, int32_t>;
358     EXPECT_EQ(0, L::Partial(0).Size<0>());
359     EXPECT_EQ(3, L::Partial(3).Size<0>());
360     EXPECT_EQ(3, L::Partial(3, 5).Size<0>());
361     EXPECT_EQ(5, L::Partial(3, 5).Size<1>());
362     EXPECT_EQ(3, L(3, 5).Size<0>());
363     EXPECT_EQ(5, L(3, 5).Size<1>());
364   }
365   {
366     using L = Layout<int8_t, int32_t, Int128>;
367     EXPECT_EQ(3, L::Partial(3).Size<0>());
368     EXPECT_EQ(3, L::Partial(3, 5).Size<0>());
369     EXPECT_EQ(5, L::Partial(3, 5).Size<1>());
370     EXPECT_EQ(3, L::Partial(3, 5, 7).Size<0>());
371     EXPECT_EQ(5, L::Partial(3, 5, 7).Size<1>());
372     EXPECT_EQ(7, L::Partial(3, 5, 7).Size<2>());
373     EXPECT_EQ(3, L(3, 5, 7).Size<0>());
374     EXPECT_EQ(5, L(3, 5, 7).Size<1>());
375     EXPECT_EQ(7, L(3, 5, 7).Size<2>());
376   }
377 }
378 
TEST(Layout,SizeByType)379 TEST(Layout, SizeByType) {
380   {
381     using L = Layout<int32_t>;
382     EXPECT_EQ(0, L::Partial(0).Size<int32_t>());
383     EXPECT_EQ(3, L::Partial(3).Size<int32_t>());
384     EXPECT_EQ(3, L(3).Size<int32_t>());
385   }
386   {
387     using L = Layout<int8_t, int32_t, Int128>;
388     EXPECT_EQ(3, L::Partial(3).Size<int8_t>());
389     EXPECT_EQ(3, L::Partial(3, 5).Size<int8_t>());
390     EXPECT_EQ(5, L::Partial(3, 5).Size<int32_t>());
391     EXPECT_EQ(3, L::Partial(3, 5, 7).Size<int8_t>());
392     EXPECT_EQ(5, L::Partial(3, 5, 7).Size<int32_t>());
393     EXPECT_EQ(7, L::Partial(3, 5, 7).Size<Int128>());
394     EXPECT_EQ(3, L(3, 5, 7).Size<int8_t>());
395     EXPECT_EQ(5, L(3, 5, 7).Size<int32_t>());
396     EXPECT_EQ(7, L(3, 5, 7).Size<Int128>());
397   }
398 }
399 
TEST(Layout,Sizes)400 TEST(Layout, Sizes) {
401   {
402     using L = Layout<int32_t>;
403     EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
404     EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
405     EXPECT_THAT(L(3).Sizes(), ElementsAre(3));
406   }
407   {
408     using L = Layout<int32_t, int32_t>;
409     EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
410     EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
411     EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5));
412     EXPECT_THAT(L(3, 5).Sizes(), ElementsAre(3, 5));
413   }
414   {
415     using L = Layout<int8_t, int32_t, Int128>;
416     EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
417     EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
418     EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5));
419     EXPECT_THAT(L::Partial(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
420     EXPECT_THAT(L(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
421   }
422 }
423 
TEST(Layout,StaticSize)424 TEST(Layout, StaticSize) {
425   using L = Layout<int8_t, int32_t, Int128>;
426   {
427     using SL = L::WithStaticSizes<>;
428     EXPECT_THAT(SL::Partial().Sizes(), ElementsAre());
429     EXPECT_THAT(SL::Partial(3).Size<0>(), 3);
430     EXPECT_THAT(SL::Partial(3).Size<int8_t>(), 3);
431     EXPECT_THAT(SL::Partial(3).Sizes(), ElementsAre(3));
432     EXPECT_THAT(SL::Partial(3, 5, 7).Size<0>(), 3);
433     EXPECT_THAT(SL::Partial(3, 5, 7).Size<int8_t>(), 3);
434     EXPECT_THAT(SL::Partial(3, 5, 7).Size<2>(), 7);
435     EXPECT_THAT(SL::Partial(3, 5, 7).Size<Int128>(), 7);
436     EXPECT_THAT(SL::Partial(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
437     EXPECT_THAT(SL(3, 5, 7).Size<0>(), 3);
438     EXPECT_THAT(SL(3, 5, 7).Size<int8_t>(), 3);
439     EXPECT_THAT(SL(3, 5, 7).Size<2>(), 7);
440     EXPECT_THAT(SL(3, 5, 7).Size<Int128>(), 7);
441     EXPECT_THAT(SL(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
442   }
443 }
444 
TEST(Layout,PointerByIndex)445 TEST(Layout, PointerByIndex) {
446   alignas(max_align_t) const unsigned char p[100] = {0};
447   {
448     using L = Layout<int32_t>;
449     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
450     EXPECT_EQ(0,
451               Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
452     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<0>(p))));
453   }
454   {
455     using L = Layout<int32_t, int32_t>;
456     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
457     EXPECT_EQ(0,
458               Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
459     EXPECT_EQ(12,
460               Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p))));
461     EXPECT_EQ(
462         0, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
463     EXPECT_EQ(
464         12, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
465     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<0>(p))));
466     EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<1>(p))));
467   }
468   {
469     using L = Layout<int8_t, int32_t, Int128>;
470     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<0>(p))));
471     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<0>(p))));
472     EXPECT_EQ(0,
473               Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p))));
474     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<0>(p))));
475     EXPECT_EQ(4,
476               Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p))));
477     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<0>(p))));
478     EXPECT_EQ(8,
479               Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p))));
480     EXPECT_EQ(0,
481               Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
482     EXPECT_EQ(
483         0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
484     EXPECT_EQ(0,
485               Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<2>(p))));
486     EXPECT_EQ(0,
487               Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
488     EXPECT_EQ(
489         4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
490     EXPECT_EQ(8,
491               Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<2>(p))));
492     EXPECT_EQ(0,
493               Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
494     EXPECT_EQ(
495         8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
496     EXPECT_EQ(24,
497               Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<2>(p))));
498     EXPECT_EQ(
499         0, Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
500     EXPECT_EQ(
501         0,
502         Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
503     EXPECT_EQ(
504         0, Distance(p, Type<const Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
505     EXPECT_EQ(
506         0, Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
507     EXPECT_EQ(
508         4,
509         Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
510     EXPECT_EQ(
511         8, Distance(p, Type<const Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
512     EXPECT_EQ(
513         0, Distance(p, Type<const int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
514     EXPECT_EQ(
515         24,
516         Distance(p, Type<const Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
517     EXPECT_EQ(
518         8,
519         Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
520     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L(5, 3, 1).Pointer<0>(p))));
521     EXPECT_EQ(24, Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<2>(p))));
522     EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<1>(p))));
523   }
524 }
525 
TEST(Layout,PointerByType)526 TEST(Layout, PointerByType) {
527   alignas(max_align_t) const unsigned char p[100] = {0};
528   {
529     using L = Layout<int32_t>;
530     EXPECT_EQ(
531         0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p))));
532     EXPECT_EQ(
533         0,
534         Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
535     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<int32_t>(p))));
536   }
537   {
538     using L = Layout<int8_t, int32_t, Int128>;
539     EXPECT_EQ(
540         0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p))));
541     EXPECT_EQ(
542         0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
543     EXPECT_EQ(
544         0,
545         Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
546     EXPECT_EQ(
547         0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
548     EXPECT_EQ(
549         4,
550         Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
551     EXPECT_EQ(
552         0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
553     EXPECT_EQ(
554         8,
555         Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
556     EXPECT_EQ(
557         0,
558         Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
559     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
560                                  L::Partial(0, 0).Pointer<int32_t>(p))));
561     EXPECT_EQ(
562         0,
563         Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
564     EXPECT_EQ(
565         0,
566         Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
567     EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
568                                  L::Partial(1, 0).Pointer<int32_t>(p))));
569     EXPECT_EQ(
570         8,
571         Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
572     EXPECT_EQ(
573         0,
574         Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
575     EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
576                                  L::Partial(5, 3).Pointer<int32_t>(p))));
577     EXPECT_EQ(
578         24,
579         Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
580     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
581                                  L::Partial(0, 0, 0).Pointer<int8_t>(p))));
582     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
583                                  L::Partial(0, 0, 0).Pointer<int32_t>(p))));
584     EXPECT_EQ(0, Distance(p, Type<const Int128*>(
585                                  L::Partial(0, 0, 0).Pointer<Int128>(p))));
586     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
587                                  L::Partial(1, 0, 0).Pointer<int8_t>(p))));
588     EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
589                                  L::Partial(1, 0, 0).Pointer<int32_t>(p))));
590     EXPECT_EQ(8, Distance(p, Type<const Int128*>(
591                                  L::Partial(1, 0, 0).Pointer<Int128>(p))));
592     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
593                                  L::Partial(5, 3, 1).Pointer<int8_t>(p))));
594     EXPECT_EQ(24, Distance(p, Type<const Int128*>(
595                                   L::Partial(5, 3, 1).Pointer<Int128>(p))));
596     EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
597                                  L::Partial(5, 3, 1).Pointer<int32_t>(p))));
598     EXPECT_EQ(24,
599               Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
600     EXPECT_EQ(
601         8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
602   }
603 }
604 
TEST(Layout,MutablePointerByIndex)605 TEST(Layout, MutablePointerByIndex) {
606   alignas(max_align_t) unsigned char p[100] = {0};
607   {
608     using L = Layout<int32_t>;
609     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p))));
610     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p))));
611     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<0>(p))));
612   }
613   {
614     using L = Layout<int32_t, int32_t>;
615     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p))));
616     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p))));
617     EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<1>(p))));
618     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
619     EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
620     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3, 5).Pointer<0>(p))));
621     EXPECT_EQ(12, Distance(p, Type<int32_t*>(L(3, 5).Pointer<1>(p))));
622   }
623   {
624     using L = Layout<int8_t, int32_t, Int128>;
625     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<0>(p))));
626     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<0>(p))));
627     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0).Pointer<1>(p))));
628     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<0>(p))));
629     EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1).Pointer<1>(p))));
630     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<0>(p))));
631     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5).Pointer<1>(p))));
632     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
633     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
634     EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<2>(p))));
635     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
636     EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
637     EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<2>(p))));
638     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
639     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
640     EXPECT_EQ(24, Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<2>(p))));
641     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
642     EXPECT_EQ(0,
643               Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
644     EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
645     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
646     EXPECT_EQ(4,
647               Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
648     EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
649     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
650     EXPECT_EQ(24,
651               Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
652     EXPECT_EQ(8,
653               Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
654     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<0>(p))));
655     EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<2>(p))));
656     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<1>(p))));
657   }
658 }
659 
TEST(Layout,MutablePointerByType)660 TEST(Layout, MutablePointerByType) {
661   alignas(max_align_t) unsigned char p[100] = {0};
662   {
663     using L = Layout<int32_t>;
664     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<int32_t>(p))));
665     EXPECT_EQ(0,
666               Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
667     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<int32_t>(p))));
668   }
669   {
670     using L = Layout<int8_t, int32_t, Int128>;
671     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<int8_t>(p))));
672     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
673     EXPECT_EQ(0,
674               Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
675     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
676     EXPECT_EQ(4,
677               Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
678     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
679     EXPECT_EQ(8,
680               Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
681     EXPECT_EQ(0,
682               Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
683     EXPECT_EQ(
684         0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
685     EXPECT_EQ(0,
686               Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
687     EXPECT_EQ(0,
688               Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
689     EXPECT_EQ(
690         4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
691     EXPECT_EQ(8,
692               Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
693     EXPECT_EQ(0,
694               Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
695     EXPECT_EQ(
696         8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
697     EXPECT_EQ(24,
698               Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
699     EXPECT_EQ(
700         0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
701     EXPECT_EQ(
702         0,
703         Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
704     EXPECT_EQ(
705         0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<Int128>(p))));
706     EXPECT_EQ(
707         0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
708     EXPECT_EQ(
709         4,
710         Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
711     EXPECT_EQ(
712         8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<Int128>(p))));
713     EXPECT_EQ(
714         0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
715     EXPECT_EQ(
716         24, Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<Int128>(p))));
717     EXPECT_EQ(
718         8,
719         Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
720     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<int8_t>(p))));
721     EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
722     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
723   }
724 }
725 
TEST(Layout,Pointers)726 TEST(Layout, Pointers) {
727   alignas(max_align_t) const unsigned char p[100] = {0};
728   using L = Layout<int8_t, int8_t, Int128>;
729   {
730     const auto x = L::Partial();
731     EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),
732               Type<std::tuple<const int8_t*>>(x.Pointers(p)));
733   }
734   {
735     const auto x = L::Partial(1);
736     EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
737               (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p))));
738   }
739   {
740     const auto x = L::Partial(1, 2);
741     EXPECT_EQ(
742         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
743         (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
744             x.Pointers(p))));
745   }
746   {
747     const auto x = L::Partial(1, 2, 3);
748     EXPECT_EQ(
749         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
750         (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
751             x.Pointers(p))));
752   }
753   {
754     const L x(1, 2, 3);
755     EXPECT_EQ(
756         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
757         (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
758             x.Pointers(p))));
759   }
760 }
761 
TEST(Layout,MutablePointers)762 TEST(Layout, MutablePointers) {
763   alignas(max_align_t) unsigned char p[100] = {0};
764   using L = Layout<int8_t, int8_t, Int128>;
765   {
766     const auto x = L::Partial();
767     EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),
768               Type<std::tuple<int8_t*>>(x.Pointers(p)));
769   }
770   {
771     const auto x = L::Partial(1);
772     EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
773               (Type<std::tuple<int8_t*, int8_t*>>(x.Pointers(p))));
774   }
775   {
776     const auto x = L::Partial(1, 2);
777     EXPECT_EQ(
778         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
779         (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
780   }
781   {
782     const auto x = L::Partial(1, 2, 3);
783     EXPECT_EQ(
784         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
785         (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
786   }
787   {
788     const L x(1, 2, 3);
789     EXPECT_EQ(
790         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
791         (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
792   }
793 }
794 
TEST(Layout,StaticPointers)795 TEST(Layout, StaticPointers) {
796   alignas(max_align_t) const unsigned char p[100] = {0};
797   using L = Layout<int8_t, int8_t, Int128>;
798   {
799     const auto x = L::WithStaticSizes<>::Partial();
800     EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),
801               Type<std::tuple<const int8_t*>>(x.Pointers(p)));
802   }
803   {
804     const auto x = L::WithStaticSizes<>::Partial(1);
805     EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
806               (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p))));
807   }
808   {
809     const auto x = L::WithStaticSizes<1>::Partial();
810     EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
811               (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p))));
812   }
813   {
814     const auto x = L::WithStaticSizes<>::Partial(1, 2, 3);
815     EXPECT_EQ(
816         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
817         (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
818             x.Pointers(p))));
819   }
820   {
821     const auto x = L::WithStaticSizes<1>::Partial(2, 3);
822     EXPECT_EQ(
823         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
824         (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
825             x.Pointers(p))));
826   }
827   {
828     const auto x = L::WithStaticSizes<1, 2>::Partial(3);
829     EXPECT_EQ(
830         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
831         (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
832             x.Pointers(p))));
833   }
834   {
835     const auto x = L::WithStaticSizes<1, 2, 3>::Partial();
836     EXPECT_EQ(
837         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
838         (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
839             x.Pointers(p))));
840   }
841   {
842     const L::WithStaticSizes<1, 2, 3> x;
843     EXPECT_EQ(
844         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
845         (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
846             x.Pointers(p))));
847   }
848 }
849 
TEST(Layout,SliceByIndexSize)850 TEST(Layout, SliceByIndexSize) {
851   alignas(max_align_t) const unsigned char p[100] = {0};
852   {
853     using L = Layout<int32_t>;
854     EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size());
855     EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
856     EXPECT_EQ(3, L(3).Slice<0>(p).size());
857   }
858   {
859     using L = Layout<int32_t, int32_t>;
860     EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
861     EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
862     EXPECT_EQ(5, L(3, 5).Slice<1>(p).size());
863   }
864   {
865     using L = Layout<int8_t, int32_t, Int128>;
866     EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
867     EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size());
868     EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
869     EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size());
870     EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size());
871     EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size());
872     EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size());
873     EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size());
874     EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size());
875   }
876 }
877 
TEST(Layout,SliceByTypeSize)878 TEST(Layout, SliceByTypeSize) {
879   alignas(max_align_t) const unsigned char p[100] = {0};
880   {
881     using L = Layout<int32_t>;
882     EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size());
883     EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size());
884     EXPECT_EQ(3, L(3).Slice<int32_t>(p).size());
885   }
886   {
887     using L = Layout<int8_t, int32_t, Int128>;
888     EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size());
889     EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size());
890     EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size());
891     EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size());
892     EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size());
893     EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size());
894     EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size());
895     EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size());
896     EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size());
897   }
898 }
TEST(Layout,MutableSliceByIndexSize)899 TEST(Layout, MutableSliceByIndexSize) {
900   alignas(max_align_t) unsigned char p[100] = {0};
901   {
902     using L = Layout<int32_t>;
903     EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size());
904     EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
905     EXPECT_EQ(3, L(3).Slice<0>(p).size());
906   }
907   {
908     using L = Layout<int32_t, int32_t>;
909     EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
910     EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
911     EXPECT_EQ(5, L(3, 5).Slice<1>(p).size());
912   }
913   {
914     using L = Layout<int8_t, int32_t, Int128>;
915     EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
916     EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size());
917     EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
918     EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size());
919     EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size());
920     EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size());
921     EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size());
922     EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size());
923     EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size());
924   }
925 }
926 
TEST(Layout,MutableSliceByTypeSize)927 TEST(Layout, MutableSliceByTypeSize) {
928   alignas(max_align_t) unsigned char p[100] = {0};
929   {
930     using L = Layout<int32_t>;
931     EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size());
932     EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size());
933     EXPECT_EQ(3, L(3).Slice<int32_t>(p).size());
934   }
935   {
936     using L = Layout<int8_t, int32_t, Int128>;
937     EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size());
938     EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size());
939     EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size());
940     EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size());
941     EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size());
942     EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size());
943     EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size());
944     EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size());
945     EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size());
946   }
947 }
948 
TEST(Layout,StaticSliceSize)949 TEST(Layout, StaticSliceSize) {
950   alignas(max_align_t) const unsigned char cp[100] = {0};
951   alignas(max_align_t) unsigned char p[100] = {0};
952   using L = Layout<int8_t, int32_t, Int128>;
953   using SL = L::WithStaticSizes<3, 5>;
954 
955   EXPECT_EQ(3, SL::Partial().Slice<0>(cp).size());
956   EXPECT_EQ(3, SL::Partial().Slice<int8_t>(cp).size());
957   EXPECT_EQ(3, SL::Partial(7).Slice<0>(cp).size());
958   EXPECT_EQ(3, SL::Partial(7).Slice<int8_t>(cp).size());
959 
960   EXPECT_EQ(5, SL::Partial().Slice<1>(cp).size());
961   EXPECT_EQ(5, SL::Partial().Slice<int32_t>(cp).size());
962   EXPECT_EQ(5, SL::Partial(7).Slice<1>(cp).size());
963   EXPECT_EQ(5, SL::Partial(7).Slice<int32_t>(cp).size());
964 
965   EXPECT_EQ(7, SL::Partial(7).Slice<2>(cp).size());
966   EXPECT_EQ(7, SL::Partial(7).Slice<Int128>(cp).size());
967 
968   EXPECT_EQ(3, SL::Partial().Slice<0>(p).size());
969   EXPECT_EQ(3, SL::Partial().Slice<int8_t>(p).size());
970   EXPECT_EQ(3, SL::Partial(7).Slice<0>(p).size());
971   EXPECT_EQ(3, SL::Partial(7).Slice<int8_t>(p).size());
972 
973   EXPECT_EQ(5, SL::Partial().Slice<1>(p).size());
974   EXPECT_EQ(5, SL::Partial().Slice<int32_t>(p).size());
975   EXPECT_EQ(5, SL::Partial(7).Slice<1>(p).size());
976   EXPECT_EQ(5, SL::Partial(7).Slice<int32_t>(p).size());
977 
978   EXPECT_EQ(7, SL::Partial(7).Slice<2>(p).size());
979   EXPECT_EQ(7, SL::Partial(7).Slice<Int128>(p).size());
980 }
981 
TEST(Layout,SliceByIndexData)982 TEST(Layout, SliceByIndexData) {
983   alignas(max_align_t) const unsigned char p[100] = {0};
984   {
985     using L = Layout<int32_t>;
986     EXPECT_EQ(
987         0, Distance(
988                p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data()));
989     EXPECT_EQ(
990         0, Distance(
991                p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
992     EXPECT_EQ(0,
993               Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data()));
994   }
995   {
996     using L = Layout<int32_t, int32_t>;
997     EXPECT_EQ(
998         0, Distance(
999                p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
1000     EXPECT_EQ(
1001         0,
1002         Distance(
1003             p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
1004     EXPECT_EQ(
1005         12,
1006         Distance(
1007             p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
1008     EXPECT_EQ(
1009         0, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data()));
1010     EXPECT_EQ(
1011         12, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data()));
1012   }
1013   {
1014     using L = Layout<int8_t, int32_t, Int128>;
1015     EXPECT_EQ(
1016         0, Distance(
1017                p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data()));
1018     EXPECT_EQ(
1019         0, Distance(
1020                p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data()));
1021     EXPECT_EQ(
1022         0, Distance(
1023                p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data()));
1024     EXPECT_EQ(
1025         0,
1026         Distance(
1027             p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
1028     EXPECT_EQ(
1029         0,
1030         Distance(
1031             p, Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
1032     EXPECT_EQ(
1033         0,
1034         Distance(
1035             p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
1036     EXPECT_EQ(
1037         4,
1038         Distance(
1039             p, Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
1040     EXPECT_EQ(
1041         0,
1042         Distance(
1043             p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
1044     EXPECT_EQ(
1045         8,
1046         Distance(
1047             p, Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
1048     EXPECT_EQ(
1049         0,
1050         Distance(
1051             p,
1052             Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
1053     EXPECT_EQ(
1054         0,
1055         Distance(
1056             p,
1057             Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
1058     EXPECT_EQ(
1059         0,
1060         Distance(
1061             p,
1062             Type<Span<const Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
1063     EXPECT_EQ(
1064         0,
1065         Distance(
1066             p,
1067             Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
1068     EXPECT_EQ(
1069         4,
1070         Distance(
1071             p,
1072             Type<Span<const int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
1073     EXPECT_EQ(
1074         8,
1075         Distance(
1076             p,
1077             Type<Span<const Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
1078     EXPECT_EQ(
1079         0,
1080         Distance(
1081             p,
1082             Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
1083     EXPECT_EQ(
1084         24,
1085         Distance(
1086             p,
1087             Type<Span<const Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
1088     EXPECT_EQ(
1089         8,
1090         Distance(
1091             p,
1092             Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
1093     EXPECT_EQ(
1094         0,
1095         Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
1096     EXPECT_EQ(
1097         24,
1098         Distance(p, Type<Span<const Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
1099     EXPECT_EQ(
1100         8,
1101         Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
1102   }
1103 }
1104 
TEST(Layout,SliceByTypeData)1105 TEST(Layout, SliceByTypeData) {
1106   alignas(max_align_t) const unsigned char p[100] = {0};
1107   {
1108     using L = Layout<int32_t>;
1109     EXPECT_EQ(
1110         0,
1111         Distance(
1112             p,
1113             Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
1114     EXPECT_EQ(
1115         0,
1116         Distance(
1117             p,
1118             Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
1119     EXPECT_EQ(
1120         0,
1121         Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data()));
1122   }
1123   {
1124     using L = Layout<int8_t, int32_t, Int128>;
1125     EXPECT_EQ(
1126         0,
1127         Distance(
1128             p,
1129             Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
1130     EXPECT_EQ(
1131         0,
1132         Distance(
1133             p,
1134             Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
1135     EXPECT_EQ(
1136         0,
1137         Distance(
1138             p,
1139             Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
1140     EXPECT_EQ(
1141         0,
1142         Distance(p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p))
1143                         .data()));
1144     EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
1145                                  L::Partial(0, 0).Slice<int32_t>(p))
1146                                  .data()));
1147     EXPECT_EQ(
1148         0,
1149         Distance(p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p))
1150                         .data()));
1151     EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
1152                                  L::Partial(1, 0).Slice<int32_t>(p))
1153                                  .data()));
1154     EXPECT_EQ(
1155         0,
1156         Distance(p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p))
1157                         .data()));
1158     EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
1159                                  L::Partial(5, 3).Slice<int32_t>(p))
1160                                  .data()));
1161     EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
1162                                  L::Partial(0, 0, 0).Slice<int8_t>(p))
1163                                  .data()));
1164     EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
1165                                  L::Partial(0, 0, 0).Slice<int32_t>(p))
1166                                  .data()));
1167     EXPECT_EQ(0, Distance(p, Type<Span<const Int128>>(
1168                                  L::Partial(0, 0, 0).Slice<Int128>(p))
1169                                  .data()));
1170     EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
1171                                  L::Partial(1, 0, 0).Slice<int8_t>(p))
1172                                  .data()));
1173     EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
1174                                  L::Partial(1, 0, 0).Slice<int32_t>(p))
1175                                  .data()));
1176     EXPECT_EQ(8, Distance(p, Type<Span<const Int128>>(
1177                                  L::Partial(1, 0, 0).Slice<Int128>(p))
1178                                  .data()));
1179     EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
1180                                  L::Partial(5, 3, 1).Slice<int8_t>(p))
1181                                  .data()));
1182     EXPECT_EQ(24, Distance(p, Type<Span<const Int128>>(
1183                                   L::Partial(5, 3, 1).Slice<Int128>(p))
1184                                   .data()));
1185     EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
1186                                  L::Partial(5, 3, 1).Slice<int32_t>(p))
1187                                  .data()));
1188     EXPECT_EQ(
1189         0,
1190         Distance(p,
1191                  Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
1192     EXPECT_EQ(
1193         24,
1194         Distance(p,
1195                  Type<Span<const Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
1196     EXPECT_EQ(
1197         8,
1198         Distance(
1199             p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
1200   }
1201 }
1202 
TEST(Layout,MutableSliceByIndexData)1203 TEST(Layout, MutableSliceByIndexData) {
1204   alignas(max_align_t) unsigned char p[100] = {0};
1205   {
1206     using L = Layout<int32_t>;
1207     EXPECT_EQ(
1208         0, Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data()));
1209     EXPECT_EQ(
1210         0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
1211     EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<0>(p)).data()));
1212   }
1213   {
1214     using L = Layout<int32_t, int32_t>;
1215     EXPECT_EQ(
1216         0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
1217     EXPECT_EQ(
1218         0,
1219         Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
1220     EXPECT_EQ(
1221         12,
1222         Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
1223     EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<0>(p)).data()));
1224     EXPECT_EQ(12, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<1>(p)).data()));
1225   }
1226   {
1227     using L = Layout<int8_t, int32_t, Int128>;
1228     EXPECT_EQ(
1229         0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data()));
1230     EXPECT_EQ(
1231         0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data()));
1232     EXPECT_EQ(
1233         0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data()));
1234     EXPECT_EQ(
1235         0,
1236         Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
1237     EXPECT_EQ(
1238         0,
1239         Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
1240     EXPECT_EQ(
1241         0,
1242         Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
1243     EXPECT_EQ(
1244         4,
1245         Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
1246     EXPECT_EQ(
1247         0,
1248         Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
1249     EXPECT_EQ(
1250         8,
1251         Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
1252     EXPECT_EQ(
1253         0, Distance(
1254                p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
1255     EXPECT_EQ(
1256         0, Distance(
1257                p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
1258     EXPECT_EQ(
1259         0, Distance(
1260                p, Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
1261     EXPECT_EQ(
1262         0, Distance(
1263                p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
1264     EXPECT_EQ(
1265         4, Distance(
1266                p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
1267     EXPECT_EQ(
1268         8, Distance(
1269                p, Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
1270     EXPECT_EQ(
1271         0, Distance(
1272                p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
1273     EXPECT_EQ(
1274         24, Distance(
1275                 p, Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
1276     EXPECT_EQ(
1277         8, Distance(
1278                p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
1279     EXPECT_EQ(0,
1280               Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
1281     EXPECT_EQ(24,
1282               Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
1283     EXPECT_EQ(8,
1284               Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
1285   }
1286 }
1287 
TEST(Layout,MutableSliceByTypeData)1288 TEST(Layout, MutableSliceByTypeData) {
1289   alignas(max_align_t) unsigned char p[100] = {0};
1290   {
1291     using L = Layout<int32_t>;
1292     EXPECT_EQ(
1293         0, Distance(
1294                p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
1295     EXPECT_EQ(
1296         0, Distance(
1297                p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
1298     EXPECT_EQ(0,
1299               Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data()));
1300   }
1301   {
1302     using L = Layout<int8_t, int32_t, Int128>;
1303     EXPECT_EQ(
1304         0,
1305         Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
1306     EXPECT_EQ(
1307         0,
1308         Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
1309     EXPECT_EQ(
1310         0,
1311         Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
1312     EXPECT_EQ(
1313         0,
1314         Distance(p,
1315                  Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
1316     EXPECT_EQ(
1317         0,
1318         Distance(
1319             p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
1320     EXPECT_EQ(
1321         0,
1322         Distance(p,
1323                  Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
1324     EXPECT_EQ(
1325         4,
1326         Distance(
1327             p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
1328     EXPECT_EQ(
1329         0,
1330         Distance(p,
1331                  Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
1332     EXPECT_EQ(
1333         8,
1334         Distance(
1335             p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
1336     EXPECT_EQ(
1337         0,
1338         Distance(
1339             p,
1340             Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
1341     EXPECT_EQ(
1342         0,
1343         Distance(
1344             p,
1345             Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data()));
1346     EXPECT_EQ(
1347         0,
1348         Distance(
1349             p,
1350             Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<Int128>(p)).data()));
1351     EXPECT_EQ(
1352         0,
1353         Distance(
1354             p,
1355             Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
1356     EXPECT_EQ(
1357         4,
1358         Distance(
1359             p,
1360             Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data()));
1361     EXPECT_EQ(
1362         8,
1363         Distance(
1364             p,
1365             Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<Int128>(p)).data()));
1366     EXPECT_EQ(
1367         0,
1368         Distance(
1369             p,
1370             Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
1371     EXPECT_EQ(
1372         24,
1373         Distance(
1374             p,
1375             Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<Int128>(p)).data()));
1376     EXPECT_EQ(
1377         8,
1378         Distance(
1379             p,
1380             Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data()));
1381     EXPECT_EQ(
1382         0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
1383     EXPECT_EQ(
1384         24,
1385         Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
1386     EXPECT_EQ(
1387         8,
1388         Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
1389   }
1390 }
1391 
TEST(Layout,StaticSliceData)1392 TEST(Layout, StaticSliceData) {
1393   alignas(max_align_t) const unsigned char cp[100] = {0};
1394   alignas(max_align_t) unsigned char p[100] = {0};
1395   using L = Layout<int8_t, int32_t, Int128>;
1396   using SL = L::WithStaticSizes<3, 5>;
1397 
1398   EXPECT_EQ(0, Distance(cp, SL::Partial().Slice<0>(cp).data()));
1399   EXPECT_EQ(0, Distance(cp, SL::Partial().Slice<int8_t>(cp).data()));
1400   EXPECT_EQ(0, Distance(cp, SL::Partial(7).Slice<0>(cp).data()));
1401   EXPECT_EQ(0, Distance(cp, SL::Partial(7).Slice<int8_t>(cp).data()));
1402 
1403   EXPECT_EQ(4, Distance(cp, SL::Partial().Slice<1>(cp).data()));
1404   EXPECT_EQ(4, Distance(cp, SL::Partial().Slice<int32_t>(cp).data()));
1405   EXPECT_EQ(4, Distance(cp, SL::Partial(7).Slice<1>(cp).data()));
1406   EXPECT_EQ(4, Distance(cp, SL::Partial(7).Slice<int32_t>(cp).data()));
1407 
1408   EXPECT_EQ(24, Distance(cp, SL::Partial(7).Slice<2>(cp).data()));
1409   EXPECT_EQ(24, Distance(cp, SL::Partial(7).Slice<Int128>(cp).data()));
1410 
1411   EXPECT_EQ(0, Distance(p, SL::Partial().Slice<0>(p).data()));
1412   EXPECT_EQ(0, Distance(p, SL::Partial().Slice<int8_t>(p).data()));
1413   EXPECT_EQ(0, Distance(p, SL::Partial(7).Slice<0>(p).data()));
1414   EXPECT_EQ(0, Distance(p, SL::Partial(7).Slice<int8_t>(p).data()));
1415 
1416   EXPECT_EQ(4, Distance(p, SL::Partial().Slice<1>(p).data()));
1417   EXPECT_EQ(4, Distance(p, SL::Partial().Slice<int32_t>(p).data()));
1418   EXPECT_EQ(4, Distance(p, SL::Partial(7).Slice<1>(p).data()));
1419   EXPECT_EQ(4, Distance(p, SL::Partial(7).Slice<int32_t>(p).data()));
1420 
1421   EXPECT_EQ(24, Distance(p, SL::Partial(7).Slice<2>(p).data()));
1422   EXPECT_EQ(24, Distance(p, SL::Partial(7).Slice<Int128>(p).data()));
1423 }
1424 
1425 MATCHER_P(IsSameSlice, slice, "") {
1426   return arg.size() == slice.size() && arg.data() == slice.data();
1427 }
1428 
1429 template <typename... M>
1430 class TupleMatcher {
1431  public:
TupleMatcher(M...matchers)1432   explicit TupleMatcher(M... matchers) : matchers_(std::move(matchers)...) {}
1433 
1434   template <typename Tuple>
MatchAndExplain(const Tuple & p,testing::MatchResultListener *) const1435   bool MatchAndExplain(const Tuple& p,
1436                        testing::MatchResultListener* /* listener */) const {
1437     static_assert(std::tuple_size<Tuple>::value == sizeof...(M), "");
1438     return MatchAndExplainImpl(
1439         p, absl::make_index_sequence<std::tuple_size<Tuple>::value>{});
1440   }
1441 
1442   // For the matcher concept. Left empty as we don't really need the diagnostics
1443   // right now.
DescribeTo(::std::ostream * os) const1444   void DescribeTo(::std::ostream* os) const {}
DescribeNegationTo(::std::ostream * os) const1445   void DescribeNegationTo(::std::ostream* os) const {}
1446 
1447  private:
1448   template <typename Tuple, size_t... Is>
MatchAndExplainImpl(const Tuple & p,absl::index_sequence<Is...>) const1449   bool MatchAndExplainImpl(const Tuple& p, absl::index_sequence<Is...>) const {
1450     // Using std::min as a simple variadic "and".
1451     return std::min(
1452         {true, testing::SafeMatcherCast<
1453                    const typename std::tuple_element<Is, Tuple>::type&>(
1454                    std::get<Is>(matchers_))
1455                    .Matches(std::get<Is>(p))...});
1456   }
1457 
1458   std::tuple<M...> matchers_;
1459 };
1460 
1461 template <typename... M>
Tuple(M...matchers)1462 testing::PolymorphicMatcher<TupleMatcher<M...>> Tuple(M... matchers) {
1463   return testing::MakePolymorphicMatcher(
1464       TupleMatcher<M...>(std::move(matchers)...));
1465 }
1466 
TEST(Layout,Slices)1467 TEST(Layout, Slices) {
1468   alignas(max_align_t) const unsigned char p[100] = {0};
1469   using L = Layout<int8_t, int8_t, Int128>;
1470   {
1471     const auto x = L::Partial();
1472     EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple());
1473   }
1474   {
1475     const auto x = L::Partial(1);
1476     EXPECT_THAT(Type<std::tuple<Span<const int8_t>>>(x.Slices(p)),
1477                 Tuple(IsSameSlice(x.Slice<0>(p))));
1478   }
1479   {
1480     const auto x = L::Partial(1, 2);
1481     EXPECT_THAT(
1482         (Type<std::tuple<Span<const int8_t>, Span<const int8_t>>>(x.Slices(p))),
1483         Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));
1484   }
1485   {
1486     const auto x = L::Partial(1, 2, 3);
1487     EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
1488                                  Span<const Int128>>>(x.Slices(p))),
1489                 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1490                       IsSameSlice(x.Slice<2>(p))));
1491   }
1492   {
1493     const L x(1, 2, 3);
1494     EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
1495                                  Span<const Int128>>>(x.Slices(p))),
1496                 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1497                       IsSameSlice(x.Slice<2>(p))));
1498   }
1499 }
1500 
TEST(Layout,MutableSlices)1501 TEST(Layout, MutableSlices) {
1502   alignas(max_align_t) unsigned char p[100] = {0};
1503   using L = Layout<int8_t, int8_t, Int128>;
1504   {
1505     const auto x = L::Partial();
1506     EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple());
1507   }
1508   {
1509     const auto x = L::Partial(1);
1510     EXPECT_THAT(Type<std::tuple<Span<int8_t>>>(x.Slices(p)),
1511                 Tuple(IsSameSlice(x.Slice<0>(p))));
1512   }
1513   {
1514     const auto x = L::Partial(1, 2);
1515     EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>>>(x.Slices(p))),
1516                 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));
1517   }
1518   {
1519     const auto x = L::Partial(1, 2, 3);
1520     EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
1521                     x.Slices(p))),
1522                 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1523                       IsSameSlice(x.Slice<2>(p))));
1524   }
1525   {
1526     const L x(1, 2, 3);
1527     EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
1528                     x.Slices(p))),
1529                 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1530                       IsSameSlice(x.Slice<2>(p))));
1531   }
1532 }
1533 
TEST(Layout,StaticSlices)1534 TEST(Layout, StaticSlices) {
1535   alignas(max_align_t) const unsigned char cp[100] = {0};
1536   alignas(max_align_t) unsigned char p[100] = {0};
1537   using SL = Layout<int8_t, int8_t, Int128>::WithStaticSizes<1, 2>;
1538   {
1539     const auto x = SL::Partial();
1540     EXPECT_THAT(
1541         (Type<std::tuple<Span<const int8_t>, Span<const int8_t>>>(
1542             x.Slices(cp))),
1543         Tuple(IsSameSlice(x.Slice<0>(cp)), IsSameSlice(x.Slice<1>(cp))));
1544     EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>>>(x.Slices(p))),
1545                 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));
1546   }
1547   {
1548     const auto x = SL::Partial(3);
1549     EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
1550                                  Span<const Int128>>>(x.Slices(cp))),
1551                 Tuple(IsSameSlice(x.Slice<0>(cp)), IsSameSlice(x.Slice<1>(cp)),
1552                       IsSameSlice(x.Slice<2>(cp))));
1553     EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
1554                     x.Slices(p))),
1555                 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1556                       IsSameSlice(x.Slice<2>(p))));
1557   }
1558   {
1559     const SL x(3);
1560     EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
1561                                  Span<const Int128>>>(x.Slices(cp))),
1562                 Tuple(IsSameSlice(x.Slice<0>(cp)), IsSameSlice(x.Slice<1>(cp)),
1563                       IsSameSlice(x.Slice<2>(cp))));
1564     EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
1565                     x.Slices(p))),
1566                 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1567                       IsSameSlice(x.Slice<2>(p))));
1568   }
1569 }
1570 
TEST(Layout,UnalignedTypes)1571 TEST(Layout, UnalignedTypes) {
1572   constexpr Layout<unsigned char, unsigned char, unsigned char> x(1, 2, 3);
1573   alignas(max_align_t) unsigned char p[x.AllocSize() + 1];
1574   EXPECT_THAT(x.Pointers(p + 1), Tuple(p + 1, p + 2, p + 4));
1575 }
1576 
TEST(Layout,CustomAlignment)1577 TEST(Layout, CustomAlignment) {
1578   constexpr Layout<unsigned char, Aligned<unsigned char, 8>> x(1, 2);
1579   alignas(max_align_t) unsigned char p[x.AllocSize()];
1580   EXPECT_EQ(10, x.AllocSize());
1581   EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 8));
1582 }
1583 
TEST(Layout,OverAligned)1584 TEST(Layout, OverAligned) {
1585   constexpr size_t M = alignof(max_align_t);
1586   constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3);
1587 #ifdef __GNUC__
1588   // Using __attribute__ ((aligned ())) instead of alignas to bypass a gcc bug:
1589   // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89357
1590   __attribute__((aligned(2 * M))) unsigned char p[x.AllocSize()];
1591 #else
1592   alignas(2 * M) unsigned char p[x.AllocSize()];
1593 #endif
1594   EXPECT_EQ(2 * M + 3, x.AllocSize());
1595   EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 2 * M));
1596 }
1597 
TEST(Layout,Alignment)1598 TEST(Layout, Alignment) {
1599   static_assert(Layout<int8_t>::Alignment() == 1, "");
1600   static_assert(Layout<int32_t>::Alignment() == 4, "");
1601   static_assert(Layout<Int64>::Alignment() == 8, "");
1602   static_assert(Layout<Aligned<int8_t, 64>>::Alignment() == 64, "");
1603   static_assert(Layout<int8_t, int32_t, Int64>::Alignment() == 8, "");
1604   static_assert(Layout<int8_t, Int64, int32_t>::Alignment() == 8, "");
1605   static_assert(Layout<int32_t, int8_t, Int64>::Alignment() == 8, "");
1606   static_assert(Layout<int32_t, Int64, int8_t>::Alignment() == 8, "");
1607   static_assert(Layout<Int64, int8_t, int32_t>::Alignment() == 8, "");
1608   static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, "");
1609   static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, "");
1610   static_assert(
1611       Layout<Aligned<int8_t, 64>>::WithStaticSizes<>::Alignment() == 64, "");
1612   static_assert(
1613       Layout<Aligned<int8_t, 64>>::WithStaticSizes<2>::Alignment() == 64, "");
1614 }
1615 
TEST(Layout,StaticAlignment)1616 TEST(Layout, StaticAlignment) {
1617   static_assert(Layout<int8_t>::WithStaticSizes<>::Alignment() == 1, "");
1618   static_assert(Layout<int8_t>::WithStaticSizes<0>::Alignment() == 1, "");
1619   static_assert(Layout<int8_t>::WithStaticSizes<7>::Alignment() == 1, "");
1620   static_assert(Layout<int32_t>::WithStaticSizes<>::Alignment() == 4, "");
1621   static_assert(Layout<int32_t>::WithStaticSizes<0>::Alignment() == 4, "");
1622   static_assert(Layout<int32_t>::WithStaticSizes<3>::Alignment() == 4, "");
1623   static_assert(
1624       Layout<Aligned<int8_t, 64>>::WithStaticSizes<>::Alignment() == 64, "");
1625   static_assert(
1626       Layout<Aligned<int8_t, 64>>::WithStaticSizes<0>::Alignment() == 64, "");
1627   static_assert(
1628       Layout<Aligned<int8_t, 64>>::WithStaticSizes<2>::Alignment() == 64, "");
1629   static_assert(
1630       Layout<int32_t, Int64, int8_t>::WithStaticSizes<>::Alignment() == 8, "");
1631   static_assert(
1632       Layout<int32_t, Int64, int8_t>::WithStaticSizes<0, 0, 0>::Alignment() ==
1633           8,
1634       "");
1635   static_assert(
1636       Layout<int32_t, Int64, int8_t>::WithStaticSizes<1, 1, 1>::Alignment() ==
1637           8,
1638       "");
1639 }
1640 
TEST(Layout,ConstexprPartial)1641 TEST(Layout, ConstexprPartial) {
1642   constexpr size_t M = alignof(max_align_t);
1643   constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3);
1644   static_assert(x.Partial(1).template Offset<1>() == 2 * M, "");
1645 }
1646 
TEST(Layout,StaticConstexpr)1647 TEST(Layout, StaticConstexpr) {
1648   constexpr size_t M = alignof(max_align_t);
1649   using L = Layout<unsigned char, Aligned<unsigned char, 2 * M>>;
1650   using SL = L::WithStaticSizes<1, 3>;
1651   constexpr SL x;
1652   static_assert(x.Offset<1>() == 2 * M, "");
1653 }
1654 
1655 // [from, to)
1656 struct Region {
1657   size_t from;
1658   size_t to;
1659 };
1660 
ExpectRegionPoisoned(const unsigned char * p,size_t n,bool poisoned)1661 void ExpectRegionPoisoned(const unsigned char* p, size_t n, bool poisoned) {
1662 #ifdef ABSL_HAVE_ADDRESS_SANITIZER
1663   for (size_t i = 0; i != n; ++i) {
1664     EXPECT_EQ(poisoned, __asan_address_is_poisoned(p + i));
1665   }
1666 #endif
1667 }
1668 
1669 template <size_t N>
ExpectPoisoned(const unsigned char (& buf)[N],std::initializer_list<Region> reg)1670 void ExpectPoisoned(const unsigned char (&buf)[N],
1671                     std::initializer_list<Region> reg) {
1672   size_t prev = 0;
1673   for (const Region& r : reg) {
1674     ExpectRegionPoisoned(buf + prev, r.from - prev, false);
1675     ExpectRegionPoisoned(buf + r.from, r.to - r.from, true);
1676     prev = r.to;
1677   }
1678   ExpectRegionPoisoned(buf + prev, N - prev, false);
1679 }
1680 
TEST(Layout,PoisonPadding)1681 TEST(Layout, PoisonPadding) {
1682   using L = Layout<int8_t, Int64, int32_t, Int128>;
1683 
1684   constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize();
1685   {
1686     constexpr auto x = L::Partial();
1687     alignas(max_align_t) const unsigned char c[n] = {};
1688     x.PoisonPadding(c);
1689     EXPECT_EQ(x.Slices(c), x.Slices(c));
1690     ExpectPoisoned(c, {});
1691   }
1692   {
1693     constexpr auto x = L::Partial(1);
1694     alignas(max_align_t) const unsigned char c[n] = {};
1695     x.PoisonPadding(c);
1696     EXPECT_EQ(x.Slices(c), x.Slices(c));
1697     ExpectPoisoned(c, {{1, 8}});
1698   }
1699   {
1700     constexpr auto x = L::Partial(1, 2);
1701     alignas(max_align_t) const unsigned char c[n] = {};
1702     x.PoisonPadding(c);
1703     EXPECT_EQ(x.Slices(c), x.Slices(c));
1704     ExpectPoisoned(c, {{1, 8}});
1705   }
1706   {
1707     constexpr auto x = L::Partial(1, 2, 3);
1708     alignas(max_align_t) const unsigned char c[n] = {};
1709     x.PoisonPadding(c);
1710     EXPECT_EQ(x.Slices(c), x.Slices(c));
1711     ExpectPoisoned(c, {{1, 8}, {36, 40}});
1712   }
1713   {
1714     constexpr auto x = L::Partial(1, 2, 3, 4);
1715     alignas(max_align_t) const unsigned char c[n] = {};
1716     x.PoisonPadding(c);
1717     EXPECT_EQ(x.Slices(c), x.Slices(c));
1718     ExpectPoisoned(c, {{1, 8}, {36, 40}});
1719   }
1720   {
1721     constexpr L x(1, 2, 3, 4);
1722     alignas(max_align_t) const unsigned char c[n] = {};
1723     x.PoisonPadding(c);
1724     EXPECT_EQ(x.Slices(c), x.Slices(c));
1725     ExpectPoisoned(c, {{1, 8}, {36, 40}});
1726   }
1727 }
1728 
TEST(Layout,StaticPoisonPadding)1729 TEST(Layout, StaticPoisonPadding) {
1730   using L = Layout<int8_t, Int64, int32_t, Int128>;
1731   using SL = L::WithStaticSizes<1, 2>;
1732 
1733   constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize();
1734   {
1735     constexpr auto x = SL::Partial();
1736     alignas(max_align_t) const unsigned char c[n] = {};
1737     x.PoisonPadding(c);
1738     EXPECT_EQ(x.Slices(c), x.Slices(c));
1739     ExpectPoisoned(c, {{1, 8}});
1740   }
1741   {
1742     constexpr auto x = SL::Partial(3);
1743     alignas(max_align_t) const unsigned char c[n] = {};
1744     x.PoisonPadding(c);
1745     EXPECT_EQ(x.Slices(c), x.Slices(c));
1746     ExpectPoisoned(c, {{1, 8}, {36, 40}});
1747   }
1748   {
1749     constexpr auto x = SL::Partial(3, 4);
1750     alignas(max_align_t) const unsigned char c[n] = {};
1751     x.PoisonPadding(c);
1752     EXPECT_EQ(x.Slices(c), x.Slices(c));
1753     ExpectPoisoned(c, {{1, 8}, {36, 40}});
1754   }
1755   {
1756     constexpr SL x(3, 4);
1757     alignas(max_align_t) const unsigned char c[n] = {};
1758     x.PoisonPadding(c);
1759     EXPECT_EQ(x.Slices(c), x.Slices(c));
1760     ExpectPoisoned(c, {{1, 8}, {36, 40}});
1761   }
1762 }
1763 
TEST(Layout,DebugString)1764 TEST(Layout, DebugString) {
1765   {
1766     constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial();
1767     EXPECT_EQ("@0<signed char>(1)", x.DebugString());
1768   }
1769   {
1770     constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1);
1771     EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)", x.DebugString());
1772   }
1773   {
1774     constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2);
1775     EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)",
1776               x.DebugString());
1777   }
1778   {
1779     constexpr auto x =
1780         Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
1781     EXPECT_EQ(
1782         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1783         "@16" +
1784             Int128::Name() + "(16)",
1785         x.DebugString());
1786   }
1787   {
1788     constexpr auto x =
1789         Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
1790     EXPECT_EQ(
1791         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1792         "@16" +
1793             Int128::Name() + "(16)[4]",
1794         x.DebugString());
1795   }
1796   {
1797     constexpr Layout<int8_t, int32_t, int8_t, Int128> x(1, 2, 3, 4);
1798     EXPECT_EQ(
1799         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1800         "@16" +
1801             Int128::Name() + "(16)[4]",
1802         x.DebugString());
1803   }
1804 }
1805 
TEST(Layout,StaticDebugString)1806 TEST(Layout, StaticDebugString) {
1807   {
1808     constexpr auto x =
1809         Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<>::Partial();
1810     EXPECT_EQ("@0<signed char>(1)", x.DebugString());
1811   }
1812   {
1813     constexpr auto x =
1814         Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<>::Partial(1);
1815     EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)", x.DebugString());
1816   }
1817   {
1818     constexpr auto x =
1819         Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<1>::Partial();
1820     EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)", x.DebugString());
1821   }
1822   {
1823     constexpr auto x =
1824         Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<>::Partial(1,
1825                                                                             2);
1826     EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)",
1827               x.DebugString());
1828   }
1829   {
1830     constexpr auto x =
1831         Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<1>::Partial(2);
1832     EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)",
1833               x.DebugString());
1834   }
1835   {
1836     constexpr auto x = Layout<int8_t, int32_t, int8_t,
1837                               Int128>::WithStaticSizes<1, 2>::Partial();
1838     EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)",
1839               x.DebugString());
1840   }
1841   {
1842     constexpr auto x = Layout<int8_t, int32_t, int8_t,
1843                               Int128>::WithStaticSizes<1, 2, 3, 4>::Partial();
1844     EXPECT_EQ(
1845         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1846         "@16" +
1847             Int128::Name() + "(16)[4]",
1848         x.DebugString());
1849   }
1850   {
1851     constexpr Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<1, 2, 3,
1852                                                                        4>
1853         x;
1854     EXPECT_EQ(
1855         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1856         "@16" +
1857             Int128::Name() + "(16)[4]",
1858         x.DebugString());
1859   }
1860 }
1861 
TEST(Layout,CharTypes)1862 TEST(Layout, CharTypes) {
1863   constexpr Layout<int32_t> x(1);
1864   alignas(max_align_t) char c[x.AllocSize()] = {};
1865   alignas(max_align_t) unsigned char uc[x.AllocSize()] = {};
1866   alignas(max_align_t) signed char sc[x.AllocSize()] = {};
1867   alignas(max_align_t) const char cc[x.AllocSize()] = {};
1868   alignas(max_align_t) const unsigned char cuc[x.AllocSize()] = {};
1869   alignas(max_align_t) const signed char csc[x.AllocSize()] = {};
1870 
1871   Type<int32_t*>(x.Pointer<0>(c));
1872   Type<int32_t*>(x.Pointer<0>(uc));
1873   Type<int32_t*>(x.Pointer<0>(sc));
1874   Type<const int32_t*>(x.Pointer<0>(cc));
1875   Type<const int32_t*>(x.Pointer<0>(cuc));
1876   Type<const int32_t*>(x.Pointer<0>(csc));
1877 
1878   Type<int32_t*>(x.Pointer<int32_t>(c));
1879   Type<int32_t*>(x.Pointer<int32_t>(uc));
1880   Type<int32_t*>(x.Pointer<int32_t>(sc));
1881   Type<const int32_t*>(x.Pointer<int32_t>(cc));
1882   Type<const int32_t*>(x.Pointer<int32_t>(cuc));
1883   Type<const int32_t*>(x.Pointer<int32_t>(csc));
1884 
1885   Type<std::tuple<int32_t*>>(x.Pointers(c));
1886   Type<std::tuple<int32_t*>>(x.Pointers(uc));
1887   Type<std::tuple<int32_t*>>(x.Pointers(sc));
1888   Type<std::tuple<const int32_t*>>(x.Pointers(cc));
1889   Type<std::tuple<const int32_t*>>(x.Pointers(cuc));
1890   Type<std::tuple<const int32_t*>>(x.Pointers(csc));
1891 
1892   Type<Span<int32_t>>(x.Slice<0>(c));
1893   Type<Span<int32_t>>(x.Slice<0>(uc));
1894   Type<Span<int32_t>>(x.Slice<0>(sc));
1895   Type<Span<const int32_t>>(x.Slice<0>(cc));
1896   Type<Span<const int32_t>>(x.Slice<0>(cuc));
1897   Type<Span<const int32_t>>(x.Slice<0>(csc));
1898 
1899   Type<std::tuple<Span<int32_t>>>(x.Slices(c));
1900   Type<std::tuple<Span<int32_t>>>(x.Slices(uc));
1901   Type<std::tuple<Span<int32_t>>>(x.Slices(sc));
1902   Type<std::tuple<Span<const int32_t>>>(x.Slices(cc));
1903   Type<std::tuple<Span<const int32_t>>>(x.Slices(cuc));
1904   Type<std::tuple<Span<const int32_t>>>(x.Slices(csc));
1905 }
1906 
TEST(Layout,ConstElementType)1907 TEST(Layout, ConstElementType) {
1908   constexpr Layout<const int32_t> x(1);
1909   alignas(int32_t) char c[x.AllocSize()] = {};
1910   const char* cc = c;
1911   const int32_t* p = reinterpret_cast<const int32_t*>(cc);
1912 
1913   EXPECT_EQ(alignof(int32_t), x.Alignment());
1914 
1915   EXPECT_EQ(0, x.Offset<0>());
1916   EXPECT_EQ(0, x.Offset<const int32_t>());
1917 
1918   EXPECT_THAT(x.Offsets(), ElementsAre(0));
1919 
1920   EXPECT_EQ(1, x.Size<0>());
1921   EXPECT_EQ(1, x.Size<const int32_t>());
1922 
1923   EXPECT_THAT(x.Sizes(), ElementsAre(1));
1924 
1925   EXPECT_EQ(sizeof(int32_t), x.AllocSize());
1926 
1927   EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(c)));
1928   EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(cc)));
1929 
1930   EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(c)));
1931   EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(cc)));
1932 
1933   EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(c)), Tuple(p));
1934   EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(cc)), Tuple(p));
1935 
1936   EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(c)),
1937               IsSameSlice(Span<const int32_t>(p, 1)));
1938   EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(cc)),
1939               IsSameSlice(Span<const int32_t>(p, 1)));
1940 
1941   EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(c)),
1942               IsSameSlice(Span<const int32_t>(p, 1)));
1943   EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(cc)),
1944               IsSameSlice(Span<const int32_t>(p, 1)));
1945 
1946   EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(c)),
1947               Tuple(IsSameSlice(Span<const int32_t>(p, 1))));
1948   EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(cc)),
1949               Tuple(IsSameSlice(Span<const int32_t>(p, 1))));
1950 }
1951 
1952 namespace example {
1953 
1954 // Immutable move-only string with sizeof equal to sizeof(void*). The string
1955 // size and the characters are kept in the same heap allocation.
1956 class CompactString {
1957  public:
CompactString(const char * s="")1958   CompactString(const char* s = "") {  // NOLINT
1959     const size_t size = strlen(s);
1960     // size_t[1], followed by char[size + 1].
1961     // This statement doesn't allocate memory.
1962     const L layout(1, size + 1);
1963     // AllocSize() tells us how much memory we need to allocate for all our
1964     // data.
1965     p_.reset(new unsigned char[layout.AllocSize()]);
1966     // If running under ASAN, mark the padding bytes, if any, to catch memory
1967     // errors.
1968     layout.PoisonPadding(p_.get());
1969     // Store the size in the allocation.
1970     // Pointer<size_t>() is a synonym for Pointer<0>().
1971     *layout.Pointer<size_t>(p_.get()) = size;
1972     // Store the characters in the allocation.
1973     memcpy(layout.Pointer<char>(p_.get()), s, size + 1);
1974   }
1975 
size() const1976   size_t size() const {
1977     // Equivalent to reinterpret_cast<size_t&>(*p).
1978     return *L::Partial().Pointer<size_t>(p_.get());
1979   }
1980 
c_str() const1981   const char* c_str() const {
1982     // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)).
1983     // The argument in Partial(1) specifies that we have size_t[1] in front of
1984     // the characters.
1985     return L::Partial(1).Pointer<char>(p_.get());
1986   }
1987 
1988  private:
1989   // Our heap allocation contains a size_t followed by an array of chars.
1990   using L = Layout<size_t, char>;
1991   std::unique_ptr<unsigned char[]> p_;
1992 };
1993 
TEST(CompactString,Works)1994 TEST(CompactString, Works) {
1995   CompactString s = "hello";
1996   EXPECT_EQ(5, s.size());
1997   EXPECT_STREQ("hello", s.c_str());
1998 }
1999 
2000 // Same as the previous CompactString example, except we set the first array
2001 // size to 1 statically, since we know it is always 1. This allows us to compute
2002 // the offset of the character array at compile time.
2003 class StaticCompactString {
2004  public:
StaticCompactString(const char * s="")2005   StaticCompactString(const char* s = "") {  // NOLINT
2006     const size_t size = strlen(s);
2007     const SL layout(size + 1);
2008     p_.reset(new unsigned char[layout.AllocSize()]);
2009     layout.PoisonPadding(p_.get());
2010     *layout.Pointer<size_t>(p_.get()) = size;
2011     memcpy(layout.Pointer<char>(p_.get()), s, size + 1);
2012   }
2013 
size() const2014   size_t size() const { return *SL::Partial().Pointer<size_t>(p_.get()); }
2015 
c_str() const2016   const char* c_str() const { return SL::Partial().Pointer<char>(p_.get()); }
2017 
2018  private:
2019   using SL = Layout<size_t, char>::WithStaticSizes<1>;
2020   std::unique_ptr<unsigned char[]> p_;
2021 };
2022 
TEST(StaticCompactString,Works)2023 TEST(StaticCompactString, Works) {
2024   StaticCompactString s = "hello";
2025   EXPECT_EQ(5, s.size());
2026   EXPECT_STREQ("hello", s.c_str());
2027 }
2028 
2029 }  // namespace example
2030 
2031 }  // namespace
2032 }  // namespace container_internal
2033 ABSL_NAMESPACE_END
2034 }  // namespace absl
2035