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