Coverage Report

Created: 2026-04-30 11:02

test/zserio/ArrayViewTest.cpp
Line
Count
Source
1
#include <algorithm>
2
3
#include "gtest/gtest.h"
4
#include "zserio/ArrayView.h"
5
#include "zserio/Types.h"
6
7
namespace zserio
8
{
9
10
namespace
11
{
12
13
struct TestObject
14
{
15
    UInt32 field;
16
17
    constexpr bool operator==(const TestObject& other) const
18
15
    {
19
15
        return field == other.field;
20
15
    }
21
22
    constexpr bool operator<(const TestObject& other) const
23
3
    {
24
3
        return field < other.field;
25
3
    }
26
};
27
28
struct VarDynInt16Owner
29
{
30
    uint8_t numBits = 10;
31
};
32
33
} // namespace
34
35
template <>
36
class View<TestObject>
37
{
38
public:
39
    explicit View(const TestObject& data) :
40
60
            m_data(data)
41
60
    {}
42
43
    UInt32 field() const
44
35
    {
45
35
        return m_data.field;
46
35
    }
47
48
    constexpr bool operator==(const View& other) const
49
8
    {
50
8
        return m_data == other.m_data;
51
8
    }
52
53
    constexpr bool operator!=(const View& other) const
54
4
    {
55
4
        return !operator==(other);
56
4
    }
57
58
    constexpr bool operator<(const View& other) const
59
3
    {
60
3
        return m_data < other.m_data;
61
3
    }
62
63
private:
64
    const TestObject& m_data;
65
};
66
67
namespace detail
68
{
69
70
template <>
71
struct ObjectTraits<TestObject>
72
{
73
    struct PackingContext
74
    {
75
        DeltaContext field;
76
    };
77
78
    static BitSize bitSizeOf(const View<TestObject>& view, BitSize bitPosition)
79
2
    {
80
2
        BitSize endBitPosition = bitPosition;
81
2
        endBitPosition += detail::bitSizeOf(view.field(), endBitPosition);
82
2
        return endBitPosition - bitPosition;
83
2
    }
84
85
    static void write(BitStreamWriter& writer, const View<TestObject>& view)
86
2
    {
87
2
        detail::write(writer, view.field());
88
2
    }
89
90
    static View<TestObject> read(BitStreamReader& reader, TestObject& data)
91
4
    {
92
4
        View<TestObject> view(data);
93
4
        detail::read(reader, data.field);
94
4
        return view;
95
4
    }
96
97
    static void initContext(PackingContext& packingContext, const View<TestObject>& view)
98
10
    {
99
10
        detail::initContext(packingContext.field, view.field());
100
10
    }
101
102
    static BitSize bitSizeOf(PackingContext& packingContext, const View<TestObject>& view, BitSize bitPosition)
103
5
    {
104
5
        BitSize endBitPosition = bitPosition;
105
5
        endBitPosition += detail::bitSizeOf(packingContext.field, view.field(), endBitPosition);
106
5
        return endBitPosition - bitPosition;
107
5
    }
108
109
    static void write(PackingContext& packingContext, BitStreamWriter& writer, const View<TestObject>& view)
110
5
    {
111
5
        detail::write(packingContext.field, writer, view.field());
112
5
    }
113
114
    static void read(PackingContext& packingContext, BitStreamReader& reader, TestObject& data)
115
11
    {
116
117
11
        detail::read(packingContext.field, reader, data.field);
118
11
    }
119
};
120
121
} // namespace detail
122
123
struct VarDynInt16ArrayTraits
124
{
125
    using OwnerType = VarDynInt16Owner;
126
127
    static View<DynInt16> at(const VarDynInt16Owner& owner, const DynInt16& element, size_t)
128
48
    {
129
48
        return View<DynInt16>(element, owner.numBits);
130
48
    }
131
132
    static void read(BitStreamReader& reader, const VarDynInt16Owner& owner, DynInt16& element, size_t)
133
11
    {
134
11
        detail::read(reader, element, owner.numBits);
135
11
    }
136
137
    static void read(detail::DeltaContext& context, BitStreamReader& reader, const VarDynInt16Owner& owner,
138
            DynInt16& element, size_t)
139
7
    {
140
7
        detail::read(context, reader, element, owner.numBits);
141
7
    }
142
};
143
144
TEST(ArrayViewTest, boolArray)
145
1
{
146
1
    Vector<Bool> rawArray1{true, false};
147
1
    Vector<Bool> rawArray2{true, true};
148
149
1
    ArrayView<const Bool> array1(rawArray1);
150
1
    ASSERT_EQ(rawArray1.at(0), array1.at(0));
151
1
    ASSERT_EQ(rawArray1.at(1), array1.at(1));
152
153
1
    ArrayView<const Bool> array2(rawArray2);
154
1
    ASSERT_FALSE(array1 == array2);
155
1
    ASSERT_TRUE(array1 != array2);
156
1
    ASSERT_LT(array1, array2);
157
158
1
    const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1);
159
1
    BitBuffer buffer(bitSize);
160
1
    BitStreamWriter writer(buffer);
161
1
    detail::write<detail::ArrayType::AUTO>(writer, array1);
162
1
    ASSERT_EQ(bitSize, writer.getBitPosition());
163
164
1
    BitStreamReader reader(buffer);
165
1
    Vector<Bool> readRawArray;
166
1
    detail::read<detail::ArrayType::AUTO>(reader, readRawArray);
167
1
    ASSERT_EQ(bitSize, reader.getBitPosition());
168
1
    ASSERT_EQ(rawArray1, readRawArray);
169
170
1
    const std::array<uint8_t, 10> buffer2{
171
1
            0xFF, 0xFF, 0xFF, 0x3F, // big array size
172
1
    };
173
1
    BitStreamReader reader2(buffer2.data(), buffer2.size());
174
1
    ASSERT_THROW(detail::read<detail::ArrayType::AUTO>(reader2, readRawArray), CppRuntimeException);
175
1
}
176
177
TEST(ArrayViewTest, boolPackedArray)
178
1
{
179
1
    Vector<Bool> rawArray{true, false, true, false, true};
180
1
    ArrayView<const Bool> array(rawArray);
181
182
1
    const BitSize packedBitSize = detail::bitSizeOfPacked<detail::ArrayType::AUTO>(array);
183
1
    BitBuffer buffer(packedBitSize);
184
1
    BitStreamWriter writer(buffer);
185
1
    detail::writePacked<detail::ArrayType::AUTO>(writer, array);
186
1
    ASSERT_EQ(packedBitSize, writer.getBitPosition());
187
188
1
    BitStreamReader reader(buffer);
189
1
    Vector<Bool> readRawArray;
190
1
    detail::readPacked<detail::ArrayType::AUTO>(reader, readRawArray, rawArray.size());
191
1
    ASSERT_EQ(packedBitSize, reader.getBitPosition());
192
1
    ASSERT_EQ(rawArray, readRawArray);
193
194
1
    const std::array<uint8_t, 10> buffer2{
195
1
            0xFF, 0xFF, 0xFF, 0x3F, // big array size
196
1
    };
197
1
    BitStreamReader reader2(buffer2.data(), buffer2.size());
198
1
    ASSERT_THROW(detail::readPacked<detail::ArrayType::AUTO>(reader2, readRawArray), CppRuntimeException);
199
1
}
200
201
TEST(ArrayViewTest, int8Array)
202
1
{
203
1
    Vector<Int8> rawArray1{0, 13};
204
1
    Vector<Int8> rawArray2{0, 42};
205
206
1
    ArrayView<const Int8> array1(rawArray1);
207
1
    ASSERT_EQ(rawArray1.at(0), array1.at(0));
208
1
    ASSERT_EQ(rawArray1.at(1), array1.at(1));
209
210
1
    ArrayView<const Int8> array2(rawArray2);
211
1
    ASSERT_FALSE(array1 == array2);
212
1
    ASSERT_TRUE(array1 != array2);
213
1
    ASSERT_LT(array1, array2);
214
215
1
    const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1);
