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