static decode(bytes, version, ecLevel, hints) {
			const bits = new BitSource(bytes);
			let result = new StringBuilder();
			const byteSegments = new Array(); // 1
			// TYPESCRIPTPORT: I do not use constructor with size 1 as in original Java means capacity and the array length is checked below
			let symbolSequence = -1;
			let parityData = -1;
			try {
				let currentCharacterSetECI = null;
				let fc1InEffect = false;
				let mode;
				do {
					// While still another segment to read...
					if (bits.available() < 4) {
						// OK, assume we're done. Really, a TERMINATOR mode should have been recorded here
						mode = Mode$1.TERMINATOR;
					}
					else {
						const modeBits = bits.readBits(4);
						mode = Mode$1.forBits(modeBits); // mode is encoded by 4 bits
					}
					switch (mode) {
						case Mode$1.TERMINATOR:
							break;
						case Mode$1.FNC1_FIRST_POSITION:
						case Mode$1.FNC1_SECOND_POSITION:
							// We do little with FNC1 except alter the parsed result a bit according to the spec
							fc1InEffect = true;
							break;
						case Mode$1.STRUCTURED_APPEND:
							if (bits.available() < 16) {
								throw new FormatException();
							}
							// sequence number and parity is added later to the result metadata
							// Read next 8 bits (symbol sequence #) and 8 bits (data: parity), then continue
							symbolSequence = bits.readBits(8);
							parityData = bits.readBits(8);
							break;
						case Mode$1.ECI:
							// Count doesn't apply to ECI
							const value = DecodedBitStreamParser$1.parseECIValue(bits);
							currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value);
							if (currentCharacterSetECI === null) {
								throw new FormatException();
							}
							break;
						case Mode$1.HANZI:
							// First handle Hanzi mode which does not start with character count
							// Chinese mode contains a sub set indicator right after mode indicator
							const subset = bits.readBits(4);
							const countHanzi = bits.readBits(mode.getCharacterCountBits(version));
							if (subset === DecodedBitStreamParser$1.GB2312_SUBSET) {
								DecodedBitStreamParser$1.decodeHanziSegment(bits, result, countHanzi);
							}
							break;
						default:
							// "Normal" QR code modes:
							// How many characters will follow, encoded in this mode?
							const count = bits.readBits(mode.getCharacterCountBits(version));
							switch (mode) {
								case Mode$1.NUMERIC:
									DecodedBitStreamParser$1.decodeNumericSegment(bits, result, count);
									break;
								case Mode$1.ALPHANUMERIC:
									DecodedBitStreamParser$1.decodeAlphanumericSegment(bits, result, count, fc1InEffect);
									break;
								case Mode$1.BYTE:
									DecodedBitStreamParser$1.decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints);
									break;
								case Mode$1.KANJI:
									DecodedBitStreamParser$1.decodeKanjiSegment(bits, result, count);
									break;
								default:
									throw new FormatException();
							}
							break;
					}
				} while (mode !== Mode$1.TERMINATOR);
			}
			catch (iae /*: IllegalArgumentException*/) {
				// from readBits() calls
				throw new FormatException();
			}
			return new DecoderResult(bytes, result.toString(), byteSegments.length === 0 ? null : byteSegments, ecLevel === null ? null : ecLevel.toString(), symbolSequence, parityData);
		}
<p>QR Codes can encode text as bits in one of several modes, and can use multiple modes
in one QR Code. This class decodes the bits back into text.</p>

<p>See ISO 18004:2006, 6.4.3 - 6.4.7</p>

@author Sean Owen