blob: e1ecda1e2c10750cf2b7e00e1ec48f962b86a3cc [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.zipflinger;
import com.android.annotations.NonNull;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/*
* A wrapper around a FileChannel providing a bounded view of
* it according to the provided Location.
*
* Does not need to be closed. And does not close the wrapped
* channel either.
*/
public class PayloadInputStream extends InputStream {
private FileChannel channel;
private Location boundaries;
private long position;
public PayloadInputStream(@NonNull FileChannel channel, @NonNull Location location)
throws IOException {
this.channel = channel;
this.boundaries = location;
this.position = location.first;
if (location.first < 0 || location.last >= channel.size()) {
throw new IllegalStateException("Location not within channel boundaries");
}
}
@Override
public int read() throws IOException {
if (position > boundaries.last) {
return -1;
}
byte[] buffer = new byte[1];
read(buffer);
return buffer[0];
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (position > boundaries.last) {
return -1;
}
long available = boundaries.last - position + 1;
available = Math.min(available, Integer.MAX_VALUE);
int toRead = Math.min(Math.toIntExact(available), b.length);
ByteBuffer buffer = ByteBuffer.wrap(b, off, toRead);
int read = channel.read(buffer, position);
position += read;
return read;
}
}