• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

realm / realm-core / 2290

02 May 2024 08:09PM UTC coverage: 90.754% (+0.007%) from 90.747%
2290

push

Evergreen

web-flow
Fix a deadlock when accessing current user from inside an App listener (#7671)

App::switch_user() emitted changes without first releasing the lock on
m_user_mutex, leading to a deadlock if anyone inside the listener tried to
acquire the mutex. The rest of the places where we emitted changes were
correct.

The newly added wrapper catches this error when building with clang.

101922 of 180246 branches covered (56.55%)

14 of 17 new or added lines in 2 files covered. (82.35%)

45 existing lines in 15 files now uncovered.

212546 of 234199 relevant lines covered (90.75%)

5635345.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.91
/src/realm/array_mixed.cpp
1
/*************************************************************************
2
 *
3
 * Copyright 2018 Realm Inc.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 **************************************************************************/
18

19
#include <realm/array_mixed.hpp>
20
#include <realm/array_basic.hpp>
21

22
using namespace realm;
23

24
ArrayMixed::ArrayMixed(Allocator& a)
25
    : Array(a)
345,990✔
26
    , m_composite(a)
345,990✔
27
    , m_ints(a)
345,990✔
28
    , m_int_pairs(a)
345,990✔
29
    , m_strings(a)
345,990✔
30
    , m_refs(a)
345,990✔
31
{
692,655✔
32
    m_composite.set_parent(this, payload_idx_type);
692,655✔
33
}
692,655✔
34

35
void ArrayMixed::create()
36
{
47,076✔
37
    Array::create(type_HasRefs, false, payload_idx_size);
47,076✔
38
    m_composite.create(type_Normal);
47,076✔
39
    m_composite.update_parent();
47,076✔
40
}
47,076✔
41

42
void ArrayMixed::init_from_mem(MemRef mem) noexcept
43
{
457,947✔
44
    Array::init_from_mem(mem);
457,947✔
45
    m_composite.init_from_parent();
457,947✔
46
    m_ints.detach();
457,947✔
47
    m_int_pairs.detach();
457,947✔
48
    m_strings.detach();
457,947✔
49
    m_refs.detach();
457,947✔
50
}
457,947✔
51

52
void ArrayMixed::add(Mixed value)
53
{
168✔
54
    if (value.is_null()) {
168✔
55
        m_composite.add(0);
54✔
56
        return;
54✔
57
    }
54✔
58
    m_composite.add(store(value));
114✔
59
}
114✔
60

61

62
void ArrayMixed::set(size_t ndx, Mixed value)
63
{
33,804✔
64
    auto old_type = get_type(ndx);
33,804✔
65
    // If we replace a collections ref value with one of the
66
    // same type, then it is just an update of of the
67
    // ref stored in the parent. If the new type is a different
68
    // type then it means that we are overwriting a collection
69
    // with some other value and hence the collection must be
70
    // destroyed as well as the possible key.
71
    bool destroy_collection = !value.is_type(old_type);
33,804✔
72

73
    if (value.is_null()) {
33,804✔
74
        set_null(ndx);
1,866✔
75
    }
1,866✔
76
    else {
31,938✔
77
        erase_linked_payload(ndx, destroy_collection);
31,938✔
78
        m_composite.set(ndx, store(value));
31,938✔
79
    }
31,938✔
80

81
    if (destroy_collection && Array::size() > payload_idx_key) {
33,804✔
82
        if (auto ref = Array::get_as_ref(payload_idx_key)) {
18,078✔
83
            Array keys(Array::get_alloc());
1,242✔
84
            keys.set_parent(const_cast<ArrayMixed*>(this), payload_idx_key);
1,242✔
85
            keys.init_from_ref(ref);
1,242✔
86
            if (ndx < keys.size())
1,242✔
87
                keys.set(ndx, 0);
1,194✔
88
        }
1,242✔
89
    }
18,078✔
90
}
33,804✔
91

92
void ArrayMixed::insert(size_t ndx, Mixed value)
93
{
149,268✔
94
    if (value.is_null()) {
149,268✔
95
        m_composite.insert(ndx, 0);
25,068✔
96
    }
25,068✔
97
    else {
124,200✔
98
        m_composite.insert(ndx, store(value));
124,200✔
99
    }
124,200✔
100
    if (Array::size() > payload_idx_key) {
149,268✔
101
        if (auto ref = Array::get_as_ref(payload_idx_key)) {
149,013✔
102
            Array keys(Array::get_alloc());
1,596✔
103
            keys.set_parent(const_cast<ArrayMixed*>(this), payload_idx_key);
1,596✔
104
            keys.init_from_ref(ref);
1,596✔
105
            keys.insert(ndx, 0);
1,596✔
106
        }
1,596✔
107
    }
149,013✔
108
}
149,268✔
109

110
void ArrayMixed::set_null(size_t ndx)
111
{
1,866✔
112
    auto val = m_composite.get(ndx);
1,866✔
113
    if (val) {
1,866✔
114
        erase_linked_payload(ndx, true);
1,842✔
115
        m_composite.set(ndx, 0);
1,842✔
116
    }
1,842✔
117
}
1,866✔
118

119
Mixed ArrayMixed::get(size_t ndx) const
120
{
1,787,436✔
121
    int64_t val = m_composite.get(ndx);
1,787,436✔
122

123
    if (val) {
1,787,436✔
124
        int64_t int_val = val >> s_data_shift;
1,742,223✔
125
        size_t payload_ndx = size_t(int_val);
1,742,223✔
126
        DataType type = DataType((val & s_data_type_mask) - 1);
1,742,223✔
127
        switch (type) {
1,742,223✔
128
            case type_Int: {
308,655✔
129
                if (val & s_payload_idx_mask) {
308,655✔
130
                    ensure_int_array();
4,938✔
131
                    return Mixed(m_ints.get(payload_ndx));
4,938✔
132
                }
4,938✔
133
                return Mixed(int_val);
303,717✔
134
            }
308,655✔
135
            case type_Bool:
20,070✔
136
                return Mixed(int_val != 0);
20,070✔
137
            case type_Float:
27,378✔
138
                ensure_int_array();
27,378✔
139
                return Mixed(type_punning<float>(m_ints.get(payload_ndx)));
27,378✔
140
            case type_Double:
59,670✔
141
                ensure_int_array();
59,670✔
142
                return Mixed(type_punning<double>(m_ints.get(payload_ndx)));
59,670✔
143
            case type_String: {
125,550✔
144
                ensure_string_array();
125,550✔
145
                REALM_ASSERT(size_t(int_val) < m_strings.size());
125,550✔
146
                return Mixed(m_strings.get(payload_ndx));
125,550✔
147
            }
308,655✔
148
            case type_Binary: {
20,031✔
149
                ensure_string_array();
20,031✔
150
                REALM_ASSERT(size_t(int_val) < m_strings.size());
20,031✔
151
                auto s = m_strings.get(payload_ndx);
20,031✔
152
                return Mixed(BinaryData(s.data(), s.size()));
20,031✔
153
            }
308,655✔
154
            case type_Timestamp: {
18,207✔
155
                ensure_int_pair_array();
18,207✔
156
                payload_ndx <<= 1;
18,207✔
157
                REALM_ASSERT(payload_ndx + 1 < m_int_pairs.size());
18,207✔
158
                return Mixed(Timestamp(m_int_pairs.get(payload_ndx), int32_t(m_int_pairs.get(payload_ndx + 1))));
18,207✔
159
            }
308,655✔
160
            case type_ObjectId: {
26,826✔
161
                ensure_string_array();
26,826✔
162
                REALM_ASSERT(size_t(int_val) < m_strings.size());
26,826✔
163
                auto s = m_strings.get(payload_ndx);
26,826✔
164
                ObjectId id;
26,826✔
165
                memcpy(&id, s.data(), sizeof(ObjectId));
26,826✔
166
                return Mixed(id);
26,826✔
167
            }
308,655✔
168
            case type_Decimal: {
51,621✔
169
                ensure_int_pair_array();
51,621✔
170
                Decimal128::Bid128 raw;
51,621✔
171
                payload_ndx <<= 1;
51,621✔
172
                REALM_ASSERT(payload_ndx + 1 < m_int_pairs.size());
51,621✔
173
                raw.w[0] = m_int_pairs.get(payload_ndx);
51,621✔
174
                raw.w[1] = m_int_pairs.get(payload_ndx + 1);
51,621✔
175
                return Mixed(Decimal128(raw));
51,621✔
176
            }
308,655✔
177
            case type_Link:
✔
178
                ensure_int_array();
×
179
                return Mixed(ObjKey(m_ints.get(payload_ndx)));
×
180
            case type_TypedLink: {
970,266✔
181
                ensure_int_pair_array();
970,266✔
182
                payload_ndx <<= 1;
970,266✔
183
                REALM_ASSERT(payload_ndx + 1 < m_int_pairs.size());
970,266✔
184
                ObjLink ret{TableKey(uint32_t(m_int_pairs.get(payload_ndx))),
970,266✔
185
                            ObjKey(m_int_pairs.get(payload_ndx + 1))};
970,266✔
186
                return Mixed(ret);
970,266✔
187
            }
308,655✔
188
            case type_UUID: {
29,025✔
189
                ensure_string_array();
29,025✔
190
                REALM_ASSERT(size_t(int_val) < m_strings.size());
29,025✔
191
                auto s = m_strings.get(payload_ndx);
29,025✔
192
                UUID::UUIDBytes bytes{};
29,025✔
193
                std::copy_n(s.data(), bytes.size(), bytes.begin());
29,025✔
194
                return Mixed(UUID(bytes));
29,025✔
195
            }
308,655✔
196
            default:
84,930✔
197
                if (size_t((val & s_payload_idx_mask) >> s_payload_idx_shift) == payload_idx_ref) {
84,930✔
198
                    ensure_ref_array();
84,930✔
199
                    return Mixed(m_refs.get(payload_ndx), CollectionType(int(type)));
84,930✔
200
                }
84,930✔
201
                break;
×
202
        }
1,742,223✔
203
    }
1,742,223✔
204

205
    return {};
45,213✔
206
}
1,787,436✔
207

208
void ArrayMixed::clear()
209
{
588✔
210
    m_composite.clear();
588✔
211
    m_ints.destroy();
588✔
212
    m_int_pairs.destroy();
588✔
213
    m_strings.destroy();
588✔
214
    m_refs.destroy_deep();
588✔
215
    Array::set(payload_idx_int, 0);
588✔
216
    Array::set(payload_idx_pair, 0);
588✔
217
    Array::set(payload_idx_str, 0);
588✔
218
    Array::set(payload_idx_ref, 0);
588✔
219
    if (Array::size() > payload_idx_key) {
588✔
220
        if (auto ref = Array::get_as_ref(payload_idx_key)) {
588✔
221
            Array::destroy(ref, m_composite.get_alloc());
6✔
222
            Array::set(payload_idx_key, 0);
6✔
223
        }
6✔
224
    }
588✔
225
}
588✔
226

227
void ArrayMixed::erase(size_t ndx)
228
{
20,772✔
229
    erase_linked_payload(ndx, true);
20,772✔
230
    m_composite.erase(ndx);
20,772✔
231
    if (Array::size() > payload_idx_key) {
20,772✔
232
        if (auto ref = Array::get_as_ref(payload_idx_key)) {
20,760✔
233
            Array keys(Array::get_alloc());
246✔
234
            keys.set_parent(const_cast<ArrayMixed*>(this), payload_idx_key);
246✔
235
            keys.init_from_ref(ref);
246✔
236
            keys.erase(ndx);
246✔
237
        }
246✔
238
    }
20,760✔
239
}
20,772✔
240

241
void ArrayMixed::move(ArrayMixed& dst, size_t ndx)
242
{
6✔
243
    auto sz = size();
6✔
244
    size_t i = ndx;
6✔
245
    while (i < sz) {
60✔
246
        auto val = get(i++);
54✔
247
        dst.add(val);
54✔
248
    }
54✔
249
    if (Array::size() > payload_idx_key) {
6✔
250
        if (auto ref = Array::get_as_ref(payload_idx_key)) {
6✔
251
            dst.ensure_keys();
×
252
            Array keys(Array::get_alloc());
×
253
            keys.set_parent(const_cast<ArrayMixed*>(this), payload_idx_key);
×
254
            keys.init_from_ref(ref);
×
255
            for (size_t j = 0, i = ndx; i < sz; i++, j++) {
×
256
                dst.set_key(j, keys.get(i));
×
257
            }
×
258
            keys.truncate(ndx);
×
259
        }
×
260
    }
6✔
261
    while (i > ndx) {
60✔
262
        erase_linked_payload(--i, false);
54✔
263
    }
54✔
264
    m_composite.truncate(ndx);
6✔
265
}
6✔
266

267
size_t ArrayMixed::find_first(Mixed value, size_t begin, size_t end) const noexcept
268
{
63,990✔
269
    if (value.is_null()) {
63,990✔
270
        return m_composite.find_first(0, begin, end);
468✔
271
    }
468✔
272
    DataType type = value.get_type();
63,522✔
273
    if (end == realm::npos)
63,522✔
274
        end = size();
6✔
275
    for (size_t i = begin; i < end; i++) {
626,280✔
276
        if (Mixed::data_types_are_comparable(this->get_type(i), type) && get(i) == value) {
623,526✔
277
            return i;
60,768✔
278
        }
60,768✔
279
    }
623,526✔
280
    return realm::npos;
2,754✔
281
}
63,522✔
282

283
bool ArrayMixed::ensure_keys()
284
{
4,038✔
285
    if (Array::size() < payload_idx_key + 1 || Array::get(payload_idx_key) == 0) {
4,038✔
286
        Array keys(Array::get_alloc());
2,670✔
287
        keys.set_parent(const_cast<ArrayMixed*>(this), payload_idx_key);
2,670✔
288
        keys.create(type_Normal, false, size(), 0);
2,670✔
289
        keys.update_parent();
2,670✔
290

291
        return false;
2,670✔
292
    }
2,670✔
293
    return true;
1,368✔
294
}
4,038✔
295

296
size_t ArrayMixed::find_key(int64_t key) const noexcept
297
{
57,756✔
298
    if (ref_type ref = get_as_ref(payload_idx_key)) {
57,756✔
299
        Array keys(Array::get_alloc());
57,732✔
300
        keys.init_from_ref(ref);
57,732✔
301
        return keys.find_first(key);
57,732✔
302
    }
57,732✔
303
    return realm::not_found;
24✔
304
}
57,756✔
305

306
void ArrayMixed::set_key(size_t ndx, int64_t key)
307
{
6,636✔
308
    Array keys(Array::get_alloc());
6,636✔
309
    ensure_array_accessor(keys, payload_idx_key);
6,636✔
310
    while (keys.size() <= ndx) {
8,850✔
311
        keys.add(0);
2,214✔
312
    }
2,214✔
313
    keys.set(ndx, key);
6,636✔
314
}
6,636✔
315

316
int64_t ArrayMixed::get_key(size_t ndx) const
317
{
36,282✔
318
    Array keys(Array::get_alloc());
36,282✔
319
    if (ref_type ref = get_as_ref(payload_idx_key)) {
36,282✔
320
        keys.init_from_ref(ref);
36,282✔
321
        return (ndx < keys.size()) ? keys.get(ndx) : 0;
36,282✔
322
    }
36,282✔
UNCOV
323
    return 0;
×
324
}
36,282✔
325

326
void ArrayMixed::verify() const
327
{
14,901✔
328
    // TODO: Implement
329
}
14,901✔
330

331
void ArrayMixed::ensure_array_accessor(Array& arr, size_t ndx_in_parent) const
332
{
1,326,840✔
333
    if (!arr.is_attached()) {
1,326,840✔
334
        ref_type ref = get_as_ref(ndx_in_parent);
242,190✔
335
        arr.set_parent(const_cast<ArrayMixed*>(this), ndx_in_parent);
242,190✔
336
        if (ref) {
242,190✔
337
            arr.init_from_ref(ref);
218,847✔
338
        }
218,847✔
339
        else {
23,343✔
340
            arr.create(ndx_in_parent == payload_idx_ref ? type_HasRefs : type_Normal);
23,343✔
341
            arr.update_parent();
23,343✔
342
        }
23,343✔
343
    }
242,190✔
344
}
1,326,840✔
345

346
void ArrayMixed::ensure_int_array() const
347
{
113,169✔
348
    ensure_array_accessor(m_ints, payload_idx_int);
113,169✔
349
}
113,169✔
350

351
void ArrayMixed::ensure_int_pair_array() const
352
{
1,096,146✔
353
    ensure_array_accessor(m_int_pairs, payload_idx_pair);
1,096,146✔
354
}
1,096,146✔
355

356
void ArrayMixed::ensure_string_array() const
357
{
250,902✔
358
    if (!m_strings.is_attached()) {
250,902✔
359
        ref_type ref = get_as_ref(payload_idx_str);
79,248✔
360
        m_strings.set_parent(const_cast<ArrayMixed*>(this), payload_idx_str);
79,248✔
361
        if (ref) {
79,248✔
362
            m_strings.init_from_ref(ref);
60,846✔
363
        }
60,846✔
364
        else {
18,402✔
365
            m_strings.create();
18,402✔
366
            m_strings.update_parent();
18,402✔
367
        }
18,402✔
368
    }
79,248✔
369
}
250,902✔
370

371
void ArrayMixed::ensure_ref_array() const
372
{
110,889✔
373
    while (Array::size() < payload_idx_ref + 1) {
110,889✔
374
        const_cast<ArrayMixed*>(this)->Array::add(0);
×
375
    }
×
376
    ensure_array_accessor(m_refs, payload_idx_ref);
110,889✔
377
}
110,889✔
378

379
void ArrayMixed::replace_index(size_t old_ndx, size_t new_ndx, size_t payload_arr_index)
380
{
12,813✔
381
    if (old_ndx != new_ndx) {
12,813✔
382
        size_t sz = m_composite.size();
12,813✔
383
        for (size_t i = 0; i != sz; i++) {
728,175✔
384
            int64_t val = m_composite.get(i);
728,175✔
385
            if (size_t((val & s_payload_idx_mask) >> s_payload_idx_shift) == payload_arr_index &&
728,175✔
386
                (val >> s_data_shift) == int64_t(old_ndx)) {
728,175✔
387
                m_composite.set(i, int64_t(new_ndx << s_data_shift) | (val & 0xff));
12,813✔
388
                return;
12,813✔
389
            }
12,813✔
390
        }
728,175✔
391
    }
12,813✔
392
}
12,813✔
393

394
void ArrayMixed::erase_linked_payload(size_t ndx, bool free_linked_arrays)
395
{
54,606✔
396
    auto val = m_composite.get(ndx);
54,606✔
397
    auto payload_arr_index = size_t((val & s_payload_idx_mask) >> s_payload_idx_shift);
54,606✔
398

399
    if (payload_arr_index) {
54,606✔
400
        // A value is stored in one of the payload arrays
401
        size_t last_ndx = 0;
32,955✔
402
        size_t erase_ndx = size_t(val >> s_data_shift);
32,955✔
403
        // Clean up current value by moving last over
404
        switch (payload_arr_index) {
32,955✔
405
            case payload_idx_int: {
4,671✔
406
                ensure_int_array();
4,671✔
407
                last_ndx = m_ints.size() - 1;
4,671✔
408
                if (erase_ndx != last_ndx) {
4,671✔
409
                    m_ints.set(erase_ndx, m_ints.get(last_ndx));
3,435✔
410
                    replace_index(last_ndx, erase_ndx, payload_arr_index);
3,435✔
411
                }
3,435✔
412
                m_ints.erase(last_ndx);
4,671✔
413
                break;
4,671✔
414
            }
×
415
            case payload_idx_str: {
5,982✔
416
                ensure_string_array();
5,982✔
417
                last_ndx = m_strings.size() - 1;
5,982✔
418
                if (erase_ndx != last_ndx) {
5,982✔
419
                    StringData tmp = m_strings.get(last_ndx);
3,336✔
420
                    std::string tmp_val(tmp.data(), tmp.size());
3,336✔
421
                    m_strings.set(erase_ndx, StringData(tmp_val));
3,336✔
422
                    replace_index(last_ndx, erase_ndx, payload_arr_index);
3,336✔
423
                }
3,336✔
424
                m_strings.erase(last_ndx);
5,982✔
425
                break;
5,982✔
426
            }
×
427
            case payload_idx_pair: {
12,066✔
428
                ensure_int_pair_array();
12,066✔
429
                last_ndx = m_int_pairs.size() - 2;
12,066✔
430
                erase_ndx <<= 1;
12,066✔
431
                if (erase_ndx != last_ndx) {
12,066✔
432
                    m_int_pairs.set(erase_ndx, m_int_pairs.get(last_ndx));
5,382✔
433
                    m_int_pairs.set(erase_ndx + 1, m_int_pairs.get(last_ndx + 1));
5,382✔
434
                    replace_index(last_ndx >> 1, erase_ndx >> 1, payload_arr_index);
5,382✔
435
                }
5,382✔
436
                m_int_pairs.truncate(last_ndx);
12,066✔
437
                break;
12,066✔
438
            }
×
439
            case payload_idx_ref: {
10,236✔
440
                ensure_ref_array();
10,236✔
441
                last_ndx = m_refs.size() - 1;
10,236✔
442
                auto old_ref = m_refs.get(erase_ndx);
10,236✔
443
                if (erase_ndx != last_ndx) {
10,236✔
444
                    m_refs.set(erase_ndx, m_refs.get(last_ndx));
660✔
445
                    replace_index(last_ndx, erase_ndx, payload_arr_index);
660✔
446
                }
660✔
447
                m_refs.erase(last_ndx);
10,236✔
448
                if (old_ref && free_linked_arrays)
10,236✔
449
                    Array::destroy_deep(old_ref, m_composite.get_alloc());
738✔
450
                break;
10,236✔
451
            }
×
452
            default:
✔
453
                break;
×
454
        }
32,955✔
455
    }
32,955✔
456
}
54,606✔
457

458
int64_t ArrayMixed::store(const Mixed& value)
459
{
156,252✔
460
    DataType type = value.get_type();
156,252✔
461
    int64_t val;
156,252✔
462
    switch (type) {
156,252✔
463
        case type_Int: {
37,692✔
464
            int64_t int_val = value.get_int();
37,692✔
465
            if (std::numeric_limits<int32_t>::min() <= int_val && int_val <= std::numeric_limits<int32_t>::max()) {
37,692✔
466
                val = (static_cast<uint64_t>(int_val) << s_data_shift);
33,714✔
467
            }
33,714✔
468
            else {
3,978✔
469
                ensure_int_array();
3,978✔
470
                size_t ndx = m_ints.size();
3,978✔
471
                m_ints.add(int_val);
3,978✔
472
                val = int64_t(ndx << s_data_shift) | (payload_idx_int << s_payload_idx_shift);
3,978✔
473
            }
3,978✔
474
            break;
37,692✔
475
        }
×
476
        case type_Bool:
2,832✔
477
            val = (value.get_bool() << s_data_shift);
2,832✔
478
            break;
2,832✔
479
        case type_Float: {
6,006✔
480
            ensure_int_array();
6,006✔
481
            size_t ndx = m_ints.size();
6,006✔
482
            m_ints.add(type_punning<int64_t>(value.get_float()));
6,006✔
483
            val = int64_t(ndx << s_data_shift) | (payload_idx_int << s_payload_idx_shift);
6,006✔
484
            break;
6,006✔
485
        }
×
486
        case type_Double: {
6,528✔
487
            ensure_int_array();
6,528✔
488
            size_t ndx = m_ints.size();
6,528✔
489
            m_ints.add(type_punning<int64_t>(value.get_double()));
6,528✔
490
            val = int64_t(ndx << s_data_shift) | (payload_idx_int << s_payload_idx_shift);
6,528✔
491
            break;
6,528✔
492
        }
×
493
        case type_String: {
29,700✔
494
            ensure_string_array();
29,700✔
495
            size_t ndx = m_strings.size();
29,700✔
496
            m_strings.add(value.get_string());
29,700✔
497
            val = int64_t(ndx << s_data_shift) | (payload_idx_str << s_payload_idx_shift);
29,700✔
498
            break;
29,700✔
499
        }
×
500
        case type_Binary: {
5,052✔
501
            ensure_string_array();
5,052✔
502
            size_t ndx = m_strings.size();
5,052✔
503
            auto bin = value.get<Binary>();
5,052✔
504
            m_strings.add(StringData(bin.data(), bin.size()));
5,052✔
505
            val = int64_t(ndx << s_data_shift) | (payload_idx_str << s_payload_idx_shift);
5,052✔
506
            break;
5,052✔
507
        }
×
508
        case type_Timestamp: {
3,528✔
509
            ensure_int_pair_array();
3,528✔
510
            size_t ndx = m_int_pairs.size() / 2;
3,528✔
511
            auto t = value.get_timestamp();
3,528✔
512
            m_int_pairs.add(t.get_seconds());
3,528✔
513
            m_int_pairs.add(t.get_nanoseconds());
3,528✔
514
            val = int64_t(ndx << s_data_shift) | (payload_idx_pair << s_payload_idx_shift);
3,528✔
515
            break;
3,528✔
516
        }
×
517
        case type_ObjectId: {
3,684✔
518
            ensure_string_array();
3,684✔
519
            size_t ndx = m_strings.size();
3,684✔
520
            auto id = value.get<ObjectId>();
3,684✔
521
            char buffer[sizeof(ObjectId)];
3,684✔
522
            memcpy(buffer, &id, sizeof(ObjectId));
3,684✔
523
            m_strings.add(StringData(buffer, sizeof(ObjectId)));
3,684✔
524
            val = int64_t(ndx << s_data_shift) | (payload_idx_str << s_payload_idx_shift);
3,684✔
525
            break;
3,684✔
526
        }
×
527
        case type_Decimal: {
5,538✔
528
            ensure_int_pair_array();
5,538✔
529
            size_t ndx = m_int_pairs.size() / 2;
5,538✔
530
            auto t = value.get<Decimal128>();
5,538✔
531
            m_int_pairs.add(t.raw()->w[0]);
5,538✔
532
            m_int_pairs.add(t.raw()->w[1]);
5,538✔
533
            val = int64_t(ndx << s_data_shift) | (payload_idx_pair << s_payload_idx_shift);
5,538✔
534
            break;
5,538✔
535
        }
×
536
        case type_Link: {
✔
537
            ensure_int_array();
×
538
            size_t ndx = m_ints.size();
×
539
            m_ints.add(value.get<ObjKey>().value);
×
540
            val = int64_t(ndx << s_data_shift) | (payload_idx_int << s_payload_idx_shift);
×
541
            break;
×
542
        }
×
543
        case type_TypedLink: {
34,920✔
544
            ensure_int_pair_array();
34,920✔
545
            size_t ndx = m_int_pairs.size() / 2;
34,920✔
546
            auto t = value.get<ObjLink>();
34,920✔
547
            m_int_pairs.add(int64_t(t.get_table_key().value));
34,920✔
548
            m_int_pairs.add(t.get_obj_key().value);
34,920✔
549
            val = int64_t(ndx << s_data_shift) | (payload_idx_pair << s_payload_idx_shift);
34,920✔
550
            break;
34,920✔
551
        }
×
552
        case type_UUID: {
5,052✔
553
            ensure_string_array();
5,052✔
554
            size_t ndx = m_strings.size();
5,052✔
555
            auto id = value.get<UUID>();
5,052✔
556
            const auto uuid_bytes = id.to_bytes();
5,052✔
557
            m_strings.add(StringData(reinterpret_cast<const char*>(uuid_bytes.data()), uuid_bytes.size()));
5,052✔
558
            val = int64_t(ndx << s_data_shift) | (payload_idx_str << s_payload_idx_shift);
5,052✔
559
            break;
5,052✔
560
        }
×
561
        default:
15,720✔
562
            REALM_ASSERT(type == type_List || type == type_Dictionary);
15,720✔
563
            ensure_ref_array();
15,720✔
564
            size_t ndx = m_refs.size();
15,720✔
565
            m_refs.add(value.get_ref());
15,720✔
566
            val = int64_t(ndx << s_data_shift) | (payload_idx_ref << s_payload_idx_shift);
15,720✔
567
            break;
15,720✔
568
    }
156,252✔
569
    return val + int(type) + 1;
156,252✔
570
}
156,252✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc