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