@Override
    public int read() throws IOException {
        int c;
        
        // If we have a block in here, start feeding that out.
        if ((c = outBuffer.read()) != -1)
            return c;
        
        // Otherwise, time to make a block.
        while (inBuffer.size() < ConCh.Delta(source.length, codeabet.length, ConCh.BLOCK_LIMIT)
                && (c = input.read()) != -1) {
            int b = 0xFF & c;
            // Ignore bytes not in the code alphabet.
            if (ConCh.indexOf(codeabet, (byte) b) != -1)
                inBuffer.write(b);
        }
        
        byte[] block = inBuffer.toByteArray();
        inBuffer.reset();
        
        // We tried to get a block, but we failed.
        if (block.length == 0)
            return -1;
        
        // Or we succeeded.
        outBuffer = new ByteArrayInputStream(ConCh.decode(source, codeabet, block));
        
        return outBuffer.read();
    }