package org.whispersystems.signalservice.api.messages.multidevice; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; public class ChunkedInputStream { protected final InputStream in; public ChunkedInputStream(InputStream in) { this.in = in; } protected int readRawVarint32() throws IOException { byte tmp = (byte)in.read(); if (tmp >= 0) { return tmp; } int result = tmp & 0x7f; if ((tmp = (byte)in.read()) >= 0) { result |= tmp << 7; } else { result |= (tmp & 0x7f) << 7; if ((tmp = (byte)in.read()) >= 0) { result |= tmp << 14; } else { result |= (tmp & 0x7f) << 14; if ((tmp = (byte)in.read()) >= 0) { result |= tmp << 21; } else { result |= (tmp & 0x7f) << 21; result |= (tmp = (byte)in.read()) << 28; if (tmp < 0) { // Discard upper 32 bits. for (int i = 0; i < 5; i++) { if ((byte)in.read() >= 0) { return result; } } throw new IOException("Malformed varint!"); } } } } return result; } protected static final class LimitedInputStream extends FilterInputStream { private long left; private long mark = -1; LimitedInputStream(InputStream in, long limit) { super(in); left = limit; } @Override public int available() throws IOException { return (int) Math.min(in.available(), left); } // it's okay to mark even if mark isn't supported, as reset won't work @Override public synchronized void mark(int readLimit) { in.mark(readLimit); mark = left; } @Override public int read() throws IOException { if (left == 0) { return -1; } int result = in.read(); if (result != -1) { --left; } return result; } @Override public int read(byte[] b, int off, int len) throws IOException { if (left == 0) { return -1; } len = (int) Math.min(len, left); int result = in.read(b, off, len); if (result != -1) { left -= result; } return result; } @Override public synchronized void reset() throws IOException { if (!in.markSupported()) { throw new IOException("Mark not supported"); } if (mark == -1) { throw new IOException("Mark not set"); } in.reset(); left = mark; } @Override public long skip(long n) throws IOException { n = Math.min(n, left); long skipped = in.skip(n); left -= skipped; return skipped; } } }