216
1
    BitBuffer buffer(bitSize);
217
1
    BitStreamWriter writer(buffer);
218
1
    detail::write<detail::ArrayType::AUTO>(writer, array1);
219
1
    ASSERT_EQ(bitSize, writer.getBitPosition());
220
221
1
    BitStreamReader reader(buffer);
222
1
    Vector<Int8> readRawArray;
223
1
    detail::read<detail::ArrayType::AUTO>(reader, readRawArray);
224
1
    ASSERT_EQ(bitSize, reader.getBitPosition());
225
1
    ASSERT_EQ(rawArray1, readRawArray);
226
227
1
    const std::array<uint8_t, 10> buffer2{
228
1
            0xFF, 0xFF, 0xFF, 0x3F, // big array size
229
1
    };
230
1
    BitStreamReader reader2(buffer2.data(), buffer2.size());
231
1
    ASSERT_THROW(detail::read<detail::ArrayType::AUTO>(reader2, readRawArray), CppRuntimeException);
232
1
}
233
234
TEST(ArrayViewTest, int8PackedArray)
235
1
{
236
1
    Vector<Int8> rawArray = {-4, -3, -1, 0, 2, 4, 6, 8, 10, 10, 11};
237
1
    ArrayView<const Int8> array(rawArray);
238
239
1
    static_assert(detail::is_packable_v<Int8>, "shall be packable");
240
1
    static_assert(detail::is_packable_v<const Int8>, "shall be packable");
241
242
    // maxBitNumber == 2
243
    // packingDescriptor 7 + firstElement 8 + 10 * (maxBitNumber 2 + 1)
244
1
    static constexpr BitSize packedBitSize = 45;
245
1
    ASSERT_EQ(packedBitSize, detail::bitSizeOfPacked<detail::ArrayType::NORMAL>(array));
246
247
1
    BitBuffer buffer(packedBitSize);
248
1
    BitStreamWriter writer(buffer);
249
1
    detail::writePacked<detail::ArrayType::NORMAL>(writer, array);
250
1
    ASSERT_EQ(packedBitSize, writer.getBitPosition());
251
252
1
    BitStreamReader reader(buffer);
253
1
    Vector<Int8> readRawArray;
254
255
1
    ASSERT_THROW(
256
1
            detail::readPacked<detail::ArrayType::NORMAL>(reader, readRawArray, 9999), CppRuntimeException);
257
258
1
    reader.setBitPosition(0);
259
1
    detail::readPacked<detail::ArrayType::NORMAL>(reader, readRawArray, rawArray.size());
260
1
    ASSERT_EQ(rawArray, readRawArray);
261
262
1
    ASSERT_EQ(rawArray.size(), array.size());
263
1
    ASSERT_FALSE(array.empty());
264
265
1
    Vector<Int8> emptyRawArray;
266
1
    ArrayView<const Int8> emptyArray(emptyRawArray);
267
1
    ASSERT_TRUE(emptyArray.empty());
268
269
1
    ASSERT_THROW(emptyArray.front(), CppRuntimeException);
270
271
1
    ASSERT_EQ(rawArray.front(), array.front());
272
1
    ASSERT_EQ(rawArray.back(), array.back());
273
274
1
    auto it = array.begin();
275
1
    ASSERT_EQ(-4, *it);
276
1
    ASSERT_EQ(-1, it[2]);
277
1
    it += 2;
278
1
    ASSERT_EQ(-1, *it);
279
1
    ASSERT_EQ(-3, it[-1]);
280
1
    it -= 1;
281
1
    ASSERT_EQ(-3, *it);
282
1
    auto otherIt = it + 2;
283
1
    ASSERT_EQ(0, *otherIt);
284
1
    ASSERT_EQ(2, *(++otherIt));
285
1
    ASSERT_EQ(2, *(otherIt++));
286
1
    ASSERT_EQ(4, *otherIt);
287
1
    ASSERT_EQ(2, *(--otherIt));
288
1
    ASSERT_EQ(2, *(otherIt--));
289
1
    ASSERT_EQ(0, *otherIt);
290
1
    otherIt = 2 + it;
291
1
    ASSERT_EQ(0, *otherIt);
292
1
    otherIt = it - 1;
293
1
    ASSERT_EQ(-4, *otherIt);
294
1
    ASSERT_EQ(1, it - otherIt);
295
1
    ASSERT_EQ(-1, otherIt - it);
296
1
    ASSERT_EQ(array.size(), array.end() - array.begin());
297
298
1
    ASSERT_TRUE(otherIt == array.begin());
299
1
    ASSERT_FALSE(otherIt == array.end());
300
301
1
    ASSERT_TRUE(otherIt != array.end());
302
1
    ASSERT_FALSE(otherIt != array.begin());
303
304
1
    ASSERT_TRUE(otherIt < array.end());
305
1
    ASSERT_FALSE(array.end() < otherIt);
306
307
1
    ASSERT_TRUE(array.end() > array.begin());
308
1
    ASSERT_FALSE(array.begin() > array.end());
309
310
1
    ASSERT_TRUE(array.begin() <= array.end());
311
1
    ASSERT_TRUE(array.begin() <= array.begin());
312
1
    ASSERT_FALSE(array.end() <= array.begin());
313
314
1
    ASSERT_TRUE(array.end() >= array.begin());
315
1
    ASSERT_TRUE(array.end() >= array.end());
316
1
    ASSERT_FALSE(array.begin() >= array.end());
317
318
1
    size_t i = 0;
319
1
    for (auto element : array)
320
11
    {
321
11
        ASSERT_EQ(rawArray[i++], element);
322
11
    }
323
324
1
    i = array.size() - 1;
325
12
    for (auto rit = array.rbegin(); rit < array.rend(); 
++rit11
)
326
11
    {
327
11
        ASSERT_EQ(rawArray[i--], *rit);
328
11
    }
329
330
5
    
auto foundIt = std::find_if(array.begin(), array.end(), [](auto value) 1
{
331
5
        return value > 0;
332
5
    });
333
1
    ASSERT_NE(array.end(), foundIt);
334
1
    ASSERT_EQ(2, *foundIt);
335
1
}
336
337
TEST(ArrayViewTest, fixedDynInt16Array)
338
1
{
339
1
    Vector<Int<9>> rawArray1{-2, 13};
340
1
    Vector<Int<9>> rawArray2{-2, 42};
341
342
1
    ArrayView<const Int<9>> array1(rawArray1);
343
1
    ASSERT_EQ(rawArray1.at(0), array1.at(0));
344
1
    ASSERT_EQ(rawArray1.at(1), array1.at(1));
345
346
1
    ArrayView<const Int<9>> array2(rawArray2);
347
1
    ASSERT_FALSE(array1 == array2);
348
1
    ASSERT_TRUE(array1 != array2);
349
1
    ASSERT_LT(array1, array2);
350
351
1
    const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1);
