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

wuwen5 / hessian / 17328794241

29 Aug 2025 03:55PM UTC coverage: 68.88% (+0.1%) from 68.748%
17328794241

push

github

web-flow
fix: Fix the issue of parent class fields covering subclasses (#39)

1835 of 2863 branches covered (64.09%)

Branch coverage included in aggregate %.

4212 of 5916 relevant lines covered (71.2%)

3.1 hits per line

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

75.0
hessian2-codec/src/main/java/io/github/wuwen5/hessian/io/HessianDebugState.java
1
/*
2
 * Copyright (c) 2001-2004 Caucho Technology, Inc.  All rights reserved.
3
 *
4
 * The Apache Software License, Version 1.1
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 *
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 *
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in
15
 *    the documentation and/or other materials provided with the
16
 *    distribution.
17
 *
18
 * 3. The end-user documentation included with the redistribution, if
19
 *    any, must include the following acknowlegement:
20
 *       "This product includes software developed by the
21
 *        Caucho Technology (http://www.caucho.com/)."
22
 *    Alternately, this acknowlegement may appear in the software itself,
23
 *    if and wherever such third-party acknowlegements normally appear.
24
 *
25
 * 4. The names "Hessian", "Resin", and "Caucho" must not be used to
26
 *    endorse or promote products derived from this software without prior
27
 *    written permission. For written permission, please contact
28
 *    info@caucho.com.
29
 *
30
 * 5. Products derived from this software may not be called "Resin"
31
 *    nor may "Resin" appear in their names without prior written
32
 *    permission of Caucho Technology.
33
 *
34
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
35
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
36
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37
 * DISCLAIMED.  IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
38
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
39
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
40
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
43
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
44
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45
 *
46
 * @author Scott Ferguson
47
 */
48

49
package io.github.wuwen5.hessian.io;
50

51
import java.io.PrintWriter;
52
import java.util.ArrayList;
53
import java.util.List;
54
import java.util.logging.Logger;
55
import lombok.Getter;
56
import lombok.Setter;
57

58
/**
59
 * Debugging input stream for Hessian requests.
60
 */
61
public class HessianDebugState implements Hessian2Constants {
62
    private static final Logger log = Logger.getLogger(HessianDebugState.class.getName());
5✔
63

64
    private final PrintWriter dbg;
65

66
    private State state;
67
    private final List<State> stateStack = new ArrayList<>();
5✔
68

69
    private final List<ObjectDef> objectDefList = new ArrayList<>();
5✔
70

71
    private final ArrayList<String> typeDefList = new ArrayList<>();
5✔
72

73
    private int refId;
74
    private boolean isNewline = true;
3✔
75
    private boolean isObject = false;
3✔
76
    private int column;
77

78
    @Getter
3✔
79
    @Setter
80
    private int depth = 0;
81

82
    /**
83
     * Creates an uninitialized Hessian input stream.
84
     */
85
    public HessianDebugState(PrintWriter dbg) {
2✔
86
        this.dbg = dbg;
3✔
87

88
        state = new InitialState();
6✔
89
    }
1✔
90

91
    public void startTop2() {
92
        state = new Top2State();
6✔
93
    }
1✔
94

95
    public void startStreaming() {
96
        state = new StreamingState(new InitialState(), false);
11✔
97
    }
1✔
98

99
    /**
100
     * Reads a character.
101
     */
102
    public void next(int ch) {
103
        state = state.next(ch);
6✔
104
    }
1✔
105

106
    void pushStack(State state) {
107
        stateStack.add(state);
×
108
    }
×
109

110
    State popStack() {
111
        return stateStack.remove(stateStack.size() - 1);
×
112
    }
113

114
    void println() {
115
        if (!isNewline) {
3!
116
            dbg.println();
×
117
            dbg.flush();
×
118
        }
119

120
        isNewline = true;
3✔
121
        column = 0;
3✔
122
    }
1✔
123

124
    abstract class State {
125
        State next;
126

127
        State() {}
6✔
128

129
        State(State next) {
5✔
130
            this.next = next;
3✔
131
        }
1✔
132

133
        abstract State next(int ch);
134

135
        boolean isShift(Object value) {
136
            return false;
2✔
137
        }
138

139
        State shift(Object value) {
140
            return this;
×
141
        }
142

143
        int depth() {
144
            if (next != null) {
3✔
145
                return next.depth();
4✔
146
            } else {
147
                return HessianDebugState.this.getDepth();
4✔
148
            }
149
        }
150

151
        void printIndent(int depth) {
152
            if (isNewline) {
4✔
153
                for (int i = column; i < depth() + depth; i++) {
12✔
154
                    dbg.print(" ");
5✔
155
                    column++;
7✔
156
                }
157
            }
158
        }
1✔
159

160
        void print(String string) {
161
            print(0, string);
4✔
162
        }
1✔
163

164
        void print(int depth, String string) {
165
            printIndent(depth);
3✔
166

167
            dbg.print(string);
5✔
168
            isNewline = false;
4✔
169
            isObject = false;
4✔
170

171
            int p = string.lastIndexOf('\n');
4✔
172
            if (p > 0) {
2!
173
                column = string.length() - p - 1;
×
174
            } else {
175
                column += string.length();
8✔
176
            }
177
        }
1✔
178

179
        void println(String string) {
180
            println(0, string);
4✔
181
        }
1✔
182

183
        void println(int depth, String string) {
184
            printIndent(depth);
3✔
185

186
            dbg.println(string);
5✔
187
            dbg.flush();
4✔
188
            isNewline = true;
4✔
189
            isObject = false;
4✔
190
            column = 0;
4✔
191
        }
1✔
192

193
        void println() {
194
            if (!isNewline) {
4✔
195
                dbg.println();
4✔
196
                dbg.flush();
4✔
197
            }
198

199
            isNewline = true;
4✔
200
            isObject = false;
4✔
201
            column = 0;
4✔
202
        }
1✔
203

204
        void printObject(String string) {
205
            if (isObject) {
4✔
206
                println();
2✔
207
            }
208

209
            printIndent(0);
3✔
210

211
            dbg.print(string);
5✔
212
            dbg.flush();
4✔
213

214
            column += string.length();
8✔
215

216
            isNewline = false;
4✔
217
            isObject = true;
4✔
218
        }
1✔
219

220
        protected State nextObject(int ch) {
221
            switch (ch) {
2!
222
                case -1:
223
                    println();
2✔
224
                    return this;
2✔
225

226
                case 'N':
227
                    if (isShift(null)) {
4!
228
                        return shift(null);
×
229
                    } else {
230
                        printObject("null");
3✔
231
                        return this;
2✔
232
                    }
233

234
                case 'T':
235
                    if (isShift(Boolean.TRUE)) {
4!
236
                        return shift(Boolean.TRUE);
×
237
                    } else {
238
                        printObject("true");
3✔
239
                        return this;
2✔
240
                    }
241

242
                case 'F':
243
                    if (isShift(Boolean.FALSE)) {
4!
244
                        return shift(Boolean.FALSE);
×
245
                    } else {
246
                        printObject("false");
3✔
247
                        return this;
2✔
248
                    }
249

250
                case 0x80:
251
                case 0x81:
252
                case 0x82:
253
                case 0x83:
254
                case 0x84:
255
                case 0x85:
256
                case 0x86:
257
                case 0x87:
258
                case 0x88:
259
                case 0x89:
260
                case 0x8a:
261
                case 0x8b:
262
                case 0x8c:
263
                case 0x8d:
264
                case 0x8e:
265
                case 0x8f:
266

267
                case 0x90:
268
                case 0x91:
269
                case 0x92:
270
                case 0x93:
271
                case 0x94:
272
                case 0x95:
273
                case 0x96:
274
                case 0x97:
275
                case 0x98:
276
                case 0x99:
277
                case 0x9a:
278
                case 0x9b:
279
                case 0x9c:
280
                case 0x9d:
281
                case 0x9e:
282
                case 0x9f:
283

284
                case 0xa0:
285
                case 0xa1:
286
                case 0xa2:
287
                case 0xa3:
288
                case 0xa4:
289
                case 0xa5:
290
                case 0xa6:
291
                case 0xa7:
292
                case 0xa8:
293
                case 0xa9:
294
                case 0xaa:
295
                case 0xab:
296
                case 0xac:
297
                case 0xad:
298
                case 0xae:
299
                case 0xaf:
300

301
                case 0xb0:
302
                case 0xb1:
303
                case 0xb2:
304
                case 0xb3:
305
                case 0xb4:
306
                case 0xb5:
307
                case 0xb6:
308
                case 0xb7:
309
                case 0xb8:
310
                case 0xb9:
311
                case 0xba:
312
                case 0xbb:
313
                case 0xbc:
314
                case 0xbd:
315
                case 0xbe:
316
                case 0xbf: {
317
                    Integer value = ch - 0x90;
5✔
318

319
                    if (isShift(value)) {
4✔
320
                        return shift(value);
4✔
321
                    } else {
322
                        printObject(value.toString());
4✔
323
                        return this;
2✔
324
                    }
325
                }
326

327
                case 0xc0:
328
                case 0xc1:
329
                case 0xc2:
330
                case 0xc3:
331
                case 0xc4:
332
                case 0xc5:
333
                case 0xc6:
334
                case 0xc7:
335
                case 0xc8:
336
                case 0xc9:
337
                case 0xca:
338
                case 0xcb:
339
                case 0xcc:
340
                case 0xcd:
341
                case 0xce:
342
                case 0xcf:
343
                    return new IntegerState(this, "int", ch - 0xc8, 3);
12✔
344

345
                case 0xd0:
346
                case 0xd1:
347
                case 0xd2:
348
                case 0xd3:
349
                case 0xd4:
350
                case 0xd5:
351
                case 0xd6:
352
                case 0xd7:
353
                    return new IntegerState(this, "int", ch - 0xd4, 2);
12✔
354

355
                case 'I':
356
                    return new IntegerState(this, "int");
8✔
357

358
                case 0xd8:
359
                case 0xd9:
360
                case 0xda:
361
                case 0xdb:
362
                case 0xdc:
363
                case 0xdd:
364
                case 0xde:
365
                case 0xdf:
366
                case 0xe0:
367
                case 0xe1:
368
                case 0xe2:
369
                case 0xe3:
370
                case 0xe4:
371
                case 0xe5:
372
                case 0xe6:
373
                case 0xe7:
374
                case 0xe8:
375
                case 0xe9:
376
                case 0xea:
377
                case 0xeb:
378
                case 0xec:
379
                case 0xed:
380
                case 0xee:
381
                case 0xef: {
382
                    Long value = (long) (ch - 0xe0);
6✔
383

384
                    if (isShift(value)) {
4!
385
                        return shift(value);
×
386
                    } else {
387
                        printObject(value + "L");
4✔
388
                        return this;
2✔
389
                    }
390
                }
391

392
                case 0xf0:
393
                case 0xf1:
394
                case 0xf2:
395
                case 0xf3:
396
                case 0xf4:
397
                case 0xf5:
398
                case 0xf6:
399
                case 0xf7:
400
                case 0xf8:
401
                case 0xf9:
402
                case 0xfa:
403
                case 0xfb:
404
                case 0xfc:
405
                case 0xfd:
406
                case 0xfe:
407
                case 0xff:
408
                    return new LongState(this, "long", (long) ch - 0xf8, 7);
13✔
409

410
                case 0x38:
411
                case 0x39:
412
                case 0x3a:
413
                case 0x3b:
414
                case 0x3c:
415
                case 0x3d:
416
                case 0x3e:
417
                case 0x3f:
418
                    return new LongState(this, "long", (long) ch - 0x3c, 6);
13✔
419

420
                case BC_LONG_INT:
421
                    return new LongState(this, "long", 0, 4);
10✔
422

423
                case 'L':
424
                    return new LongState(this, "long");
8✔
425

426
                case 0x5b:
427
                case 0x5c: {
428
                    Double value = (double) (ch - 0x5b);
6✔
429

430
                    if (isShift(value)) {
4!
431
                        return shift(value);
×
432
                    } else {
433
                        printObject(value.toString());
4✔
434
                        return this;
2✔
435
                    }
436
                }
437

438
                case 0x5d:
439
                    return new DoubleIntegerState(this, 3);
8✔
440

441
                case 0x5e:
442
                    return new DoubleIntegerState(this, 2);
8✔
443

444
                case 0x5f:
445
                    return new MillsState(this);
7✔
446

447
                case 'D':
448
                    return new DoubleState(this);
7✔
449

450
                case 'Q':
451
                    return new RefState(this);
7✔
452

453
                case BC_DATE:
454
                    return new DateState(this);
7✔
455

456
                case BC_DATE_MINUTE:
457
                    return new DateState(this, true);
8✔
458

459
                case 0x00: {
460
                    String value = "\"\"";
2✔
461

462
                    if (isShift(value)) return shift(value);
4!
463
                    else {
464
                        printObject(value);
3✔
465
                        return this;
2✔
466
                    }
467
                }
468

469
                case 0x01:
470
                case 0x02:
471
                case 0x03:
472
                case 0x04:
473
                case 0x05:
474
                case 0x06:
475
                case 0x07:
476
                case 0x08:
477
                case 0x09:
478
                case 0x0a:
479
                case 0x0b:
480
                case 0x0c:
481
                case 0x0d:
482
                case 0x0e:
483
                case 0x0f:
484

485
                case 0x10:
486
                case 0x11:
487
                case 0x12:
488
                case 0x13:
489
                case 0x14:
490
                case 0x15:
491
                case 0x16:
492
                case 0x17:
493
                case 0x18:
494
                case 0x19:
495
                case 0x1a:
496
                case 0x1b:
497
                case 0x1c:
498
                case 0x1d:
499
                case 0x1e:
500
                case 0x1f:
501
                    return new StringState(this, 'S', ch);
9✔
502

503
                case 0x30:
504
                case 0x31:
505
                case 0x32:
506
                case 0x33:
507
                    return new StringState(this, 'S', ch - 0x30, true);
12✔
508

509
                case 'R':
510
                    return new StringState(this, 'S', false);
9✔
511

512
                case 'S':
513
                    return new StringState(this, 'S', true);
9✔
514

515
                case 0x20: {
516
                    String value = "binary(0)";
2✔
517

518
                    if (isShift(value)) {
4!
519
                        return shift(value);
×
520
                    } else {
521
                        printObject(value);
3✔
522
                        return this;
2✔
523
                    }
524
                }
525

526
                case 0x21:
527
                case 0x22:
528
                case 0x23:
529
                case 0x24:
530
                case 0x25:
531
                case 0x26:
532
                case 0x27:
533
                case 0x28:
534
                case 0x29:
535
                case 0x2a:
536
                case 0x2b:
537
                case 0x2c:
538
                case 0x2d:
539
                case 0x2e:
540
                case 0x2f:
541
                    return new BinaryState(this, 'B', ch - 0x20);
11✔
542

543
                case 0x34:
544
                case 0x35:
545
                case 0x36:
546
                case 0x37:
547
                    return new BinaryState(this, 'B', ch - 0x34, true);
12✔
548

549
                case 'A':
550
                    return new BinaryState(this, 'B', false);
9✔
551

552
                case 'B':
553
                    return new BinaryState(this, 'B', true);
9✔
554

555
                case 'M':
556
                    return new MapState(this, refId++);
15✔
557

558
                case 'H':
559
                    return new MapState(this, refId++, false);
16✔
560

561
                case BC_LIST_VARIABLE:
562
                    return new ListState(this, refId++, true);
16✔
563

564
                case BC_LIST_VARIABLE_UNTYPED:
565
                    return new ListState(this, refId++, false);
16✔
566

567
                case BC_LIST_FIXED:
568
                    return new CompactListState(this, refId++, true);
16✔
569

570
                case BC_LIST_FIXED_UNTYPED:
571
                    return new CompactListState(this, refId++, false);
16✔
572

573
                case 0x70:
574
                case 0x71:
575
                case 0x72:
576
                case 0x73:
577
                case 0x74:
578
                case 0x75:
579
                case 0x76:
580
                case 0x77:
581
                    return new CompactListState(this, refId++, true, ch - 0x70);
19✔
582

583
                case 0x78:
584
                case 0x79:
585
                case 0x7a:
586
                case 0x7b:
587
                case 0x7c:
588
                case 0x7d:
589
                case 0x7e:
590
                case 0x7f:
591
                    return new CompactListState(this, refId++, false, ch - 0x78);
19✔
592

593
                case 'C':
594
                    return new ObjectDefState(this);
7✔
595

596
                case 0x60:
597
                case 0x61:
598
                case 0x62:
599
                case 0x63:
600
                case 0x64:
601
                case 0x65:
602
                case 0x66:
603
                case 0x67:
604
                case 0x68:
605
                case 0x69:
606
                case 0x6a:
607
                case 0x6b:
608
                case 0x6c:
609
                case 0x6d:
610
                case 0x6e:
611
                case 0x6f:
612
                    return new ObjectState(this, refId++, ch - 0x60);
18✔
613

614
                case 'O':
615
                    return new ObjectState(this, refId++);
×
616

617
                default:
618
                    return this;
×
619
            }
620
        }
621
    }
622

623
    class InitialState extends State {
7✔
624
        @Override
625
        State next(int ch) {
626
            return nextObject(ch);
4✔
627
        }
628
    }
629

630
    class Top2State extends State {
7✔
631
        @Override
632
        State next(int ch) {
633
            println();
2✔
634

635
            if (ch == 'R') {
3!
636
                return new Reply2State(this);
×
637
            } else if (ch == 'F') {
3✔
638
                return new Fault2State(this);
7✔
639
            } else if (ch == 'C') {
3✔
640
                return new Call2State(this);
7✔
641
            } else if (ch == 'H') {
3!
642
                return new Hessian2State(this);
×
643
            } else if (ch == 'r') {
3✔
644
                throw new IllegalStateException("unexpected 'r' in top2 state");
5✔
645
            } else if (ch == 'c') {
3!
646
                throw new IllegalStateException("unexpected 'c' in top2 state");
×
647
            } else {
648
                return nextObject(ch);
4✔
649
            }
650
        }
651
    }
652

653
    class IntegerState extends State {
654
        String typeCode;
655

656
        int length;
657
        int value;
658

659
        IntegerState(State next, String typeCode) {
3✔
660
            super(next);
4✔
661

662
            this.typeCode = typeCode;
3✔
663
        }
1✔
664

665
        IntegerState(State next, String typeCode, int value, int length) {
3✔
666
            super(next);
4✔
667

668
            this.typeCode = typeCode;
3✔
669

670
            this.value = value;
3✔
671
            this.length = length;
3✔
672
        }
1✔
673

674
        @Override
675
        State next(int ch) {
676
            value = 256 * value + (ch & 0xff);
10✔
677

678
            if (++length == 4) {
9✔
679
                Integer value = this.value;
4✔
680

681
                if (next.isShift(value)) {
5✔
682
                    return next.shift(value);
5✔
683
                } else {
684
                    printObject(value.toString());
4✔
685

686
                    return next;
3✔
687
                }
688
            } else {
689
                return this;
2✔
690
            }
691
        }
692
    }
693

694
    class LongState extends State {
695
        String typeCode;
696

697
        int length;
698
        long value;
699

700
        LongState(State next, String typeCode) {
3✔
701
            super(next);
4✔
702

703
            this.typeCode = typeCode;
3✔
704
        }
1✔
705

706
        LongState(State next, String typeCode, long value, int length) {
3✔
707
            super(next);
4✔
708

709
            this.typeCode = typeCode;
3✔
710

711
            this.value = value;
3✔
712
            this.length = length;
3✔
713
        }
1✔
714

715
        @Override
716
        State next(int ch) {
717
            value = 256 * value + (ch & 0xff);
11✔
718

719
            if (++length == 8) {
9✔
720
                Long value = this.value;
4✔
721

722
                if (next.isShift(value)) {
5!
723
                    return next.shift(value);
×
724
                } else {
725
                    printObject(value + "L");
4✔
726

727
                    return next;
3✔
728
                }
729
            } else {
730
                return this;
2✔
731
            }
732
        }
733
    }
734

735
    class DoubleIntegerState extends State {
736
        int length;
737
        int value;
738
        boolean isFirst = true;
3✔
739

740
        DoubleIntegerState(State next, int length) {
3✔
741
            super(next);
4✔
742

743
            this.length = length;
3✔
744
        }
1✔
745

746
        @Override
747
        State next(int ch) {
748
            if (isFirst) {
3✔
749
                value = (byte) ch;
5✔
750
            } else {
751
                value = 256 * value + (ch & 0xff);
10✔
752
            }
753

754
            isFirst = false;
3✔
755

756
            if (++length == 4) {
9✔
757
                Double value = (double) this.value;
5✔
758

759
                if (next.isShift(value)) {
5!
760
                    return next.shift(value);
×
761
                } else {
762
                    printObject(value.toString());
4✔
763

764
                    return next;
3✔
765
                }
766
            } else {
767
                return this;
2✔
768
            }
769
        }
770
    }
771

772
    class RefState extends State {
773
        String typeCode;
774

775
        int length;
776
        int value;
777

778
        RefState(State next) {
3✔
779
            super(next);
4✔
780
        }
1✔
781

782
        RefState(State next, String typeCode) {
×
783
            super(next);
×
784

785
            this.typeCode = typeCode;
×
786
        }
×
787

788
        RefState(State next, String typeCode, int value, int length) {
×
789
            super(next);
×
790

791
            this.typeCode = typeCode;
×
792

793
            this.value = value;
×
794
            this.length = length;
×
795
        }
×
796

797
        @Override
798
        boolean isShift(Object o) {
799
            return true;
2✔
800
        }
801

802
        @Override
803
        State shift(Object o) {
804
            println("ref #" + o);
5✔
805

806
            return next;
3✔
807
        }
808

809
        @Override
810
        State next(int ch) {
811
            return nextObject(ch);
4✔
812
        }
813
    }
814

815
    class DateState extends State {
816
        int length;
817
        long value;
818
        boolean isMinute;
819

820
        DateState(State next) {
3✔
821
            super(next);
4✔
822
        }
1✔
823

824
        DateState(State next, boolean isMinute) {
3✔
825
            super(next);
4✔
826

827
            length = 4;
3✔
828
            this.isMinute = isMinute;
3✔
829
        }
1✔
830

831
        @Override
832
        State next(int ch) {
833
            value = 256 * value + (ch & 0xff);
11✔
834

835
            if (++length == 8) {
9✔
836
                java.util.Date value;
837

838
                if (isMinute) {
3✔
839
                    value = new java.util.Date(this.value * 60000L);
9✔
840
                } else {
841
                    value = new java.util.Date(this.value);
6✔
842
                }
843

844
                if (next.isShift(value)) {
5!
845
                    return next.shift(value);
×
846
                } else {
847
                    printObject(value.toString());
4✔
848

849
                    return next;
3✔
850
                }
851
            } else {
852
                return this;
2✔
853
            }
854
        }
855
    }
856

857
    class DoubleState extends State {
858
        int length;
859
        long value;
860

861
        DoubleState(State next) {
3✔
862
            super(next);
4✔
863
        }
1✔
864

865
        @Override
866
        State next(int ch) {
867
            value = 256 * value + (ch & 0xff);
11✔
868

869
            if (++length == 8) {
9✔
870
                Double value = Double.longBitsToDouble(this.value);
5✔
871

872
                if (next.isShift(value)) {
5!
873
                    return next.shift(value);
×
874
                } else {
875
                    printObject(value.toString());
4✔
876

877
                    return next;
3✔
878
                }
879
            } else {
880
                return this;
2✔
881
            }
882
        }
883
    }
884

885
    class MillsState extends State {
886
        int length;
887
        int value;
888

889
        MillsState(State next) {
3✔
890
            super(next);
4✔
891
        }
1✔
892

893
        @Override
894
        State next(int ch) {
895
            value = 256 * value + (ch & 0xff);
10✔
896

897
            if (++length == 4) {
9✔
898
                Double value = 0.001 * this.value;
7✔
899

900
                if (next.isShift(value)) {
5!
901
                    return next.shift(value);
×
902
                } else {
903
                    printObject(value.toString());
4✔
904

905
                    return next;
3✔
906
                }
907
            } else {
908
                return this;
2✔
909
            }
910
        }
911
    }
912

913
    class StringState extends State {
914
        private static final int TOP = 0;
915
        private static final int UTF_2_1 = 1;
916
        private static final int UTF_3_1 = 2;
917
        private static final int UTF_3_2 = 3;
918

919
        char typeCode;
920

921
        StringBuilder value = new StringBuilder();
15✔
922
        int lengthIndex;
923
        int length;
924
        boolean isLastChunk;
925

926
        int utfState;
927
        char ch;
928

929
        StringState(State next, char typeCode, boolean isLastChunk) {
3✔
930
            super(next);
4✔
931

932
            this.typeCode = typeCode;
3✔
933
            this.isLastChunk = isLastChunk;
3✔
934
        }
1✔
935

936
        StringState(State next, char typeCode, int length) {
3✔
937
            super(next);
4✔
938

939
            this.typeCode = typeCode;
3✔
940
            isLastChunk = true;
3✔
941
            this.length = length;
3✔
942
            lengthIndex = 2;
3✔
943
        }
1✔
944

945
        StringState(State next, char typeCode, int length, boolean isLastChunk) {
3✔
946
            super(next);
4✔
947

948
            this.typeCode = typeCode;
3✔
949
            this.isLastChunk = isLastChunk;
3✔
950
            this.length = length;
3✔
951
            lengthIndex = 1;
3✔
952
        }
1✔
953

954
        @Override
955
        State next(int ch) {
956
            if (lengthIndex < 2) {
4✔
957
                length = 256 * length + (ch & 0xff);
10✔
958

959
                if (++lengthIndex == 2 && length == 0 && isLastChunk) {
12!
960
                    if (next.isShift(value.toString())) {
×
961
                        return next.shift(value.toString());
×
962
                    } else {
963
                        printObject("\"" + value + "\"");
×
964
                        return next;
×
965
                    }
966
                } else {
967
                    return this;
2✔
968
                }
969
            } else if (length == 0) {
3✔
970
                if (ch == 's' || ch == 'x') {
6!
971
                    isLastChunk = false;
×
972
                    lengthIndex = 0;
×
973
                    return this;
×
974
                } else if (ch == 'S' || ch == 'X') {
3!
975
                    isLastChunk = true;
3✔
976
                    lengthIndex = 0;
3✔
977
                    return this;
2✔
978
                } else if (ch == 0x00) {
×
979
                    if (next.isShift(value.toString())) {
×
980
                        return next.shift(value.toString());
×
981
                    } else {
982
                        printObject("\"" + value + "\"");
×
983
                        return next;
×
984
                    }
985
                } else if (0x00 <= ch && ch < 0x20) {
×
986
                    isLastChunk = true;
×
987
                    lengthIndex = 2;
×
988
                    length = ch & 0xff;
×
989
                    return this;
×
990
                } else if (0x30 <= ch && ch < 0x34) {
×
991
                    isLastChunk = true;
×
992
                    lengthIndex = 1;
×
993
                    length = (ch - 0x30);
×
994
                    return this;
×
995
                } else {
996
                    println(this + " " + (char) ch + ": unexpected character");
×
997
                    return next;
×
998
                }
999
            }
1000

1001
            switch (utfState) {
3!
1002
                case TOP:
1003
                    if (ch < 0x80) {
3✔
1004
                        length--;
6✔
1005

1006
                        value.append((char) ch);
7✔
1007
                    } else if (ch < 0xe0) {
3!
1008
                        this.ch = (char) ((ch & 0x1f) << 6);
×
1009
                        utfState = UTF_2_1;
×
1010
                    } else {
1011
                        this.ch = (char) ((ch & 0xf) << 12);
8✔
1012
                        utfState = UTF_3_1;
3✔
1013
                    }
1014
                    break;
1✔
1015

1016
                case UTF_2_1:
1017
                case UTF_3_2:
1018
                    this.ch += ch & 0x3f;
9✔
1019
                    value.append(this.ch);
6✔
1020
                    length--;
6✔
1021
                    utfState = TOP;
3✔
1022
                    break;
1✔
1023

1024
                case UTF_3_1:
1025
                    this.ch += (char) ((ch & 0x3f) << 6);
12✔
1026
                    utfState = UTF_3_2;
3✔
1027
                    break;
1✔
1028
                default:
1029
                    break;
1030
            }
1031

1032
            if (length == 0 && isLastChunk) {
6✔
1033
                if (next.isShift(value.toString())) {
7✔
1034
                    return next.shift(value.toString());
7✔
1035
                } else {
1036
                    printObject("\"" + value + "\"");
6✔
1037

1038
                    return next;
3✔
1039
                }
1040
            } else {
1041
                return this;
2✔
1042
            }
1043
        }
1044
    }
1045

1046
    class BinaryState extends State {
1047
        char typeCode;
1048

1049
        int totalLength;
1050

1051
        int lengthIndex;
1052
        int length;
1053
        boolean isLastChunk;
1054

1055
        BinaryState(State next, char typeCode, boolean isLastChunk) {
3✔
1056
            super(next);
4✔
1057

1058
            this.typeCode = typeCode;
3✔
1059
            this.isLastChunk = isLastChunk;
3✔
1060
        }
1✔
1061

1062
        BinaryState(State next, char typeCode, int length) {
3✔
1063
            super(next);
4✔
1064

1065
            this.typeCode = typeCode;
3✔
1066
            isLastChunk = true;
3✔
1067
            this.length = length;
3✔
1068
            lengthIndex = 2;
3✔
1069
        }
1✔
1070

1071
        BinaryState(State next, char typeCode, int length, boolean isLastChunk) {
3✔
1072
            super(next);
4✔
1073

1074
            this.typeCode = typeCode;
3✔
1075
            this.isLastChunk = isLastChunk;
3✔
1076
            this.length = length;
3✔
1077
            lengthIndex = 1;
3✔
1078
        }
1✔
1079

1080
        @Override
1081
        State next(int ch) {
1082
            if (lengthIndex < 2) {
4✔
1083
                length = 256 * length + (ch & 0xff);
10✔
1084

1085
                if (++lengthIndex == 2 && length == 0 && isLastChunk) {
12!
1086
                    String value = getBinaryValue();
×
1087

1088
                    if (next.isShift(value)) {
×
1089
                        return next.shift(value);
×
1090
                    } else {
1091
                        printObject(value);
×
1092
                        return next;
×
1093
                    }
1094
                } else {
1095
                    return this;
2✔
1096
                }
1097
            } else if (length == 0) {
3✔
1098
                if (ch == 'b' || ch == 'A') {
6!
1099
                    isLastChunk = false;
3✔
1100
                    lengthIndex = 0;
3✔
1101
                    return this;
2✔
1102
                } else if (ch == 'B') {
3✔
1103
                    isLastChunk = true;
3✔
1104
                    lengthIndex = 0;
3✔
1105
                    return this;
2✔
1106
                } else if (ch == 0x20) {
3!
1107
                    String value = getBinaryValue();
3✔
1108

1109
                    if (next.isShift(value)) {
5!
1110
                        return next.shift(value);
×
1111
                    } else {
1112
                        printObject(value);
3✔
1113
                        return next;
3✔
1114
                    }
1115
                } else if (0x20 <= ch && ch < 0x30) {
×
1116
                    isLastChunk = true;
×
1117
                    lengthIndex = 2;
×
1118
                    length = (ch & 0xff) - 0x20;
×
1119
                    return this;
×
1120
                } else {
1121
                    println(this + " 0x" + Integer.toHexString(ch) + " " + (char) ch + ": unexpected character");
×
1122
                    return next;
×
1123
                }
1124
            }
1125

1126
            length--;
6✔
1127
            totalLength++;
6✔
1128

1129
            if (length == 0 && isLastChunk) {
6✔
1130
                String value = getBinaryValue();
3✔
1131

1132
                if (next.isShift(value)) {
5!
1133
                    return next.shift(value);
×
1134
                } else {
1135
                    printObject(value);
3✔
1136

1137
                    return next;
3✔
1138
                }
1139
            } else {
1140
                return this;
2✔
1141
            }
1142
        }
1143

1144
        private String getBinaryValue() {
1145
            return "binary(" + totalLength + ")";
4✔
1146
        }
1147
    }
1148

1149
    class MapState extends State {
1150
        private static final int TYPE = 0;
1151
        private static final int KEY = 1;
1152
        private static final int VALUE = 2;
1153

1154
        private final int refId;
1155

1156
        private int state;
1157
        private int valueDepth;
1158
        private boolean hasData;
1159

1160
        MapState(State next, int refId) {
3✔
1161
            super(next);
4✔
1162

1163
            this.refId = refId;
3✔
1164
            state = TYPE;
3✔
1165
        }
1✔
1166

1167
        MapState(State next, int refId, boolean isType) {
3✔
1168
            super(next);
4✔
1169

1170
            this.refId = refId;
3✔
1171

1172
            if (isType) state = TYPE;
2!
1173
            else {
1174
                printObject("map (#" + this.refId + ")");
5✔
1175
                state = VALUE;
3✔
1176
            }
1177
        }
1✔
1178

1179
        @Override
1180
        boolean isShift(Object value) {
1181
            return state == TYPE;
7✔
1182
        }
1183

1184
        @Override
1185
        State shift(Object type) {
1186
            if (state == TYPE) {
3!
1187
                if (type instanceof String) {
3!
1188
                    typeDefList.add((String) type);
8✔
1189
                } else if (type instanceof Integer) {
×
1190
                    int iValue = (Integer) type;
×
1191

1192
                    if (iValue >= 0 && iValue < typeDefList.size()) type = typeDefList.get(iValue);
×
1193
                }
1194

1195
                printObject("map " + type + " (#" + refId + ")");
7✔
1196

1197
                state = VALUE;
3✔
1198

1199
                return this;
2✔
1200
            } else {
1201
                printObject(this + " unknown shift state= " + state + " type=" + type);
×
1202

1203
                return this;
×
1204
            }
1205
        }
1206

1207
        @Override
1208
        int depth() {
1209
            if (state == TYPE) {
3✔
1210
                return next.depth();
4✔
1211
            } else if (state == KEY) {
4✔
1212
                return next.depth() + 2;
6✔
1213
            } else {
1214
                return valueDepth;
3✔
1215
            }
1216
        }
1217

1218
        @Override
1219
        State next(int ch) {
1220
            switch (state) {
3!
1221
                case TYPE:
1222
                    return nextObject(ch);
4✔
1223

1224
                case VALUE:
1225
                    if (ch == 'Z') {
3✔
1226
                        if (hasData) {
3✔
1227
                            println();
2✔
1228
                        }
1229

1230
                        return next;
3✔
1231
                    } else {
1232
                        if (hasData) {
3✔
1233
                            println();
2✔
1234
                        }
1235

1236
                        hasData = true;
3✔
1237
                        state = KEY;
3✔
1238

1239
                        return nextObject(ch);
4✔
1240
                    }
1241

1242
                case KEY:
1243
                    print(" => ");
3✔
1244
                    isObject = false;
4✔
1245
                    valueDepth = column;
5✔
1246

1247
                    state = VALUE;
3✔
1248

1249
                    return nextObject(ch);
4✔
1250

1251
                default:
1252
                    throw new IllegalStateException();
×
1253
            }
1254
        }
1255
    }
1256

1257
    class ObjectDefState extends State {
1258
        private static final int STATE_TYPE = 1;
1259
        private static final int STATE_COUNT = 2;
1260
        private static final int STATE_FIELD = 3;
1261

1262
        private int state;
1263
        private int count;
1264

1265
        private final List<String> fields = new ArrayList<>();
5✔
1266

1267
        ObjectDefState(State next) {
3✔
1268
            super(next);
4✔
1269

1270
            state = STATE_TYPE;
3✔
1271
        }
1✔
1272

1273
        @Override
1274
        boolean isShift(Object value) {
1275
            return true;
2✔
1276
        }
1277

1278
        @Override
1279
        State shift(Object object) {
1280
            if (state == STATE_TYPE) {
4✔
1281
                String type = (String) object;
3✔
1282

1283
                print("/* defun " + type + " [");
4✔
1284

1285
                objectDefList.add(new ObjectDef(type, fields));
11✔
1286

1287
                state = STATE_COUNT;
3✔
1288
            } else if (state == STATE_COUNT) {
5✔
1289
                count = (Integer) object;
5✔
1290

1291
                state = STATE_FIELD;
4✔
1292
            } else if (state == STATE_FIELD) {
4!
1293
                String field = (String) object;
3✔
1294

1295
                count--;
6✔
1296

1297
                fields.add(field);
5✔
1298

1299
                if (fields.size() == 1) {
5✔
1300
                    print(field);
4✔
1301
                } else {
1302
                    print(", " + field);
4✔
1303
                }
1304
            } else {
1✔
1305
                throw new UnsupportedOperationException();
×
1306
            }
1307

1308
            return this;
2✔
1309
        }
1310

1311
        @Override
1312
        int depth() {
1313
            if (state <= STATE_TYPE) {
4✔
1314
                return next.depth();
4✔
1315
            } else {
1316
                return next.depth() + 2;
6✔
1317
            }
1318
        }
1319

1320
        @Override
1321
        State next(int ch) {
1322
            switch (state) {
3!
1323
                case STATE_TYPE:
1324

1325
                case STATE_COUNT:
1326
                    return nextObject(ch);
4✔
1327

1328
                case STATE_FIELD:
1329
                    if (count == 0) {
3✔
1330
                        println("] */");
3✔
1331
                        next.printIndent(0);
4✔
1332

1333
                        return next.nextObject(ch);
5✔
1334
                    } else {
1335
                        return nextObject(ch);
4✔
1336
                    }
1337

1338
                default:
1339
                    throw new IllegalStateException();
×
1340
            }
1341
        }
1342
    }
1343

1344
    class ObjectState extends State {
1345
        private static final int TYPE = 0;
1346
        private static final int FIELD = 1;
1347

1348
        private final int refId;
1349

1350
        private int state;
1351
        private ObjectDef def;
1352
        private int count;
1353
        private int fieldDepth;
1354

1355
        ObjectState(State next, int refId) {
×
1356
            super(next);
×
1357

1358
            this.refId = refId;
×
1359
            state = TYPE;
×
1360
        }
×
1361

1362
        ObjectState(State next, int refId, int def) {
3✔
1363
            super(next);
4✔
1364

1365
            this.refId = refId;
3✔
1366
            state = FIELD;
3✔
1367

1368
            if (def < 0 || objectDefList.size() <= def) {
7!
1369
                log.warning(this + " " + def + " is an unknown object type");
6✔
1370

1371
                println(this + " object unknown  (#" + this.refId + ")");
7✔
1372
            }
1373

1374
            this.def = objectDefList.get(def);
7✔
1375

1376
            if (isObject) {
3✔
1377
                println();
2✔
1378
            }
1379

1380
            println("object " + this.def.getType() + " (#" + this.refId + ")");
8✔
1381
        }
1✔
1382

1383
        @Override
1384
        boolean isShift(Object value) {
1385
            return state == TYPE;
5!
1386
        }
1387

1388
        @Override
1389
        State shift(Object object) {
1390
            if (state == TYPE) {
×
1391
                int def = (Integer) object;
×
1392

1393
                this.def = objectDefList.get(def);
×
1394

1395
                println("object " + this.def.getType() + " (#" + refId + ")");
×
1396

1397
                state = FIELD;
×
1398

1399
                if (this.def.getFields().isEmpty()) {
×
1400
                    return next;
×
1401
                }
1402
            }
1403

1404
            return this;
×
1405
        }
1406

1407
        @Override
1408
        int depth() {
1409
            if (state <= TYPE) {
3!
1410
                return next.depth();
×
1411
            } else {
1412
                return fieldDepth;
3✔
1413
            }
1414
        }
1415

1416
        @Override
1417
        State next(int ch) {
1418
            switch (state) {
3!
1419
                case TYPE:
1420
                    return nextObject(ch);
×
1421

1422
                case FIELD:
1423
                    if (def.getFields().size() <= count) {
7✔
1424
                        return next.next(ch);
5✔
1425
                    }
1426

1427
                    fieldDepth = next.depth() + 2;
7✔
1428
                    println();
2✔
1429
                    print(def.getFields().get(count++) + ": ");
15✔
1430

1431
                    fieldDepth = column;
5✔
1432

1433
                    isObject = false;
4✔
1434
                    return nextObject(ch);
4✔
1435

1436
                default:
1437
                    throw new IllegalStateException();
×
1438
            }
1439
        }
1440
    }
1441

1442
    class ListState extends State {
1443
        private static final int TYPE = 0;
1444
        private static final int LENGTH = 1;
1445
        private static final int VALUE = 2;
1446

1447
        private final int refId;
1448

1449
        private int state;
1450
        private int count;
1451
        private int valueDepth;
1452

1453
        ListState(State next, int refId, boolean isType) {
3✔
1454
            super(next);
4✔
1455

1456
            this.refId = refId;
3✔
1457

1458
            if (isType) {
2✔
1459
                state = TYPE;
4✔
1460
            } else {
1461
                printObject("list (#" + this.refId + ")");
5✔
1462
                state = VALUE;
3✔
1463
            }
1464
        }
1✔
1465

1466
        @Override
1467
        boolean isShift(Object value) {
1468
            return state == TYPE || state == LENGTH;
11!
1469
        }
1470

1471
        @Override
1472
        State shift(Object object) {
1473
            if (state == TYPE) {
3!
1474
                Object type = object;
2✔
1475

1476
                if (type instanceof String) {
3!
1477
                    typeDefList.add((String) type);
8✔
1478
                } else if (object instanceof Integer) {
×
1479
                    int index = (Integer) object;
×
1480

1481
                    if (index >= 0 && index < typeDefList.size()) {
×
1482
                        type = typeDefList.get(index);
×
1483
                    } else {
1484
                        type = "type-unknown(" + index + ")";
×
1485
                    }
1486
                }
1487

1488
                printObject("list " + type + "(#" + refId + ")");
7✔
1489

1490
                state = VALUE;
3✔
1491

1492
                return this;
2✔
1493
            } else if (state == LENGTH) {
×
1494
                state = VALUE;
×
1495

1496
                return this;
×
1497
            } else {
1498
                return this;
×
1499
            }
1500
        }
1501

1502
        @Override
1503
        int depth() {
1504
            if (state <= LENGTH) {
4✔
1505
                return next.depth();
4✔
1506
            } else if (state == VALUE) {
4!
1507
                return valueDepth;
3✔
1508
            } else {
1509
                return next.depth() + 2;
×
1510
            }
1511
        }
1512

1513
        @Override
1514
        State next(int ch) {
1515
            switch (state) {
3!
1516
                case TYPE:
1517
                    return nextObject(ch);
4✔
1518

1519
                case VALUE:
1520
                    if (ch == 'Z') {
3✔
1521
                        if (count > 0) {
3!
1522
                            println();
2✔
1523
                        }
1524

1525
                        return next;
3✔
1526
                    } else {
1527
                        valueDepth = next.depth() + 2;
7✔
1528
                        println();
2✔
1529
                        printObject(count++ + ": ");
10✔
1530
                        valueDepth = column;
5✔
1531
                        isObject = false;
4✔
1532

1533
                        return nextObject(ch);
4✔
1534
                    }
1535

1536
                default:
1537
                    throw new IllegalStateException();
×
1538
            }
1539
        }
1540
    }
1541

1542
    class CompactListState extends State {
1543
        private static final int STATE_TYPE = 0;
1544
        private static final int STATE_LENGTH = 1;
1545
        private static final int STATE_VALUE = 2;
1546

1547
        private final int refId;
1548

1549
        private final boolean isTyped;
1550
        private boolean isLength;
1551

1552
        private int state;
1553
        private int length;
1554
        private int count;
1555
        private int valueDepth;
1556

1557
        CompactListState(State next, int refId, boolean isTyped) {
3✔
1558
            super(next);
4✔
1559

1560
            this.isTyped = isTyped;
3✔
1561
            this.refId = refId;
3✔
1562

1563
            if (isTyped) {
2✔
1564
                state = STATE_TYPE;
4✔
1565
            } else {
1566
                state = STATE_LENGTH;
3✔
1567
            }
1568
        }
1✔
1569

1570
        CompactListState(State next, int refId, boolean isTyped, int length) {
3✔
1571
            super(next);
4✔
1572

1573
            this.isTyped = isTyped;
3✔
1574
            this.refId = refId;
3✔
1575
            this.length = length;
3✔
1576

1577
            isLength = true;
3✔
1578

1579
            if (isTyped) {
2✔
1580
                state = STATE_TYPE;
4✔
1581
            } else {
1582
                printObject("list (#" + this.refId + ")");
5✔
1583

1584
                state = STATE_VALUE;
3✔
1585
            }
1586
        }
1✔
1587

1588
        @Override
1589
        boolean isShift(Object value) {
1590
            return state == STATE_TYPE || state == STATE_LENGTH;
11✔
1591
        }
1592

1593
        @Override
1594
        State shift(Object object) {
1595
            if (state == STATE_TYPE) {
3✔
1596
                Object type = object;
2✔
1597

1598
                if (object instanceof Integer) {
3✔
1599
                    int index = (Integer) object;
4✔
1600

1601
                    if (index >= 0 && index < typeDefList.size()) {
8!
1602
                        type = typeDefList.get(index);
7✔
1603
                    } else {
1604
                        type = "type-unknown(" + index + ")";
×
1605
                    }
1606
                } else if (object instanceof String) {
4!
1607
                    typeDefList.add((String) object);
7✔
1608
                }
1609

1610
                printObject("list " + type + " (#" + refId + ")");
7✔
1611

1612
                if (isLength) {
3✔
1613
                    state = STATE_VALUE;
3✔
1614

1615
                    if (length == 0) {
3✔
1616
                        return next;
3✔
1617
                    }
1618
                } else {
1619
                    state = STATE_LENGTH;
3✔
1620
                }
1621

1622
                return this;
2✔
1623
            } else if (state == STATE_LENGTH) {
4!
1624
                length = (Integer) object;
5✔
1625

1626
                if (!isTyped) {
3!
1627
                    printObject("list (#" + refId + ")");
×
1628
                }
1629

1630
                state = STATE_VALUE;
3✔
1631

1632
                if (length == 0) {
3!
1633
                    return next;
×
1634
                } else {
1635
                    return this;
2✔
1636
                }
1637
            } else {
1638
                return this;
×
1639
            }
1640
        }
1641

1642
        @Override
1643
        int depth() {
1644
            if (state <= STATE_LENGTH) {
4✔
1645
                return next.depth();
4✔
1646
            } else if (state == STATE_VALUE) {
4!
1647
                return valueDepth;
3✔
1648
            } else {
1649
                return next.depth() + 2;
×
1650
            }
1651
        }
1652

1653
        @Override
1654
        State next(int ch) {
1655
            switch (state) {
3!
1656
                case STATE_TYPE:
1657

1658
                case STATE_LENGTH:
1659
                    return nextObject(ch);
4✔
1660

1661
                case STATE_VALUE:
1662
                    if (length <= count) {
5✔
1663
                        return next.next(ch);
5✔
1664
                    } else {
1665
                        valueDepth = next.depth() + 2;
7✔
1666
                        println();
2✔
1667
                        printObject(count++ + ": ");
10✔
1668
                        valueDepth = column;
5✔
1669
                        isObject = false;
4✔
1670

1671
                        return nextObject(ch);
4✔
1672
                    }
1673

1674
                default:
1675
                    throw new IllegalStateException();
×
1676
            }
1677
        }
1678
    }
1679

1680
    class Hessian2State extends State {
1681
        private static final int STATE_MAJOR = 0;
1682
        private static final int STATE_MINOR = 1;
1683

1684
        private int state;
1685
        private int major;
1686
        private int minor;
1687

1688
        Hessian2State(State next) {
×
1689
            super(next);
×
1690
        }
×
1691

1692
        @Override
1693
        int depth() {
1694
            return next.depth() + 2;
×
1695
        }
1696

1697
        @Override
1698
        State next(int ch) {
1699
            switch (state) {
×
1700
                case STATE_MAJOR:
1701
                    major = ch;
×
1702
                    state = STATE_MINOR;
×
1703
                    return this;
×
1704

1705
                case STATE_MINOR:
1706
                    minor = ch;
×
1707
                    println(-2, "Hessian " + major + "." + minor);
×
1708
                    return next;
×
1709

1710
                default:
1711
                    throw new IllegalStateException();
×
1712
            }
1713
        }
1714
    }
1715

1716
    class Call2State extends State {
1717
        private static final int STATE_METHOD = 0;
1718
        private static final int STATE_COUNT = 1;
1719
        private static final int STATE_ARG = 2;
1720

1721
        private int state = STATE_METHOD;
3✔
1722
        private int i;
1723
        private int count;
1724

1725
        Call2State(State next) {
3✔
1726
            super(next);
4✔
1727
        }
1✔
1728

1729
        @Override
1730
        int depth() {
1731
            return next.depth() + 5;
6✔
1732
        }
1733

1734
        @Override
1735
        boolean isShift(Object value) {
1736
            return state != STATE_ARG;
8✔
1737
        }
1738

1739
        @Override
1740
        State shift(Object object) {
1741
            if (state == STATE_METHOD) {
3✔
1742
                println(-5, "Call " + object);
6✔
1743

1744
                state = STATE_COUNT;
3✔
1745
                return this;
2✔
1746
            } else if (state == STATE_COUNT) {
4!
1747

1748
                this.count = (Integer) object;
5✔
1749

1750
                state = STATE_ARG;
3✔
1751

1752
                if (this.count == 0) {
3!
1753
                    return next;
×
1754
                } else {
1755
                    return this;
2✔
1756
                }
1757
            } else {
1758
                return this;
×
1759
            }
1760
        }
1761

1762
        @Override
1763
        State next(int ch) {
1764
            switch (state) {
3!
1765
                case STATE_COUNT:
1766

1767
                case STATE_METHOD:
1768
                    return nextObject(ch);
4✔
1769

1770
                case STATE_ARG:
1771
                    if (count <= i) {
5✔
1772
                        println();
2✔
1773
                        return next.next(ch);
5✔
1774
                    } else {
1775
                        println();
2✔
1776
                        print(-3, i++ + ": ");
11✔
1777

1778
                        return nextObject(ch);
4✔
1779
                    }
1780

1781
                default:
1782
                    throw new IllegalStateException();
×
1783
            }
1784
        }
1785
    }
1786

1787
    class Reply2State extends State {
1788
        Reply2State(State next) {
×
1789
            super(next);
×
1790

1791
            println(-2, "Reply");
×
1792
        }
×
1793

1794
        @Override
1795
        int depth() {
1796
            return next.depth() + 2;
×
1797
        }
1798

1799
        @Override
1800
        State next(int ch) {
1801
            if (ch < 0) {
×
1802
                println();
×
1803
                return next;
×
1804
            } else {
1805
                return nextObject(ch);
×
1806
            }
1807
        }
1808
    }
1809

1810
    class Fault2State extends State {
1811
        Fault2State(State next) {
3✔
1812
            super(next);
4✔
1813

1814
            println(-2, "Fault");
4✔
1815
        }
1✔
1816

1817
        @Override
1818
        int depth() {
1819
            return next.depth() + 2;
6✔
1820
        }
1821

1822
        @Override
1823
        State next(int ch) {
1824
            return nextObject(ch);
4✔
1825
        }
1826
    }
1827

1828
    class StreamingState extends State {
1829
        private long length;
1830
        private int metaLength;
1831
        private boolean isLast;
1832
        private boolean isFirst = true;
3✔
1833

1834
        private boolean isLengthState;
1835

1836
        private State childState;
1837

1838
        StreamingState(State next, boolean isLast) {
3✔
1839
            super(next);
4✔
1840

1841
            this.isLast = isLast;
3✔
1842
            childState = new InitialState();
6✔
1843
        }
1✔
1844

1845
        @Override
1846
        State next(int ch) {
1847
            if (metaLength > 0) {
3!
1848
                length = 256 * length + ch;
×
1849
                metaLength--;
×
1850

1851
                if (metaLength == 0 && isFirst) {
×
1852
                    if (isLast) {
×
1853
                        println(-1, "--- packet-start(" + length + ")");
×
1854
                    } else {
1855
                        println(-1, "--- packet-start(fragment)");
×
1856
                    }
1857
                    isFirst = false;
×
1858
                }
1859

1860
                return this;
×
1861
            }
1862

1863
            if (length > 0) {
5✔
1864
                length--;
6✔
1865
                childState = childState.next(ch);
6✔
1866

1867
                return this;
2✔
1868
            }
1869

1870
            if (!isLengthState) {
3✔
1871
                isLengthState = true;
3✔
1872

1873
                if (isLast) {
3!
1874
                    println(-1, "");
×
1875
                    println(-1, "--- packet-end");
×
1876
                    refId = 0;
×
1877

1878
                    isFirst = true;
×
1879
                }
1880

1881
                isLast = (ch & 0x80) == 0x00;
8!
1882
                isLengthState = true;
4✔
1883
            } else {
1884
                isLengthState = false;
3✔
1885
                length = (ch & 0x7f);
6✔
1886

1887
                if (length == 0x7e) {
5!
1888
                    length = 0;
×
1889
                    metaLength = 2;
×
1890
                } else if (length == 0x7f) {
5!
1891
                    length = 0;
×
1892
                    metaLength = 8;
×
1893
                } else {
1894
                    if (isFirst) {
3!
1895
                        if (isLast) {
3!
1896
                            println(-1, "--- packet-start(" + length + ")");
7✔
1897
                        } else {
1898
                            println(-1, "--- packet-start(fragment)");
×
1899
                        }
1900
                        isFirst = false;
3✔
1901
                    }
1902
                }
1903
            }
1904

1905
            return this;
2✔
1906
        }
1907
    }
1908

1909
    static class ObjectDef {
1910
        private final String type;
1911
        private final List<String> fields;
1912

1913
        ObjectDef(String type, List<String> fields) {
2✔
1914
            this.type = type;
3✔
1915
            this.fields = fields;
3✔
1916
        }
1✔
1917

1918
        String getType() {
1919
            return type;
3✔
1920
        }
1921

1922
        List<String> getFields() {
1923
            return fields;
3✔
1924
        }
1925
    }
1926
}
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