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 {
33 ABSL_NAMESPACE_BEGIN
34 namespace container_internal {
35 namespace {
36 
37 using ::absl::Span;
38 using ::testing::ElementsAre;
39 
Distance(const void * from,const void * to)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 {
53   uint64_t a, b;
operator ==(Int128 lhs,Int128 rhs)54   friend bool operator==(Int128 lhs, Int128 rhs) {
55     return std::tie(lhs.a, lhs.b) == std::tie(rhs.a, rhs.b);
56   }
57 
Nameabsl::container_internal::__anon3b8bca4b0111::Int12858   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;
operator ==(Int64 lhs,Int64 rhs)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>
SameType()84 void SameType() {
85   static_assert(std::is_same<Expected, Actual>(), "");
86 }
87 
TEST(Layout,ElementType)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 
TEST(Layout,ElementTypes)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 
TEST(Layout,OffsetByIndex)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 
TEST(Layout,OffsetByType)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 
TEST(Layout,Offsets)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 
TEST(Layout,AllocSize)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 
TEST(Layout,SizeByIndex)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 
TEST(Layout,SizeByType)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 
TEST(Layout,Sizes)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 
TEST(Layout,PointerByIndex)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 
TEST(Layout,PointerByType)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 
TEST(Layout,MutablePointerByIndex)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 
TEST(Layout,MutablePointerByType)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 
TEST(Layout,Pointers)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 
TEST(Layout,MutablePointers)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 
TEST(Layout,SliceByIndexSize)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 
TEST(Layout,SliceByTypeSize)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 
TEST(Layout,MutableSliceByIndexSize)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 
TEST(Layout,MutableSliceByTypeSize)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 
TEST(Layout,SliceByIndexData)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 
TEST(Layout,SliceByTypeData)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 
TEST(Layout,MutableSliceByIndexData)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 
TEST(Layout,MutableSliceByTypeData)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:
TupleMatcher(M...matchers)1235   explicit TupleMatcher(M... matchers) : matchers_(std::move(matchers)...) {}
1236 
1237   template <typename Tuple>
MatchAndExplain(const Tuple & p,testing::MatchResultListener *) const1238   bool MatchAndExplain(const Tuple& p,
1239                        testing::MatchResultListener* /* listener */) const {
1240     static_assert(std::tuple_size<Tuple>::value == sizeof...(M), "");
1241     return MatchAndExplainImpl(
1242         p, absl::make_index_sequence<std::tuple_size<Tuple>::value>{});
1243   }
1244 
1245   // For the matcher concept. Left empty as we don't really need the diagnostics
1246   // right now.
DescribeTo(::std::ostream * os) const1247   void DescribeTo(::std::ostream* os) const {}
DescribeNegationTo(::std::ostream * os) const1248   void DescribeNegationTo(::std::ostream* os) const {}
1249 
1250  private:
1251   template <typename Tuple, size_t... Is>
MatchAndExplainImpl(const Tuple & p,absl::index_sequence<Is...>) const1252   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>
Tuple(M...matchers)1265 testing::PolymorphicMatcher<TupleMatcher<M...>> Tuple(M... matchers) {
1266   return testing::MakePolymorphicMatcher(
1267       TupleMatcher<M...>(std::move(matchers)...));
1268 }
1269 
TEST(Layout,Slices)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);
1290     EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
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);
1297     EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
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 
TEST(Layout,MutableSlices)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);
1323     EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
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);
1330     EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
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 
TEST(Layout,UnalignedTypes)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 
TEST(Layout,CustomAlignment)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 
TEST(Layout,OverAligned)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 
TEST(Layout,Alignment)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 
TEST(Layout,ConstexprPartial)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 
ExpectRegionPoisoned(const unsigned char * p,size_t n,bool poisoned)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>
ExpectPoisoned(const unsigned char (& buf)[N],std::initializer_list<Region> reg)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 
TEST(Layout,PoisonPadding)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 
TEST(Layout,DebugString)1456 TEST(Layout, DebugString) {
1457   {
1458     constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial();
1459     EXPECT_EQ("@0<signed char>(1)", x.DebugString());
1460   }
1461   {
1462     constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1);
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 =
1472         Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
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 =
1481         Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
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 
TEST(Layout,CharTypes)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 
TEST(Layout,ConstElementType)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:
CompactString(const char * s="")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 
size() const1612   size_t size() const {
1613     // Equivalent to reinterpret_cast<size_t&>(*p).
1614     return *L::Partial().Pointer<size_t>(p_.get());
1615   }
1616 
c_str() const1617   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 
TEST(CompactString,Works)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
1640 ABSL_NAMESPACE_END
1641 }  // namespace absl
1642