352
1
    BitBuffer buffer(bitSize);
353
1
    BitStreamWriter writer(buffer);
354
1
    detail::write<detail::ArrayType::AUTO>(writer, array1);
355
1
    ASSERT_EQ(bitSize, writer.getBitPosition());
356
357
1
    BitStreamReader reader(buffer);
358
1
    Vector<Int<9>> readRawArray;
359
1
    detail::read<detail::ArrayType::AUTO>(reader, readRawArray, rawArray1.size());
360
1
    ASSERT_EQ(bitSize, reader.getBitPosition());
361
1
    ASSERT_EQ(rawArray1, readRawArray);
362
363
1
    const std::array<uint8_t, 10> buffer2{
364
1
            0xFF, 0xFF, 0xFF, 0x3F, // big array size
365
1
    };
366
1
    BitStreamReader reader2(buffer2.data(), buffer2.size());
367
1
    ASSERT_THROW(detail::read<detail::ArrayType::AUTO>(reader2, readRawArray), CppRuntimeException);
368
1
}
369
370
TEST(ArrayViewTest, variableDynInt16Array)
371
1
{
372
1
    Vector<DynInt16> rawArray1{-2, 13};
373
1
    Vector<DynInt16> rawArray2{-2, 42};
374
375
1
    VarDynInt16Owner owner;
376
377
1
    ArrayView<const DynInt16, VarDynInt16ArrayTraits> array1(rawArray1, owner);
378
1
    ASSERT_EQ(rawArray1.at(0), array1.at(0).value());
379
1
    ASSERT_EQ(rawArray1.at(1), array1.at(1).value());
380
381
1
    ArrayView<const DynInt16, VarDynInt16ArrayTraits> array2(rawArray2, owner);
382
1
    ASSERT_FALSE(array1 == array2);
383
1
    ASSERT_TRUE(array1 != array2);
384
1
    ASSERT_LT(array1, array2);
385
386
1
    const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1);
