protected void readSegment() throws IOException {
		DataInputStream dataIn = new DataInputStream(in);
		
		try {
			// ensure that segment header is valid
			// and read it (segment size and frequency table
			int magic = dataIn.readInt();
			if (magic != HuffmanConsts.HUFFMAN_MAGIC1) {
				throw new IOException("Can't read segment header: magic1 mismatch");
			}
			
			int segSz = dataIn.readInt();
			segment = new byte[segSz];
			HFreqTable freqTable = HFreqTable.restore(dataIn);
			
			magic = dataIn.readInt();
			if (magic != HuffmanConsts.HUFFMAN_MAGIC2)
				throw new IOException("Can't read segment header: magic2 mismatch");
			
			// decode the segment
			HuffmanDecoder dec = new HuffmanDecoder(freqTable);
			BitInputStream bitin = new BitInputStream(in);
			int bytesDecoded = 0;
			while (bytesDecoded < segSz) {
				int bitString = 0, length = 0;

				// continuously read the data bit by bit constructing the
				// bit string. On every iteration check whether the constructed
				// bit string of given length is a huffman code known to decoder.
				// If so, decode it, otherwise continue the process of building
				// bit string.
				while (!dec.hasCode(bitString, length)) {
					int bit = bitin.readBit();
					if (bit == -1)
						break;
					
					bitString |= (bit << length);
					length++;
					if (length >= 32)
						throw new IOException("Huffman code is too long");
				}
				if (length != 0)
					segment[bytesDecoded++] = (byte) dec.decode(bitString, length);
				else {
					eof = true;
				}
			}
		}
		catch (EOFException eoerr) {
			eof = true;
		}
	}