class Stream extends InputStream {

        private final LobStreamMap lobStreamMap;
        private final long length;
        private ByteBuffer idBuffer;
        private ByteArrayInputStream buffer;
        private byte[] oneByteBuffer;
        private long skip;
        private long pos;

        Stream(LobStreamMap lobStreamMap, byte[] id) {
            this.lobStreamMap = lobStreamMap;
            this.length = lobStreamMap.length(id);
            this.idBuffer = ByteBuffer.wrap(id);
        }

        @Override
        public int read() throws IOException {
            byte[] buffer = oneByteBuffer;
            if (buffer == null) {
                buffer = oneByteBuffer = new byte[1];
            }
            int len = read(buffer, 0, 1);
            return len == -1 ? -1 : (buffer[0] & 255);
        }

        @Override
        public long skip(long n) {<FILL_FUNCTION_BODY>}

        @Override
        public void close() {
            buffer = null;
            idBuffer.position(idBuffer.limit());
            pos = length;
        }

        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            if (len <= 0) {
                return 0;
            }
            while (true) {
                if (buffer == null) {
                    try {
                        buffer = nextBuffer();
                    } catch (IllegalStateException e) {
                        String msg = DataUtils.formatMessage(DataUtils.ERROR_BLOCK_NOT_FOUND,
                                "Block not found in id {0}", Arrays.toString(idBuffer.array()));
                        throw new IOException(msg, e);
                    }
                    if (buffer == null) {
                        return -1;
                    }
                }
                int result = buffer.read(b, off, len);
                if (result > 0) {
                    pos += result;
                    return result;
                }
                buffer = null;
            }
        }

        private ByteArrayInputStream nextBuffer() {
            while (idBuffer.hasRemaining()) {
                switch (idBuffer.get()) {
                case 0: {
                    int len = DataUtils.readVarInt(idBuffer);
                    if (skip >= len) {
                        skip -= len;
                        idBuffer.position(idBuffer.position() + len);
                        continue;
                    }
                    int p = (int) (idBuffer.position() + skip);
                    int l = (int) (len - skip);
                    idBuffer.position(p + l);
                    return new ByteArrayInputStream(idBuffer.array(), p, l);
                }
                case 1: {
                    int len = DataUtils.readVarInt(idBuffer);
                    long key = DataUtils.readVarLong(idBuffer);
                    if (skip >= len) {
                        skip -= len;
                        continue;
                    }
                    byte[] data = lobStreamMap.getBlock(key);
                    int s = (int) skip;
                    skip = 0;
                    return new ByteArrayInputStream(data, s, data.length - s);
                }
                case 2: {
                    long len = DataUtils.readVarLong(idBuffer);
                    long key = DataUtils.readVarLong(idBuffer);
                    if (skip >= len) {
                        skip -= len;
                        continue;
                    }
                    byte[] k = lobStreamMap.getBlock(key);
                    ByteBuffer newBuffer = ByteBuffer
                            .allocate(k.length + idBuffer.limit() - idBuffer.position());
                    newBuffer.put(k);
                    newBuffer.put(idBuffer);
                    newBuffer.flip();
                    idBuffer = newBuffer;
                    return nextBuffer();
                }
                default:
                    throw DataUtils.newIllegalArgumentException("Unsupported id {0}",
                            Arrays.toString(idBuffer.array()));
                }
            }
            return null;
        }
    }

            n = Math.min(length - pos, n);
            if (n == 0) {
                return 0;
            }
            if (buffer != null) {
                long s = buffer.skip(n);
                if (s > 0) {
                    n = s;
                } else {
                    buffer = null;
                    skip += n;
                }
            } else {
                skip += n;
            }
            pos += n;
            return n;
        
<no_super_class>