387
1
    BitBuffer buffer(bitSize);
388
1
    BitStreamWriter writer(buffer);
389
1
    detail::write<detail::ArrayType::AUTO>(writer, array1);
390
1
    ASSERT_EQ(bitSize, writer.getBitPosition());
391
392
1
    BitStreamReader reader(buffer);
393
1
    Vector<DynInt16> readRawArray;
394
1
    detail::readWithTraits<detail::ArrayType::AUTO, VarDynInt16ArrayTraits>(
395
1
            reader, readRawArray, owner, rawArray1.size());
396
1
    ASSERT_EQ(bitSize, reader.getBitPosition());
397
1
    ASSERT_EQ(rawArray1, readRawArray);
398
399
1
    const std::array<uint8_t, 10> buffer2{
400
1
            0xFF, 0xFF, 0xFF, 0x3F, // big array size
401
1
    };
402
1
    BitStreamReader reader2(buffer2.data(), buffer2.size());
403
1
    ASSERT_THROW((detail::readWithTraits<detail::ArrayType::AUTO, VarDynInt16ArrayTraits>(
404
1
                         reader2, readRawArray, owner)),
405
1
            CppRuntimeException);
406
1
}
407
408
TEST(ArrayViewTest, variableDynInt16PackedArray)
409
1
{
410
1
    Vector<DynInt16> rawArray{-2, 0, 2, 4, 6, 8, 10};
411
412
1
    VarDynInt16Owner owner;
413
1
    ArrayView<const DynInt16, VarDynInt16ArrayTraits> array(rawArray, owner);
414
415
    // maxBitNumber == 2
416
    // packingDescriptor 7 + firstElement 10 + 6 * (maxBitNumber 2 + 1)
417
1
    const BitSize packedBitSize = 35;
418
1
    ASSERT_EQ(packedBitSize, detail::bitSizeOfPacked<detail::ArrayType::NORMAL>(array));
419
420
1
    BitBuffer buffer(packedBitSize);
421
1
    BitStreamWriter writer(buffer);
422
1
    detail::writePacked<detail::ArrayType::NORMAL>(writer, array);
423
1
    ASSERT_EQ(packedBitSize, writer.getBitPosition());
424
425
1
    BitStreamReader reader(buffer);
426
1
    Vector<DynInt16> readRawArray;
427
1
    detail::readPackedWithTraits<detail::ArrayType::NORMAL, VarDynInt16ArrayTraits>(
428
1
            reader, readRawArray, owner, rawArray.size());
429
1
    ASSERT_EQ(packedBitSize, reader.getBitPosition());
430
1
    ASSERT_EQ(rawArray, readRawArray);
431
432
1
    reader.setBitPosition(0);
433
1
    ASSERT_THROW((detail::readWithTraits<detail::ArrayType::NORMAL, VarDynInt16ArrayTraits>(
434
1
                         reader, readRawArray, owner, 9999)),
435
1
            CppRuntimeException);
436
1
}
437
438
TEST(ArrayViewTest, varUInt16Array)
439
1
{
440
1
    Vector<VarUInt16> rawArray1{0, 13};
441
1
    Vector<VarUInt16> rawArray2{0, 42};
442
443
1
    ArrayView<const VarUInt16> array1(rawArray1);
444
1
    ASSERT_EQ(rawArray1.at(0), array1.at(0));
445
1
    ASSERT_EQ(rawArray1.at(1), array1.at(1));
446
447
1
    ArrayView<const VarUInt16> array2(rawArray2);
448
1
    ASSERT_FALSE(array1 == array2);
449
1
    ASSERT_TRUE(array1 != array2);
450
1
    ASSERT_LT(array1, array2);
451
452
1
    const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1);
