1 package net.sf.mbus4j.decoder;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 import java.util.Arrays;
31 import java.util.logging.Level;
32 import java.util.logging.Logger;
33 import net.sf.mbus4j.NotSupportedException;
34 import net.sf.mbus4j.dataframes.LongFrame;
35 import net.sf.mbus4j.dataframes.MBusMedium;
36 import net.sf.mbus4j.dataframes.datablocks.ByteDataBlock;
37 import net.sf.mbus4j.dataframes.datablocks.DataBlock;
38 import net.sf.mbus4j.dataframes.datablocks.DateAndTimeDataBlock;
39 import net.sf.mbus4j.dataframes.datablocks.DateDataBlock;
40 import net.sf.mbus4j.dataframes.datablocks.EnhancedIdentificationDataBlock;
41 import net.sf.mbus4j.dataframes.datablocks.IntegerDataBlock;
42 import net.sf.mbus4j.dataframes.datablocks.LongDataBlock;
43 import net.sf.mbus4j.dataframes.datablocks.RawDataBlock;
44 import net.sf.mbus4j.dataframes.datablocks.RealDataBlock;
45 import net.sf.mbus4j.dataframes.datablocks.ShortDataBlock;
46 import net.sf.mbus4j.dataframes.datablocks.StringDataBlock;
47 import net.sf.mbus4j.dataframes.datablocks.dif.DataFieldCode;
48 import net.sf.mbus4j.dataframes.datablocks.dif.FunctionField;
49 import net.sf.mbus4j.dataframes.datablocks.dif.VariableLengthType;
50 import net.sf.mbus4j.dataframes.datablocks.vif.ObjectAction;
51 import net.sf.mbus4j.dataframes.datablocks.vif.Vif;
52 import net.sf.mbus4j.dataframes.datablocks.vif.VifAscii;
53 import net.sf.mbus4j.dataframes.datablocks.vif.VifFB;
54 import net.sf.mbus4j.dataframes.datablocks.vif.VifFC;
55 import net.sf.mbus4j.dataframes.datablocks.vif.VifeFC;
56 import net.sf.mbus4j.dataframes.datablocks.vif.VifFD;
57 import net.sf.mbus4j.dataframes.datablocks.vif.VifManufacturerSpecific;
58 import net.sf.mbus4j.dataframes.datablocks.vif.VifPrimary;
59 import net.sf.mbus4j.dataframes.datablocks.vif.Vife;
60 import net.sf.mbus4j.dataframes.datablocks.vif.VifeError;
61 import net.sf.mbus4j.dataframes.datablocks.vif.VifeManufacturerSpecific;
62 import net.sf.mbus4j.dataframes.datablocks.vif.VifePrimary;
63 import net.sf.mbus4j.log.LogUtils;
64
65
66
67
68
69
70 public class VariableDataBlockDecoder {
71
72 private void createDataBlock() {
73 try {
74 db = DataBlock.getDataBlockClass(vif, vifes, dfc, variableLengthType).newInstance();
75 } catch (IllegalAccessException | InstantiationException ex) {
76 throw new RuntimeException(ex);
77 }
78 db.setVif(vif);
79 db.setDataFieldCode(dfc);
80 if (vifes == null) {
81 db.clearVifes();
82 } else {
83 for (Vife vife : vifes) {
84 db.addVife(vife);
85 }
86 }
87 db.setStorageNumber(storageNumber);
88 db.setTariff(tariff);
89 db.setSubUnit(subUnit);
90 db.setFunctionField(functionField);
91 db.setAction(objectAction);
92 }
93
94 public enum DecodeState {
95
96 WAIT_FOR_INIT,
97 DIF,
98 DIFE,
99 VIF,
100 VIF_FB,
101 VIF_FC,
102 VIF_FD,
103 VIFE,
104 MAN_SPEC_VIFE,
105 VIFE_FC,
106 ASCII_VIF_LENGTH,
107 ASCII_VIF_COLLECT,
108 SET_VARIABLE_LENGTH,
109 COLLECTING_VALUE,
110 ERROR,
111 RESULT_AVAIL;
112 }
113 private final static Logger LOG = LogUtils.getDecoderLogger();
114 private DecodeState ds = DecodeState.WAIT_FOR_INIT;
115 private int difePos;
116 private ObjectAction objectAction;
117 private DataFieldCode dfc;
118 private VariableLengthType variableLengthType;
119 private FunctionField functionField;
120 private long storageNumber;
121 private int tariff;
122 private short subUnit;
123 private Vif vif;
124 private Vife[] vifes;
125 private DataBlock db;
126 private LongFrame frame;
127 private final Stack stack = new Stack();
128
129 public VariableDataBlockDecoder() {
130 super();
131 }
132
133 public DecodeState addByte(final byte b, final int bytesLeft) {
134 switch (ds) {
135 case DIF:
136 decodeDif(b, bytesLeft);
137 difePos = 0;
138 return ds;
139 case DIFE:
140 decodeDIFE(b, difePos++);
141 return ds;
142 case VIF:
143 decodeVIF(b);
144 break;
145 case ASCII_VIF_LENGTH:
146 stack.init(b & 0xFF);
147 setState(DecodeState.ASCII_VIF_COLLECT);
148 return ds;
149 case ASCII_VIF_COLLECT:
150 stack.push(b);
151
152 if (stack.isFull()) {
153 ((VifAscii) vif).setValue(stack.popString());
154 startCollectingValue();
155 }
156 return ds;
157 case VIF_FB:
158 decodeVifExtention_FB(b);
159 return ds;
160 case VIF_FC:
161 decodeVifExtention_FC(b);
162 return ds;
163 case VIF_FD:
164 decodeVifExtention_FD(b);
165 return ds;
166 case VIFE:
167 decodeVife(b);
168 return ds;
169 case MAN_SPEC_VIFE:
170 decodeManSpecVife(b);
171 return ds;
172 case VIFE_FC:
173 decodeVifeExtension_FC(b);
174 return ds;
175 case COLLECTING_VALUE:
176 stack.push(b);
177 if (stack.isFull()) {
178 decodeValueFromStack();
179 }
180 return ds;
181 case SET_VARIABLE_LENGTH:
182 if ((b & 0xFF) < 0xBF) {
183 variableLengthType = VariableLengthType.STRING;
184 startCollectingValue((b & 0xFF));
185 } else if ((b & 0xFF) < 0xCF) {
186 variableLengthType = VariableLengthType.BIG_DECIMAL;
187 startCollectingValue((b & 0xFF) - 0xC0);
188 } else if ((b & 0xFF) < 0xDF) {
189 variableLengthType = VariableLengthType.BIG_DECIMAL;
190 startCollectingValue((b & 0xFF) - 0xD0);
191 } else if ((b & 0xFF) < 0xEF) {
192 throw new DecodeException("binary number ???? how to decode");
193 } else if ((b & 0xFF) < 0xFA) {
194 throw new DecodeException("floating point to be defined");
195 } else {
196 throw new DecodeException(String.format("reserved: 0x%02x ", b & 0xFF));
197 }
198 return ds;
199 default:
200 LOG.log(Level.SEVERE, "Unknown state: {0}", ds);
201 setState(DecodeState.ERROR);
202 }
203 return ds;
204 }
205
206 public void reset() {
207 stack.clear();
208 setState(DecodeState.WAIT_FOR_INIT);
209 }
210
211 private void decodeDif(final byte b, int bytesLeft) {
212 switch (b & 0xFF) {
213 case 0x0F:
214 dfc = DataFieldCode.SPECIAL_FUNCTION_MAN_SPEC_DATA_LAST_PACKET;
215 if (bytesLeft == 0) {
216 createDataBlock();
217 setState(DecodeState.RESULT_AVAIL);
218 } else {
219 startCollectingValue(bytesLeft);
220 }
221 return;
222 case 0x1F:
223 dfc = DataFieldCode.SPECIAL_FUNCTION_MAN_SPEC_DATA_PACKETS_FOLLOWS;
224 if (bytesLeft == 0) {
225 createDataBlock();
226 setState(DecodeState.RESULT_AVAIL);
227 } else {
228 startCollectingValue(bytesLeft);
229 }
230 return;
231 case 0x2F:
232
233 return;
234 case 0x3F:
235 case 0x4F:
236 case 0x5F:
237 case 0x6F:
238 setState(DecodeState.ERROR);
239 throw new DecodeException(String.format("DIF reserved 0x%02x ", b & 0xFF));
240 case 0x7F:
241 dfc = DataFieldCode.SPECIAL_FUNCTION_GLOBAL_READOUT_REQUEST;
242 break;
243 default:
244
245
246 switch (b & 0x0F) {
247 case 0x00:
248 dfc = DataFieldCode.NO_DATA;
249 break;
250 case 0x01:
251 dfc = DataFieldCode._8_BIT_INTEGER;
252 break;
253 case 0x02:
254 dfc = DataFieldCode._16_BIT_INTEGER;
255 break;
256 case 0x03:
257 dfc = DataFieldCode._24_BIT_INTEGER;
258 break;
259 case 0x04:
260 dfc = DataFieldCode._32_BIT_INTEGER;
261 break;
262 case 0x05:
263 dfc = DataFieldCode._32_BIT_REAL;
264 break;
265 case 0x06:
266 dfc = DataFieldCode._48_BIT_INTEGER;
267 break;
268 case 0x07:
269 dfc = DataFieldCode._64_BIT_INTEGER;
270 break;
271 case 0x08:
272 dfc = DataFieldCode.SELECTION_FOR_READOUT;
273 break;
274 case 0x09:
275 dfc = DataFieldCode._2_DIGIT_BCD;
276 break;
277 case 0x0A:
278 dfc = DataFieldCode._4_DIGIT_BCD;
279 break;
280 case 0x0B:
281 dfc = DataFieldCode._6_DIGIT_BCD;
282 break;
283 case 0x0C:
284 dfc = DataFieldCode._8_DIGIT_BCD;
285 break;
286 case 0x0D:
287 dfc = DataFieldCode.VARIABLE_LENGTH;
288 break;
289 case 0x0E:
290 dfc = DataFieldCode._12_DIGIT_BCD;
291 break;
292 case 0x0F:
293 setState(DecodeState.ERROR);
294 throw new NotSupportedException("data field 0x0f not supported");
295 default:
296 setState(DecodeState.ERROR);
297 throw new NotSupportedException(String.format("data field of DIF 0x%02x not supported", b & 0xFF));
298 }
299
300
301 switch (b & 0x30) {
302 case 0x00:
303 functionField = FunctionField.INSTANTANEOUS_VALUE;
304 break;
305 case 0x10:
306 functionField = FunctionField.MAXIMUM_VALUE;
307 break;
308 case 0x20:
309 functionField = FunctionField.MINIMUM_VALUE;
310 break;
311 case 0x30:
312 functionField = FunctionField.VALUE_DURING_ERROR_STATE;
313 break;
314 default:
315 throw new NotSupportedException("Function field");
316 }
317 }
318
319 storageNumber = (b >> 6) & 0x01;
320
321 if ((b & Decoder.EXTENTION_BIT) == Decoder.EXTENTION_BIT) {
322 setState(DecodeState.DIFE);
323 } else if (bytesLeft == 0) {
324 createDataBlock();
325 setState(DecodeState.RESULT_AVAIL);
326 } else {
327 setState(DecodeState.VIF);
328 }
329 }
330
331 private void decodeDIFE(final byte b, int dFIEIndex) {
332 storageNumber |= (long) (b & 0x0F) << (1 + (dFIEIndex * 4));
333 tariff |= ((b >> 4) & 0x03) << (dFIEIndex * 2);
334 subUnit |= (short) (((b >> 6) & 0x01) << dFIEIndex);
335
336 if ((b & Decoder.EXTENTION_BIT) != Decoder.EXTENTION_BIT) {
337 setState(DecodeState.VIF);
338 }
339 }
340
341 private void decodeEnhancedIdentificationDataBlock(EnhancedIdentificationDataBlock db) {
342 db.setMedium(MBusMedium.valueOf(stack.popByte()));
343 db.setVersion(stack.popByte());
344 db.setMan(stack.popMan());
345 db.setId(stack.popBcdInteger(8));
346 }
347
348 private void decodeValueFromStack() {
349 createDataBlock();
350 switch (dfc) {
351 case NO_DATA:
352 break;
353
354 case _8_BIT_INTEGER:
355 ((ByteDataBlock) db).setValue(stack.popByte());
356
357 break;
358
359 case _2_DIGIT_BCD:
360 ((ByteDataBlock) db).setBcdError(stack.peekBcdError(2));
361
362 if (((ByteDataBlock) db).getBcdError() != null) {
363 stack.popBcdByte();
364 } else {
365 ((ByteDataBlock) db).setValue(stack.popBcdByte());
366 }
367
368 break;
369
370 case _16_BIT_INTEGER:
371
372 if (db instanceof DateDataBlock) {
373 ((DateDataBlock) db).setValue(stack.popDate());
374 } else {
375 ((ShortDataBlock) db).setValue(stack.popShort());
376 }
377
378 break;
379
380 case _4_DIGIT_BCD:
381 ((ShortDataBlock) db).setBcdError(stack.peekBcdError(4));
382
383 if (((ShortDataBlock) db).getBcdError() != null) {
384 stack.popBcdShort(4);
385 } else {
386 ((ShortDataBlock) db).setValue(stack.popBcdShort(4));
387 }
388
389 break;
390
391 case _24_BIT_INTEGER:
392 ((IntegerDataBlock) db).setValue(stack.popInteger(3));
393
394 break;
395
396 case _6_DIGIT_BCD:
397 ((IntegerDataBlock) db).setBcdError(stack.peekBcdError(6));
398
399 if (((IntegerDataBlock) db).getBcdError() != null) {
400 stack.popBcdInteger(6);
401 } else {
402 ((IntegerDataBlock) db).setValue(stack.popBcdInteger(6));
403 }
404
405 break;
406
407 case _32_BIT_INTEGER:
408
409 if (db instanceof DateAndTimeDataBlock) {
410 DateAndTimeDataBlock d = ((DateAndTimeDataBlock) db);
411 d.setValid(stack.peekIsTimestampValid());
412 d.setSummerTime(stack.peekIsTimestampSummertime());
413 d.setRes1(stack.peekIsTimestampRes1());
414 d.setRes2(stack.peekIsTimestampRes2());
415 d.setRes3(stack.peekIsTimestampRes3());
416 d.setValue(stack.popTimeStamp());
417 } else {
418 ((IntegerDataBlock) db).setValue(stack.popInteger());
419 }
420
421 break;
422
423 case _8_DIGIT_BCD:
424
425 if (db instanceof EnhancedIdentificationDataBlock) {
426 ((EnhancedIdentificationDataBlock) db).setId(stack.popBcdInteger(8));
427 } else {
428 ((IntegerDataBlock) db).setBcdError(stack.peekBcdError(8));
429
430 if (((IntegerDataBlock) db).getBcdError() != null) {
431 stack.popBcdInteger(8);
432 } else {
433 ((IntegerDataBlock) db).setValue(stack.popBcdInteger(8));
434 }
435 }
436
437 break;
438
439 case _32_BIT_REAL:
440 ((RealDataBlock) db).setValue(stack.popFloat());
441
442 break;
443
444 case _48_BIT_INTEGER:
445 ((LongDataBlock) db).setValue(stack.popLong(6));
446
447 break;
448
449 case _12_DIGIT_BCD:
450 ((LongDataBlock) db).setBcdError(stack.peekBcdError(12));
451
452 if (((LongDataBlock) db).getBcdError() != null) {
453 stack.popBcdInteger(12);
454 } else {
455 ((LongDataBlock) db).setValue(stack.popBcdLong(12));
456 }
457
458 break;
459
460 case _64_BIT_INTEGER:
461
462 if (db instanceof EnhancedIdentificationDataBlock) {
463 decodeEnhancedIdentificationDataBlock((EnhancedIdentificationDataBlock) db);
464 } else {
465 ((LongDataBlock) db).setValue(stack.popLong());
466 }
467
468 break;
469
470 case VARIABLE_LENGTH:
471
472 if (db instanceof RawDataBlock) {
473 ((RawDataBlock) db).setValue(stack.popBytes());
474 } else if (db instanceof StringDataBlock) {
475 ((StringDataBlock) db).setValue(stack.popString());
476 } else {
477
478 throw new RuntimeException("decode variable lenght " + db.getClass().getName());
479 }
480
481 break;
482
483 case SPECIAL_FUNCTION_MAN_SPEC_DATA_LAST_PACKET:
484 case SPECIAL_FUNCTION_MAN_SPEC_DATA_PACKETS_FOLLOWS:
485 ((RawDataBlock) db).setValue(stack.popBytes());
486
487 break;
488
489 default:
490 throw new RuntimeException("decode data value" + db.getDataFieldCode());
491 }
492
493 stack.clear();
494 setState(DecodeState.RESULT_AVAIL);
495 }
496
497
498
499
500
501
502
503 private void decodeVIF(final byte b) {
504 switch (b & 0xFF) {
505 case 0x7C:
506
507 stack.clear();
508 vif = new VifAscii();
509 setState(DecodeState.ASCII_VIF_LENGTH);
510 return;
511
512 case 0x7E:
513 vif = VifPrimary.READOUT_SELECTION;
514 break;
515
516 case 0x7F:
517 vif = new VifManufacturerSpecific();
518 break;
519
520 case 0xFB:
521
522 setState(DecodeState.VIF_FB);
523 return;
524
525 case 0xFC:
526 setState(DecodeState.VIF_FC);
527 return;
528
529 case 0xFD:
530
531 setState(DecodeState.VIF_FD);
532 return;
533
534 case 0xFF:
535 vif = new VifManufacturerSpecific();
536 setState(DecodeState.MAN_SPEC_VIFE);
537 return;
538
539 default:
540 vif = VifPrimary.valueOfTableIndex((byte) (b & ~Decoder.EXTENTION_BIT));
541
542 }
543
544 goFromVifOrVife(b);
545 }
546
547 private void decodeManSpecVife(final byte b) {
548
549 switch (frame.getControlCode()) {
550 case RSP_UD:
551 Vife vife = new VifeManufacturerSpecific(b);
552
553 if (vifes == null) {
554 vifes = new Vife[1];
555 } else {
556 vifes = Arrays.copyOf(vifes, vifes.length + 1);
557 }
558 vifes[vifes.length - 1] = vife;
559
560 break;
561
562 case SND_UD:
563 objectAction = ObjectAction.valueOf(b);
564
565 break;
566
567 default:
568 setState(DecodeState.ERROR);
569 throw new NotSupportedException(String.format(
570 "Dont know how to handele Control code %s ",
571 frame.getControlCode()));
572 }
573
574 goFromVifOrVifeManSpec(b);
575 }
576
577 private void decodeVife(final byte b) {
578
579 switch (frame.getControlCode()) {
580 case RSP_UD:
581 if (0xFC == (b & 0xFF)) {
582 setState(DecodeState.VIFE_FC);
583 return;
584 }
585 Vife vife;
586
587 if ((b & ~Decoder.EXTENTION_BIT) > VifePrimary.CODE_OFFSET) {
588 vife = VifePrimary.valueOfTableIndex((byte) (b & ~Decoder.EXTENTION_BIT));
589 } else {
590 vife = VifeError.valueOfTableIndex((byte) (b & ~Decoder.EXTENTION_BIT));
591 }
592
593 if (vifes == null) {
594 vifes = new Vife[1];
595 } else {
596 vifes = Arrays.copyOf(vifes, vifes.length + 1);
597 }
598
599 vifes[vifes.length - 1] = vife;
600
601 if (vife == VifePrimary.MAN_SPEC) {
602 goFromVifOrVifeManSpec(b);
603 } else {
604 goFromVifOrVife(b);
605 }
606
607 break;
608
609 case SND_UD:
610 objectAction = ObjectAction.valueOf(b);
611 goFromVifOrVife(b);
612
613 break;
614
615 default:
616 setState(DecodeState.ERROR);
617 throw new NotSupportedException(String.format(
618 "Dont know how to handele Control code %s ",
619 frame.getControlCode()));
620 }
621
622 }
623
624 private void decodeVifeExtension_FC(final byte b) {
625
626 switch (frame.getControlCode()) {
627 case RSP_UD:
628 VifeFC vifeFC = VifeFC.valueOfTableIndex((byte) (b & ~Decoder.EXTENTION_BIT));
629
630 if (vifes == null) {
631 vifes = new Vife[1];
632 } else {
633 vifes = Arrays.copyOf(vifes, vifes.length + 1);
634 }
635 vifes[vifes.length - 1] = vifeFC;
636
637 break;
638
639 case SND_UD:
640 objectAction = ObjectAction.valueOf(b);
641
642 break;
643
644 default:
645 setState(DecodeState.ERROR);
646 throw new NotSupportedException(String.format(
647 "Dont know how to handele Control code %s ",
648 frame.getControlCode()));
649 }
650
651 goFromVifOrVife(b);
652 }
653
654 private void decodeVifExtention_FB(final byte b) {
655
656 vif = VifFB.valueOfTableIndex((byte) (b & ~Decoder.EXTENTION_BIT));
657 goFromVifOrVife(b);
658 }
659
660 private void decodeVifExtention_FC(final byte b) {
661
662 vif = VifFC.valueOfTableIndex((byte) (b & ~Decoder.EXTENTION_BIT));
663 goFromVifOrVife(b);
664 }
665
666 private void decodeVifExtention_FD(final byte b) {
667
668 vif = VifFD.valueOfTableIndex((byte) (b & ~Decoder.EXTENTION_BIT));
669 goFromVifOrVife(b);
670 }
671
672 public DataBlock getDataBlock() {
673 return db;
674 }
675
676 public DecodeState getState() {
677 return ds;
678 }
679
680 private void goFromVifOrVifeManSpec(final byte b) {
681 if ((b & Decoder.EXTENTION_BIT) == Decoder.EXTENTION_BIT) {
682 setState(DecodeState.MAN_SPEC_VIFE);
683 } else if ((dfc == DataFieldCode.SELECTION_FOR_READOUT) || (dfc == DataFieldCode.SPECIAL_FUNCTION_GLOBAL_READOUT_REQUEST)) {
684 createDataBlock();
685 setState(DecodeState.RESULT_AVAIL);
686 } else {
687 startCollectingValue();
688 }
689 }
690
691 private void goFromVifOrVife(final byte b) {
692 if ((b & Decoder.EXTENTION_BIT) == Decoder.EXTENTION_BIT) {
693 setState(DecodeState.VIFE);
694 } else if ((dfc == DataFieldCode.SELECTION_FOR_READOUT) || (dfc == DataFieldCode.SPECIAL_FUNCTION_GLOBAL_READOUT_REQUEST)) {
695 createDataBlock();
696 setState(DecodeState.RESULT_AVAIL);
697 } else {
698 startCollectingValue();
699 }
700 }
701
702 public void init(LongFrame frame) {
703
704 functionField = null;
705 storageNumber = 0;
706 dfc = null;
707 variableLengthType = null;
708 objectAction = null;
709 tariff = 0;
710 subUnit = 0;
711 vif = null;
712 vifes = null;
713 db = null;
714
715 setState(DecodeState.DIF);
716 this.frame = frame;
717 stack.clear();
718 }
719
720 public void setState(DecodeState ds) {
721 if ((ds == DecodeState.RESULT_AVAIL) && (db == null)) {
722 throw new RuntimeException("DB IST NULL");
723 }
724
725 final DecodeState oldState = this.ds;
726 this.ds = ds;
727
728 LOG.log(Level.FINEST, "{0} => {1}", new Object[]{oldState, ds});
729 }
730
731 private void startCollectingValue() {
732 switch (dfc) {
733 case NO_DATA:
734 stack.clear();
735 createDataBlock();
736 setState(DecodeState.RESULT_AVAIL);
737
738 return;
739
740 case _8_BIT_INTEGER:
741 case _2_DIGIT_BCD:
742 stack.init(1);
743
744 break;
745
746 case _16_BIT_INTEGER:
747 case _4_DIGIT_BCD:
748 stack.init(2);
749
750 break;
751
752 case _24_BIT_INTEGER:
753 case _6_DIGIT_BCD:
754 stack.init(3);
755
756 break;
757
758 case _32_BIT_INTEGER:
759 case _8_DIGIT_BCD:
760 case _32_BIT_REAL:
761 stack.init(4);
762
763 break;
764
765 case _48_BIT_INTEGER:
766 case _12_DIGIT_BCD:
767 stack.init(6);
768
769 break;
770
771 case _64_BIT_INTEGER:
772 stack.init(8);
773
774 break;
775
776 case VARIABLE_LENGTH:
777 setState(DecodeState.SET_VARIABLE_LENGTH);
778
779 return;
780
781 default:
782 throw new RuntimeException("START COLLECTING VALUE" + dfc);
783 }
784
785 setState(DecodeState.COLLECTING_VALUE);
786 }
787
788 private void startCollectingValue(int bytesLeft) {
789 stack.init(bytesLeft);
790 setState(DecodeState.COLLECTING_VALUE);
791 }
792 }