blob: ba4a9af350422ea6782e1e445f55ff8b2c65d8e9 [file] [log] [blame]
/*
* Copyright (C) 2018 Square, Inc.
*
* 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 okio.samples;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.WritableByteChannel;
import okio.Buffer;
import okio.Sink;
import okio.Timeout;
/**
* Creates a Sink around a WritableByteChannel and efficiently writes data using an UnsafeCursor.
*
* <p>This is a basic example showing another use for the UnsafeCursor. Using the
* {@link ByteBuffer#wrap(byte[], int, int) ByteBuffer.wrap()} along with access to Buffer segments,
* a WritableByteChannel can be given direct access to Buffer data without having to copy the data.
*/
final class ByteChannelSink implements Sink {
private final WritableByteChannel channel;
private final Timeout timeout;
private final Buffer.UnsafeCursor cursor = new Buffer.UnsafeCursor();
ByteChannelSink(WritableByteChannel channel, Timeout timeout) {
this.channel = channel;
this.timeout = timeout;
}
@Override public void write(Buffer source, long byteCount) throws IOException {
if (!channel.isOpen()) throw new IllegalStateException("closed");
if (byteCount == 0) return;
long remaining = byteCount;
while (remaining > 0) {
timeout.throwIfReached();
try (Buffer.UnsafeCursor ignored = source.readUnsafe(cursor)) {
cursor.seek(0);
int length = (int) Math.min(cursor.end - cursor.start, remaining);
int written = channel.write(ByteBuffer.wrap(cursor.data, cursor.start, length));
remaining -= written;
source.skip(written);
}
}
}
@Override public void flush() {}
@Override public Timeout timeout() {
return timeout;
}
@Override public void close() throws IOException {
channel.close();
}
}