453
1
    BitBuffer buffer(bitSize);
454
1
    BitStreamWriter writer(buffer);
455
1
    detail::write<detail::ArrayType::AUTO>(writer, array1);
456
1
    ASSERT_EQ(bitSize, writer.getBitPosition());
457
458
1
    BitStreamReader reader(buffer);
459
1
    Vector<VarUInt16> readRawArray;
460
1
    detail::read<detail::ArrayType::AUTO>(reader, readRawArray, rawArray1.size());
461
1
    ASSERT_EQ(bitSize, reader.getBitPosition());
462
1
    ASSERT_EQ(rawArray1, readRawArray);
463
464
1
    const std::array<uint8_t, 10> buffer2{
465
1
            0xFF, 0xFF, 0xFF, 0x3F, // big array size
466
1
    };
467
1
    BitStreamReader reader2(buffer2.data(), buffer2.size());
468
1
    ASSERT_THROW((detail::read<detail::ArrayType::AUTO>(reader2, readRawArray)), CppRuntimeException);
469
1
}
470
471
TEST(ArrayViewTest, varUInt16PackedArray)
472
1
{
473
1
    Vector<VarUInt16> rawArray{0, 2, 4, 6, 8, 10, 12};
474
1
    ArrayView<const VarUInt16> array(rawArray);
475
476
1
    const BitSize packedBitSize = detail::bitSizeOfPacked<detail::ArrayType::AUTO>(array);
477
1
    BitBuffer buffer(packedBitSize);
478
1
    BitStreamWriter writer(buffer);
479
1
    detail::writePacked<detail::ArrayType::AUTO>(writer, array);
480
1
    ASSERT_EQ(packedBitSize, writer.getBitPosition());
481
482
1
    BitStreamReader reader(buffer);
483
1
    Vector<VarUInt16> readRawArray;
484
1
    detail::readPacked<detail::ArrayType::AUTO>(reader, readRawArray, rawArray.size());
485
1
    ASSERT_EQ(packedBitSize, reader.getBitPosition());
486
1
    ASSERT_EQ(rawArray, readRawArray);
487
488
1
    const std::array<uint8_t, 10> buffer2{
489
1
            0xFF, 0xFF, 0xFF, 0x3F, // big array size
490
1
    };
491
1
    BitStreamReader reader2(buffer2.data(), buffer2.size());
492
1
    ASSERT_THROW((detail::readPacked<detail::ArrayType::AUTO>(reader2, readRawArray)), CppRuntimeException);
493
1
}
494
495
TEST(ArrayViewTest, float16Array)
496
1
{
497
1
    Vector<Float16> rawArray1{-9.0F, 0.0F, 10.0F};
498
1
    Vector<Float16> rawArray2{-9.0F, 0.0F, 10.1F};
499
500
1
    ArrayView<const Float16> array1(rawArray1);
501
1
    ArrayView<const Float16> array2(rawArray2);
502
503
1
    ASSERT_EQ(16, ArrayTraits<Float16>::bitSizeOf());
504
505
1
    ASSERT_LT(array1, array2);
506
1
    ASSERT_GT(array2, array1);
507
508
1
    const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1);
509
1
    BitBuffer buffer(bitSize);
510
1
    BitStreamWriter writer(buffer);
511
1
    detail::write<detail::ArrayType::AUTO>(writer, array1);
512
1
    ASSERT_EQ(bitSize, writer.getBitPosition());
513
514
1
    BitStreamReader reader(buffer);
515
1
    Vector<Float16> readRawArray;
516
1
    detail::read<detail::ArrayType::AUTO>(reader, readRawArray, rawArray1.size());
517
1
    ASSERT_EQ(bitSize, reader.getBitPosition());
518
1
    ASSERT_EQ(rawArray1, readRawArray);
519
520
1
    const std::array<uint8_t, 10> buffer2{
521
1
            0xFF, 0xFF, 0xFF, 0x3F, // big array size
522
1
    };
523
1
    BitStreamReader reader2(buffer2.data(), buffer2.size());
524
1
    ASSERT_THROW((detail::read<detail::ArrayType::AUTO>(reader2, readRawArray)), CppRuntimeException);
525
1
}
526
527
TEST(ArrayViewTest, bytesArray)
528
1
{
529
1
    Vector<Bytes> rawArray1{{{{1, 255}}, {{127, 128}}}};
530
1
    Vector<Bytes> rawArray2{{{{1, 255}}, {{127, 129}}}};
531
532
1
    ArrayView<const Bytes> array1(rawArray1);
533
1
    ArrayView<const Bytes> array2(rawArray2);
534
535
1
    ASSERT_TRUE(std::equal(
536
1
            rawArray1.begin(), rawArray1.end(), array1.zserioData().begin(), array1.zserioData().end()));
537
538
1
    constexpr bool isSpan = std::is_same_v<Span<const uint8_t>, decltype(array1.at(0))>;
539
1
    ASSERT_TRUE(isSpan);
540
541
1
    ASSERT_TRUE(std::equal(
542
1
            rawArray1.at(0).begin(), rawArray1.at(0).end(), array1.at(0).begin(), array1.at(0).end()));
543
1
    ASSERT_TRUE(std::equal(
544
1
            rawArray1.at(1).begin(), rawArray1.at(1).end(), array1.at(1).begin(), array1.at(1).end()));
545
546
1
    ASSERT_NE(array1, array2);
547
1
    ASSERT_LT(array1, array2);
548
549
1
    const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1);
