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

leonchen83 / redis-replicator / #2153

06 Jun 2025 04:52AM UTC coverage: 71.352% (-0.3%) from 71.609%
#2153

push

chenby
redis 8.0

3 of 33 new or added lines in 14 files covered. (9.09%)

3 existing lines in 2 files now uncovered.

6630 of 9292 relevant lines covered (71.35%)

0.71 hits per line

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

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

17
package com.moilioncircle.redis.replicator.rdb.iterable;
18

19
import static com.moilioncircle.redis.replicator.Constants.QUICKLIST_NODE_CONTAINER_PACKED;
20
import static com.moilioncircle.redis.replicator.Constants.QUICKLIST_NODE_CONTAINER_PLAIN;
21
import static com.moilioncircle.redis.replicator.Constants.RDB_LOAD_NONE;
22
import static com.moilioncircle.redis.replicator.rdb.BaseRdbParser.StringHelper.listPackEntry;
23

24
import java.io.IOException;
25
import java.io.UncheckedIOException;
26
import java.util.AbstractMap;
27
import java.util.Iterator;
28
import java.util.Map;
29

30
import com.moilioncircle.redis.replicator.Replicator;
31
import com.moilioncircle.redis.replicator.io.RedisInputStream;
32
import com.moilioncircle.redis.replicator.rdb.BaseRdbParser;
33
import com.moilioncircle.redis.replicator.rdb.DefaultRdbValueVisitor;
34
import com.moilioncircle.redis.replicator.rdb.datatype.ZSetEntry;
35
import com.moilioncircle.redis.replicator.util.ByteArray;
36
import com.moilioncircle.redis.replicator.util.Strings;
37

38
/**
39
 * @author Leon Chen
40
 * @since 3.1.0
41
 */