550
1
    BitBuffer buffer(bitSize);
551
1
    BitStreamWriter writer(buffer);
552
1
    detail::write<detail::ArrayType::AUTO>(writer, array1);
553
1
    ASSERT_EQ(bitSize, writer.getBitPosition());
554
555
1
    BitStreamReader reader(buffer);
556
1
    Vector<Bytes> readRawArray;
557
1
    detail::read<detail::ArrayType::AUTO>(reader, readRawArray, rawArray1.size());
558
1
    ASSERT_EQ(bitSize, reader.getBitPosition());
559
1
    ASSERT_EQ(rawArray1, readRawArray);
560
561
1
    const std::array<uint8_t, 10> buffer2{
562
1
            0xFF, 0xFF, 0xFF, 0x3F, // big array size
563
1
    };
564
1
    BitStreamReader reader2(buffer2.data(), buffer2.size());
565
1
    ASSERT_THROW((detail::read<detail::ArrayType::AUTO>(reader2, readRawArray)), CppRuntimeException);
566
1
}
567
568
TEST(ArrayViewTest, stringArray)
569
1
{
570
1
    Vector<std::string> rawArray1 = {"String0", "String1", "String2"};
571
1
    Vector<std::string> rawArray2 = {"String0", "String1", "String3"};
572
573
1
    ArrayView<const std::string> array1(rawArray1);
574
1
    ArrayView<const std::string> array2(rawArray2);
575
576
1
    constexpr bool isStringView = std::is_same_v<std::string_view, decltype(array1.at(0))>;
577
1
    ASSERT_TRUE(isStringView);
578
579
1
    ASSERT_EQ(rawArray1.at(0), array1.at(0));
580
1
    ASSERT_EQ(rawArray1.at(1), array1.at(1));
581
1
    ASSERT_EQ(rawArray1.at(2), array1.at(2));
582
583
1
    ASSERT_NE(array1, array2);
584
1
    ASSERT_LT(array1, array2);
585
586
1
    const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1);
587
1
    BitBuffer buffer(bitSize);
588
1
    BitStreamWriter writer(buffer);
589
1
    detail::write<detail::ArrayType::AUTO>(writer, array1);
590
1
    ASSERT_EQ(bitSize, writer.getBitPosition());
591
592
1
    BitStreamReader reader(buffer);
593
1
    Vector<std::string> readRawArray;
594
1
    detail::read<detail::ArrayType::AUTO>(reader, readRawArray, rawArray1.size());
595
1
    ASSERT_EQ(bitSize, reader.getBitPosition());
596
1
    ASSERT_EQ(rawArray1, readRawArray);
597
598
1
    const std::array<uint8_t, 10> buffer2{
599
1
            0xFF, 0xFF, 0xFF, 0x3F, // big array size
600
1
    };
601
1
    BitStreamReader reader2(buffer2.data(), buffer2.size());
602
1
    ASSERT_THROW((detail::read<detail::ArrayType::AUTO>(reader2, readRawArray)), CppRuntimeException);
603
1
}
604
605
TEST(ArrayViewTest, testObjectArray)
606
1
{
607
1
    Vector<TestObject> rawArray1{TestObject{0}, TestObject{13}};
608
1
    Vector<TestObject> rawArray2{TestObject{0}, TestObject{42}};
609
610
1
    ArrayView<const TestObject> array1(rawArray1);
611
1
    ASSERT_EQ(rawArray1.at(0).field, array1.at(0).field());
612
1
    ASSERT_EQ(rawArray1.at(1).field, array1.at(1).field());
613
614
1
    ArrayView<const TestObject> array2(rawArray2);
615
616
1
    ASSERT_FALSE(array1 == array2);
617
1
    ASSERT_TRUE(array1 != array2);
618
1
    ASSERT_LT(array1, array2);
619
620
1
    const std::array<uint8_t, 10> buffer2{
621
1
            0xFF, 0xFF, 0xFF, 0x3F, // big array size
622
1
    };
623
1
    Vector<TestObject> readRawArray2;
624
1
    BitStreamReader reader2(buffer2.data(), buffer2.size());
625
1
    ASSERT_THROW((detail::read<detail::ArrayType::AUTO>(reader2, readRawArray2)), CppRuntimeException);
626
627
1
    const BitSize bitSize = detail::bitSizeOf<detail::ArrayType::AUTO>(array1);
628
1
    BitBuffer buffer(bitSize);
629
1
    BitStreamWriter writer(buffer);
630
1
    detail::write<detail::ArrayType::AUTO>(writer, array1);
631
1
    ASSERT_EQ(bitSize, writer.getBitPosition());
632
633
1
    BitStreamReader reader(buffer);
634
1
    Vector<TestObject> readRawArray;
635
1
    detail::read<detail::ArrayType::AUTO>(reader, readRawArray);
636
1
    ASSERT_EQ(bitSize, reader.getBitPosition());
637
1
    ASSERT_EQ(rawArray1, readRawArray);
638
639
1
    ASSERT_FALSE(array1.empty());
640
1
    ASSERT_EQ(0, array1.front().field());
641
1
    ASSERT_EQ(13, array1.back().field());
642
643
1
    size_t i = 0;
644
1
    for (auto object : array1)
645
2
    {
646
2
        ASSERT_EQ(i++ == 0 ? 0 : 13, object.field());
647
2
    }
648
649
1
    TestObject object{13};
650
1
    zserio::View view(object);
651
1
    ASSERT_EQ(view, *(array1.begin() + 1));
652
1
    ASSERT_EQ(0, array1.begin()->field());
653
1
    ASSERT_EQ(view, array1.begin()[1]);
654
1
    ASSERT_EQ(array1.begin(), array1.end() - 2);
655
1
    ASSERT_EQ(*array1.begin(), *(array1.end() - 2));
656
1
    ASSERT_EQ(array1.size(), array1.end() - array1.begin());
657
658
2
    
auto foundIt = std::find_if(array1.begin(), array1.end(), [](const zserio::View<TestObject>& element) 1
{
659
2
        return element.field() != 0;
660
2
    });
661
1
    ASSERT_NE(array1.end(), foundIt);
662
1
    ASSERT_EQ(array1.at(1), *foundIt);
663
664
2
    
auto notFoundIt = std::find_if(array1.begin(), array1.end(), [](const zserio::View<TestObject>& element) 1
{
665
2
        return element.field() > 13;
666
2
    });
667
1
    ASSERT_EQ(array1.end(), notFoundIt);
668
1
}
669
670
TEST(ArrayViewTest, testObjectPackedArray)
671
1
{
672
1
    Vector<TestObject> rawArray{TestObject{0}, TestObject{2}, TestObject{4}, TestObject{6}, TestObject{8}};
673
1
    ArrayView<const TestObject> array(rawArray);
674
675
1
    static_assert(detail::is_packable_v<TestObject>, "shall be packable");
676
1
    static_assert(detail::is_packable_v<const TestObject>, "shall be packable");
677
678
    // maxBitNumber == 2
679
    // packingDescriptor 7 + firstElement 32 + 4 * (maxBitNumber 2 + 1)
680
1
    const BitSize packedBitSize = 51;
681
1
    ASSERT_EQ(packedBitSize, detail::bitSizeOfPacked<detail::ArrayType::NORMAL>(array));
682
683
1
    BitBuffer buffer(packedBitSize);
684
1
    BitStreamWriter writer(buffer);
685
1
    detail::writePacked<detail::ArrayType::NORMAL>(writer, array);
686
1
    ASSERT_EQ(packedBitSize, writer.getBitPosition());
687
688
1
    BitStreamReader reader(buffer);
689
1
    Vector<TestObject> readRawArray;
690
1
    detail::readPacked<detail::ArrayType::NORMAL>(reader, readRawArray, rawArray.size());
691
1
    ASSERT_EQ(packedBitSize, reader.getBitPosition());
692
1
    ASSERT_EQ(rawArray, readRawArray);
693
694
1
    reader.setBitPosition(0);
695
1
    ASSERT_THROW(
696
1
            (detail::readPacked<detail::ArrayType::NORMAL>(reader, readRawArray, 9999)), CppRuntimeException);
697
1
}
698
699
} // namespace zserio