42
@SuppressWarnings("unchecked")
43
public class ValueIterableRdbValueVisitor extends DefaultRdbValueVisitor {
44

45
    public ValueIterableRdbValueVisitor(Replicator replicator) {
46
        super(replicator);
1✔
47
    }
1✔
48

49
    @Override
50
    public <T> T applyList(RedisInputStream in, int version) throws IOException {
51
        /*
52
         * |    <len>     |       <content>       |
53
         * | 1 or 5 bytes |    string contents    |
54
         */
55
        BaseRdbParser parser = new BaseRdbParser(in);
1✔
56

57
        long len = parser.rdbLoadLen().len;
1✔
58
        Iterator<byte[]> val = new Iter<byte[]>(len, parser) {
1✔
59
            @Override
60
            public boolean hasNext() {
61
                return condition > 0;
1✔
62
            }
63

64
            @Override
65
            public byte[] next() {
66
                try {
67
                    byte[] element = parser.rdbLoadEncodedStringObject().first();
1✔
68
                    condition--;
1✔
69
                    return element;
1✔
70
                } catch (IOException e) {
×
71
                    throw new UncheckedIOException(e);
×
72
                }
73
            }
74
        };
75
        return (T) val;
1✔
76
    }
77

78
    @Override
79
    public <T> T applySet(RedisInputStream in, int version) throws IOException {
80
        /*
81
         * |    <len>     |       <content>       |
82
         * | 1 or 5 bytes |    string contents    |
83
         */
84
        BaseRdbParser parser = new BaseRdbParser(in);
1✔
85

86
        long len = parser.rdbLoadLen().len;
1✔
87
        Iterator<byte[]> val = new Iter<byte[]>(len, parser) {
1✔
88
            @Override
89
            public boolean hasNext() {
90
                return condition > 0;
1✔
91
            }
92

93
            @Override
94
            public byte[] next() {
95
                try {
96
                    byte[] element = parser.rdbLoadEncodedStringObject().first();
1✔
97
                    condition--;
1✔
98
                    return element;
1✔
99
                } catch (IOException e) {
×
100
                    throw new UncheckedIOException(e);
×
101
                }
102
            }
103
        };
104
        return (T) val;
1✔
105
    }
106
    
107
    @Override
108
    public <T> T applySetListPack(RedisInputStream in, int version) throws IOException {
109
        BaseRdbParser parser = new BaseRdbParser(in);
1✔
110
        
111
        RedisInputStream listPack = new RedisInputStream(parser.rdbLoadPlainStringObject());
1✔
112
        listPack.skip(4); // total-bytes
1✔
113
        int len = listPack.readInt(2);
1✔
114
        Iterator<byte[]> val = new Iter<byte[]>(len, null) {
1✔
115
            @Override
116
            public boolean hasNext() {
117
                if (condition > 0) return true;
1✔
118
                try {
119
                    int lpend = listPack.read();
1✔
120
                    if (lpend != 255) {
1✔
121
                        throw new AssertionError("listpack expect 255 but " + lpend);
×
122
                    }
123
                    return false;
1✔
124
                } catch (IOException e) {
×
125
                    throw new UncheckedIOException(e);
×
126
                }
127
            }
128
            
129
            @Override
130
            public byte[] next() {
131
                try {
132
                    byte[] element = listPackEntry(listPack);
1✔
133
                    condition--;
1✔
134
                    return element;
1✔
135
                } catch (IOException e) {
×
136
                    throw new UncheckedIOException(e);
×
137
                }
138
            }
139
        };
140
        return (T) val;
1✔
141
    }
142

143
    @Override
144
    public <T> T applyZSet(RedisInputStream in, int version) throws IOException {
145
        /*
146
         * |    <len>     |       <content>       |        <score>       |
147
         * | 1 or 5 bytes |    string contents    |    double content    |
148
         */
149
        BaseRdbParser parser = new BaseRdbParser(in);
1✔
150

151
        long len = parser.rdbLoadLen().len;
1✔
152
        Iterator<ZSetEntry> val = new Iter<ZSetEntry>(len, parser) {
1✔
153
            @Override
154
            public boolean hasNext() {
155
                return condition > 0;
1✔
156
            }
157

158
            @Override
159
            public ZSetEntry next() {
160
                try {
161
                    byte[] element = parser.rdbLoadEncodedStringObject().first();
1✔
162
                    double score = parser.rdbLoadDoubleValue();
1✔
163
                    condition--;
1✔
164
                    return new ZSetEntry(element, score);
1✔
165
                } catch (IOException e) {
×
166
                    throw new UncheckedIOException(e);
×
167
                }
168
            }
169
        };
170
        return (T) val;
1✔
171
    }
172

173
    @Override
174
    public <T> T applyZSet2(RedisInputStream in, int version) throws IOException {
175
        /*
176
         * |    <len>     |       <content>       |        <score>       |
177
         * | 1 or 5 bytes |    string contents    |    binary double     |
178
         */
179
        BaseRdbParser parser = new BaseRdbParser(in);
1✔
180

181
        /* rdb version 8*/
182
        long len = parser.rdbLoadLen().len;
1✔
183
        Iterator<ZSetEntry> val = new Iter<ZSetEntry>(len, parser) {
1✔
184
            @Override
185
            public boolean hasNext() {
186
                return condition > 0;
1✔
187
            }
188

189
            @Override
190
            public ZSetEntry next() {
191
                try {
192
                    byte[] element = parser.rdbLoadEncodedStringObject().first();
1✔
193
                    double score = parser.rdbLoadBinaryDoubleValue();
1✔
194
                    condition--;
1✔
195
                    return new ZSetEntry(element, score);
1✔
196
                } catch (IOException e) {
×
197
                    throw new UncheckedIOException(e);
×
198
                }
199
            }
200
        };
201
        return (T) val;
1✔
202
    }
203

204
    @Override
205
    public <T> T applyHash(RedisInputStream in, int version) throws IOException {
206
        /*
207
         * |    <len>     |       <content>       |
208
         * | 1 or 5 bytes |    string contents    |
209
         */
210
        BaseRdbParser parser = new BaseRdbParser(in);
1✔
211

212
        long len = parser.rdbLoadLen().len;
1✔
213
        Iterator<Map.Entry<byte[], byte[]>> val = new Iter<Map.Entry<byte[], byte[]>>(len, parser) {
1✔
214
            @Override
215
            public boolean hasNext() {
216
                return condition > 0;
1✔
217
            }
218

219
            @Override
220
            public Map.Entry<byte[], byte[]> next() {
221
                try {
222
                    byte[] field = parser.rdbLoadEncodedStringObject().first();
1✔
223
                    byte[] value = parser.rdbLoadEncodedStringObject().first();
1✔
224
                    condition--;
1✔
225
                    return new AbstractMap.SimpleEntry<>(field, value);
1✔
226
                } catch (IOException e) {
×
227
                    throw new UncheckedIOException(e);
×
228
                }
229
            }
230
        };
231
        return (T) val;
1✔
232
    }
233

234
    @Override
235
    public <T> T applyHashZipMap(RedisInputStream in, int version) throws IOException {
236
        /*
237
         * |<zmlen> |   <len>     |"foo"    |    <len>   | <free> |   "bar" |<zmend> |
238
         * | 1 byte | 1 or 5 byte | content |1 or 5 byte | 1 byte | content | 1 byte |
239
         */
240
        BaseRdbParser parser = new BaseRdbParser(in);
1✔
241

242
        RedisInputStream stream = new RedisInputStream(parser.rdbLoadPlainStringObject());
1✔
243
        BaseRdbParser.LenHelper.zmlen(stream); // zmlen
1✔
244
        Iterator<Map.Entry<byte[], byte[]>> val = new HashZipMapIter(stream);
1✔
245
        return (T) val;
1✔
246
    }
247

248
    @Override
249
    public <T> T applyListZipList(RedisInputStream in, int version) throws IOException {
250
        /*
251
         * |<zlbytes>| <zltail>| <zllen>| <entry> ...<entry> | <zlend>|
252
         * | 4 bytes | 4 bytes | 2bytes | zipListEntry ...   | 1byte  |
253
         */
254
        BaseRdbParser parser = new BaseRdbParser(in);
1✔
255

256
        final RedisInputStream stream = new RedisInputStream(parser.rdbLoadPlainStringObject());
1✔
257
        BaseRdbParser.LenHelper.zlbytes(stream); // zlbytes
1✔
258
        BaseRdbParser.LenHelper.zltail(stream); // zltail
1✔
259
        int zllen = BaseRdbParser.LenHelper.zllen(stream);
1✔
260
        Iterator<byte[]> val = new Iter<byte[]>(zllen, null) {
1✔
261
            @Override
262
            public boolean hasNext() {
263
                if (condition > 0) return true;
1✔
264
                try {
265
                    int zlend = BaseRdbParser.LenHelper.zlend(stream);
1✔
266
                    if (zlend != 255) {
1✔
267
                        throw new AssertionError("zlend expect 255 but " + zlend);
×
268
                    }
269
                    return false;
1✔
270
                } catch (IOException e) {
×
271
                    throw new UncheckedIOException(e);
×
272
                }
273
            }
274

275
            @Override
276
            public byte[] next() {
277
                try {
278
                    byte[] e = BaseRdbParser.StringHelper.zipListEntry(stream);
1✔
279
                    condition--;
1✔
280
                    return e;
1✔
281
                } catch (IOException e) {
×
282
                    throw new UncheckedIOException(e);
×
283
                }
284
            }
285
        };
286
        return (T) val;
1✔
287
    }
288

289
    @Override
290
    public <T> T applySetIntSet(RedisInputStream in, int version) throws IOException {
291
        /*
292
         * |<encoding>| <length-of-contents>|              <contents>                            |
293
         * | 4 bytes  |            4 bytes  | 2 bytes element| 4 bytes element | 8 bytes element |
294
         */
295
        BaseRdbParser parser = new BaseRdbParser(in);
1✔
296

297
        final RedisInputStream stream = new RedisInputStream(parser.rdbLoadPlainStringObject());
1✔
298
        final int encoding = BaseRdbParser.LenHelper.encoding(stream);
1✔
299
        long lenOfContent = BaseRdbParser.LenHelper.lenOfContent(stream);
1✔
300
        Iterator<byte[]> val = new Iter<byte[]>(lenOfContent, null) {
1✔
301
            @Override
302
            public boolean hasNext() {
303
                return condition > 0;
1✔
304
            }
305

306
            @Override
307
            public byte[] next() {
308
                try {
309
                    switch (encoding) {
1✔
310
                        case 2:
311
                            String element = String.valueOf(stream.readInt(2));
1✔
312
                            condition--;
1✔
313
                            return element.getBytes();
1✔
314
                        case 4:
315
                            element = String.valueOf(stream.readInt(4));
1✔
316
                            condition--;
1✔
317
                            return element.getBytes();
1✔
318
                        case 8:
319
                            element = String.valueOf(stream.readLong(8));
1✔
320
                            condition--;
1✔
321
                            return element.getBytes();
1✔
322
                        default:
323
                            throw new AssertionError("expect encoding [2,4,8] but:" + encoding);
×
324
                    }
325
                } catch (IOException e) {
×
326
                    throw new UncheckedIOException(e);
×
327
                }
328
            }
329
        };
330
        return (T) val;
1✔
331
    }
332

333
    @Override
334
    public <T> T applyZSetZipList(RedisInputStream in, int version) throws IOException {
335
        /*
336
         * |<zlbytes>| <zltail>| <zllen>| <entry> ...<entry> | <zlend>|
337
         * | 4 bytes | 4 bytes | 2bytes | zipListEntry ...   | 1byte  |
338
         */
339
        BaseRdbParser parser = new BaseRdbParser(in);
1✔
340

341
        final RedisInputStream stream = new RedisInputStream(parser.rdbLoadPlainStringObject());
1✔
342
        BaseRdbParser.LenHelper.zlbytes(stream); // zlbytes
1✔
343
        BaseRdbParser.LenHelper.zltail(stream); // zltail
1✔
344
        int zllen = BaseRdbParser.LenHelper.zllen(stream);
1✔
345
        Iterator<ZSetEntry> val = new Iter<ZSetEntry>(zllen, null) {
1✔
346
            @Override
347
            public boolean hasNext() {
348
                if (condition > 0) return true;
1✔
349
                try {
350
                    int zlend = BaseRdbParser.LenHelper.zlend(stream);
1✔
351
                    if (zlend != 255) {
1✔
352
                        throw new AssertionError("zlend expect 255 but " + zlend);
×
353
                    }
354
                    return false;
1✔
355
                } catch (IOException e) {
×
356
                    throw new UncheckedIOException(e);
×
357
                }
358
            }
359

360
            @Override
361
            public ZSetEntry next() {
362
                try {
363
                    byte[] element = BaseRdbParser.StringHelper.zipListEntry(stream);
1✔
364
                    condition--;
1✔
365
                    double score = Double.valueOf(Strings.toString(BaseRdbParser.StringHelper.zipListEntry(stream)));
1✔
366
                    condition--;
1✔
367
                    return new ZSetEntry(element, score);
1✔
368
                } catch (IOException e) {
×
369
                    throw new UncheckedIOException(e);
×
370
                }
371
            }
372
        };
373
        return (T) val;
1✔
374
    }
375
    
376
    @Override
377
    public <T> T applyZSetListPack(RedisInputStream in, int version) throws IOException {
378
        BaseRdbParser parser = new BaseRdbParser(in);
1✔
379
    
380
        RedisInputStream listPack = new RedisInputStream(parser.rdbLoadPlainStringObject());
1✔
381
        listPack.skip(4); // total-bytes
1✔
382
        int len = listPack.readInt(2);
1✔
383
        Iterator<ZSetEntry> val = new Iter<ZSetEntry>(len, null) {
1✔
384
            @Override
385
            public boolean hasNext() {
386
                if (condition > 0) return true;
1✔
387
                try {
388
                    int lpend = listPack.read();
1✔
389
                    if (lpend != 255) {
1✔
390
                        throw new AssertionError("listpack expect 255 but " + lpend);
×
391
                    }
392
                    return false;
1✔
393
                } catch (IOException e) {
×
394
                    throw new UncheckedIOException(e);
×
395
                }
396
            }
397
        
398
            @Override
399
            public ZSetEntry next() {
400
                try {
401
                    byte[] element = listPackEntry(listPack);
1✔
402
                    condition--;
1✔
403
                    double score = Double.valueOf(Strings.toString(listPackEntry(listPack)));
1✔
404
                    condition--;
1✔
405
                    return new ZSetEntry(element, score);
1✔
406
                } catch (IOException e) {
×
407
                    throw new UncheckedIOException(e);
×
408
                }
409
            }
410
        };
411
        return (T) val;
1✔
412
    }
413

414
    @Override
415
    public <T> T applyHashZipList(RedisInputStream in, int version) throws IOException {
416
        /*
417
         * |<zlbytes>| <zltail>| <zllen>| <entry> ...<entry> | <zlend>|
418
         * | 4 bytes | 4 bytes | 2bytes | zipListEntry ...   | 1byte  |
419
         */
420
        BaseRdbParser parser = new BaseRdbParser(in);
1✔
421

422
        final RedisInputStream stream = new RedisInputStream(parser.rdbLoadPlainStringObject());
1✔
423
        BaseRdbParser.LenHelper.zlbytes(stream); // zlbytes
1✔
424
        BaseRdbParser.LenHelper.zltail(stream); // zltail
1✔
425
        int zllen = BaseRdbParser.LenHelper.zllen(stream);
1✔
426
        Iterator<Map.Entry<byte[], byte[]>> val = new Iter<Map.Entry<byte[], byte[]>>(zllen, null) {
1✔
427
            @Override
428
            public boolean hasNext() {
429
                if (condition > 0) return true;
1✔
430
                try {
431
                    int zlend = BaseRdbParser.LenHelper.zlend(stream);
1✔
432
                    if (zlend != 255) {
1✔
433
                        throw new AssertionError("zlend expect 255 but " + zlend);
×
434
                    }
435
                    return false;
1✔
436
                } catch (IOException e) {
×
437
                    throw new UncheckedIOException(e);
×
438
                }
439
            }
440

441
            @Override
442
            public Map.Entry<byte[], byte[]> next() {
443
                try {
444
                    byte[] field = BaseRdbParser.StringHelper.zipListEntry(stream);
1✔
445
                    condition--;
1✔
446
                    byte[] value = BaseRdbParser.StringHelper.zipListEntry(stream);
1✔
447
                    condition--;
1✔
448
                    return new AbstractMap.SimpleEntry<>(field, value);
1✔
449
                } catch (IOException e) {
×
450
                    throw new UncheckedIOException(e);
×
451
                }
452
            }
453
        };
454
        return (T) val;
1✔
455
    }
456
    
457
    @Override
458
    public <T> T applyHashListPack(RedisInputStream in, int version) throws IOException {
459
        BaseRdbParser parser = new BaseRdbParser(in);
1✔
460

461
        RedisInputStream listPack = new RedisInputStream(parser.rdbLoadPlainStringObject());
1✔
462
        listPack.skip(4); // total-bytes
1✔
463
        int len = listPack.readInt(2);
1✔
464
        Iterator<Map.Entry<byte[], byte[]>> val = new Iter<Map.Entry<byte[], byte[]>>(len, null) {
1✔
465
            @Override
466
            public boolean hasNext() {
467
                if (condition > 0) return true;
1✔
468
                try {
469
                    int lpend = listPack.read();
1✔
470
                    if (lpend != 255) {
1✔
471
                        throw new AssertionError("listpack expect 255 but " + lpend);
×
472
                    }
473
                    return false;
1✔
474
                } catch (IOException e) {
×
475
                    throw new UncheckedIOException(e);
×
476
                }
477
            }
478

479
            @Override
480
            public Map.Entry<byte[], byte[]> next() {
481
                try {
482
                    byte[] field = listPackEntry(listPack);
1✔
483
                    condition--;
1✔
484
                    byte[] value = listPackEntry(listPack);
1✔
485
                    condition--;
1✔
486
                    return new AbstractMap.SimpleEntry<>(field, value);
1✔
487
                } catch (IOException e) {
×
488
                    throw new UncheckedIOException(e);
×
489
                }
490
            }
491
        };
492
        return (T) val;
1✔
493
    }
494

495
    @Override
496
    public <T> T applyListQuickList(RedisInputStream in, int version) throws IOException {
497
        BaseRdbParser parser = new BaseRdbParser(in);
1✔
498

499
        long len = parser.rdbLoadLen().len;
1✔
500
        Iterator<byte[]> val = new QuickListIter(len, parser);
1✔
501
        return (T) val;
1✔
502
    }
503
    
504
    @Override
505
    public <T> T applyListQuickList2(RedisInputStream in, int version) throws IOException {
506
        BaseRdbParser parser = new BaseRdbParser(in);
1✔
507
    
508
        long len = parser.rdbLoadLen().len;
1✔
509
        Iterator<byte[]> val = new QuickList2Iter(len, parser);
1✔
510
        return (T) val;
1✔
511
    }
512
    
513
    @Override
514
    public <T> T applyHashMetadata(RedisInputStream in, int version) throws IOException{
515
        // TODO
NEW
516
        return null;
×
517
    }
518
    
519
    @Override
520
    public <T> T applyHashListPackEx(RedisInputStream in, int version) throws IOException {
521
        // TODO
NEW
522
        return null;
×
523
    }
524

525
    private static abstract class Iter<T> implements Iterator<T> {
526

527
        protected long condition;
528
        protected final BaseRdbParser parser;
529

530
        private Iter(long condition, BaseRdbParser parser) {
1✔
531
            this.condition = condition;
1✔
532
            this.parser = parser;
1✔
533
        }
1✔
534

535
        @Override
536
        public void remove() {
537
            throw new UnsupportedOperationException();
×
538
        }
539
    }
540

541
    private static class HashZipMapIter extends Iter<Map.Entry<byte[], byte[]>> {
542

543
        protected int zmEleLen;
544
        protected final RedisInputStream stream;
545

546
        private HashZipMapIter(RedisInputStream stream) {
547
            super(0, null);
1✔
548
            this.stream = stream;
1✔
549
        }
1✔
550

551
        @Override
552
        public boolean hasNext() {
553
            try {
554
                return (this.zmEleLen = BaseRdbParser.LenHelper.zmElementLen(stream)) != 255;
1✔
555
            } catch (IOException e) {
×
556
                throw new UncheckedIOException(e);
×
557
            }
558
        }
559

560
        @Override
561
        public Map.Entry<byte[], byte[]> next() {
562
            try {
563
                byte[] field = BaseRdbParser.StringHelper.bytes(stream, zmEleLen);
1✔
564
                this.zmEleLen = BaseRdbParser.LenHelper.zmElementLen(stream);
1✔
565
                if (this.zmEleLen == 255) {
1✔
566
                    return new AbstractMap.SimpleEntry<>(field, null);
×
567
                }
568
                int free = BaseRdbParser.LenHelper.free(stream);
1✔
569
                byte[] value = BaseRdbParser.StringHelper.bytes(stream, zmEleLen);
1✔
570
                BaseRdbParser.StringHelper.skip(stream, free);
1✔
571
                return new AbstractMap.SimpleEntry<>(field, value);
1✔
572
            } catch (IOException e) {
×
573
                throw new UncheckedIOException(e);
×
574
            }
575
        }
576
    }
577

578
    private static class QuickListIter extends Iter<byte[]> {
579

580
        protected int zllen = -1;
1✔
581
        protected RedisInputStream stream;
582

583
        private QuickListIter(long condition, BaseRdbParser parser) {
584
            super(condition, parser);
1✔
585
        }
1✔
586

587
        @Override
588
        public boolean hasNext() {
589
            return zllen > 0 || condition > 0;
1✔
590
        }
591

592
        @Override
593
        public byte[] next() {
594
            try {
595
                if (zllen == -1 && condition > 0) {
1✔
596
                    this.stream = new RedisInputStream(parser.rdbGenericLoadStringObject(RDB_LOAD_NONE));
1✔
597
                    BaseRdbParser.LenHelper.zlbytes(stream); // zlbytes
1✔
598
                    BaseRdbParser.LenHelper.zltail(stream); // zltail
1✔
599
                    this.zllen = BaseRdbParser.LenHelper.zllen(stream);
1✔
600
                    if (zllen == 0) {
1✔
601
                        int zlend = BaseRdbParser.LenHelper.zlend(stream);
×
602
                        if (zlend != 255) {
×
603
                            throw new AssertionError("zlend expect 255 but " + zlend);
×
604
                        }
605
                        zllen = -1;
×
606
                        condition--;
×
607
                    }
608
                    if (hasNext()) return next();
1✔
609
                    throw new IllegalStateException("end of iterator");
×
610
                } else {
611
                    byte[] e = BaseRdbParser.StringHelper.zipListEntry(stream);
1✔
612
                    zllen--;
1✔
613
                    if (zllen == 0) {
1✔
614
                        int zlend = BaseRdbParser.LenHelper.zlend(stream);
1✔
615
                        if (zlend != 255) {
1✔
616
                            throw new AssertionError("zlend expect 255 but " + zlend);
×
617
                        }
618
                        zllen = -1;
1✔
619
                        condition--;
1✔
620
                    }
621
                    return e;
1✔
622
                }
623
            } catch (IOException e) {
×
624
                throw new UncheckedIOException(e);
×
625
            }
626
        }
627
    }
628
    
629
    private static class QuickList2Iter extends Iter<byte[]> {
630
        
631
        protected int innerLen = -1;
1✔
632
        protected RedisInputStream listPack;
633
        
634
        private QuickList2Iter(long condition, BaseRdbParser parser) {
635
            super(condition, parser);
1✔
636
        }
1✔
637
        
638
        @Override
639
        public boolean hasNext() {
640
            return innerLen > 0 || condition > 0;
1✔
641
        }
642
        
643
        @Override
644
        public byte[] next() {
645
            try {
646
                if (innerLen == -1 && condition > 0) {
1✔
647
                    long container = parser.rdbLoadLen().len;
1✔
648
                    ByteArray bytes = parser.rdbLoadPlainStringObject();
1✔
649
                    if (container == QUICKLIST_NODE_CONTAINER_PLAIN) {
1✔
650
                        innerLen = -1;
1✔
651
                        condition--;
1✔
652
                        return bytes.first();
1✔
653
                    } else if (container == QUICKLIST_NODE_CONTAINER_PACKED) {
1✔
654
                        this.listPack = new RedisInputStream(bytes);
1✔
655
                        listPack.skip(4);
1✔
656
                        this.innerLen = listPack.readInt(2);
1✔
657
                        if (innerLen == 0) {
1✔
658
                            int lpend = listPack.read();
×
659
                            if (lpend != 255) {
×
660
                                throw new AssertionError("listpack expect 255 but " + lpend);
×
661
                            }
662
                            innerLen = -1;
×
663
                            condition--;
×
664
                        }
665
                        if (hasNext()) return next();
1✔
666
                        throw new IllegalStateException("end of iterator");
×
667
                    } else {
668
                        throw new UnsupportedOperationException(String.valueOf(container));
×
669
                    }
670
                } else {
671
                    byte[] e = listPackEntry(listPack);
1✔
672
                    innerLen--;
1✔
673
                    if (innerLen == 0) {
1✔
674
                        int lpend = listPack.read();
1✔
675
                        if (lpend != 255) {
1✔
676
                            throw new AssertionError("listpack expect 255 but " + lpend);
×
677
                        }
678
                        innerLen = -1;
1✔
679
                        condition--;
1✔
680
                    }
681
                    return e;
1✔
682
                }
683
            } catch (IOException e) {
×
684
                throw new UncheckedIOException(e);
×
685
            }
686
        }
687
    }
688
}
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

© 2026 Coveralls, Inc