ratpack.stream.bytebuf.ByteBufStreams.java Source code

Java tutorial

Introduction

Here is the source code for ratpack.stream.bytebuf.ByteBufStreams.java

Source

/*
 * Copyright 2017 the original author or authors.
 *
 * 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 ratpack.stream.bytebuf;

import io.netty.buffer.*;
import org.reactivestreams.Publisher;
import ratpack.exec.Promise;
import ratpack.func.Action;
import ratpack.stream.Streams;
import ratpack.stream.TransformablePublisher;
import ratpack.stream.bytebuf.internal.ByteBufComposingPublisher;
import ratpack.util.Exceptions;

import java.io.BufferedInputStream;

/**
 * Utilities for dealing with streams of {@link ByteBuf}.
 *
 * @since 1.5
 */
public class ByteBufStreams {

    private ByteBufStreams() {
    }

    /**
     * Buffers and composes byte bufs together into composites before emitting.
     * <p>
     * Calls {@link #buffer(Publisher, long, int, ByteBufAllocator)} with {@link PooledByteBufAllocator#DEFAULT}
     *
     * @param publisher the publisher of byte bufs to buffer
     * @param sizeWatermark the watermark size for a composite
     * @param maxNum the maximum number of composite components
     * @return a byte buf composing publisher
     */
    public static TransformablePublisher<CompositeByteBuf> buffer(Publisher<? extends ByteBuf> publisher,
            long sizeWatermark, int maxNum) {
        return buffer(publisher, sizeWatermark, maxNum, PooledByteBufAllocator.DEFAULT);
    }

    /**
     * Buffers and composes byte bufs together into composites before emitting.
     * <p>
     * This is roughly analogous to {@link BufferedInputStream}.
     * The returned published accumulates upstream buffers until {@code maxNum} have been received,
     * or the cumulative size of buffered byte bufs is greater than or equal to {@code sizeWatermark}.
     * Note that unlike {@link BufferedInputStream}, the downstream writes are not guaranteed to be less than the buffer size.
     * <p>
     * Byte bufs are requested of the given publisher one at a time.
     * If this is inefficient, consider wrapping it with {@link Streams#batch(int, Publisher, Action)} before giving to this method.
     *
     * @param publisher the publisher of byte bufs to buffer
     * @param sizeWatermark the watermark size for a composite
     * @param maxNum the maximum number of composite components
     * @param alloc the allocator of composites
     * @return a byte buf composing publisher
     */
    public static TransformablePublisher<CompositeByteBuf> buffer(Publisher<? extends ByteBuf> publisher,
            long sizeWatermark, int maxNum, ByteBufAllocator alloc) {
        return new ByteBufComposingPublisher(maxNum, sizeWatermark, alloc, publisher);
    }

    /**
     * Reduces the stream to a single composite byte buf.
     * <p>
     * Calls {@link #compose(Publisher, ByteBufAllocator)} with {@link PooledByteBufAllocator#DEFAULT}.
     *
     * @param publisher the stream
     * @return the reduced composite buffer
     */
    public static Promise<CompositeByteBuf> compose(Publisher<? extends ByteBuf> publisher) {
        return compose(publisher, PooledByteBufAllocator.DEFAULT);
    }

    /**
     * Reduces the stream to a single composite byte buf.
     *
     * @param publisher the stream
     * @param alloc the buffer allocator
     * @return the reduced composite buffer
     */
    public static Promise<CompositeByteBuf> compose(Publisher<? extends ByteBuf> publisher,
            ByteBufAllocator alloc) {
        return Promise.flatten(() -> {
            CompositeByteBuf seed = alloc.compositeBuffer();
            return Streams.reduce(publisher, seed, (c, b) -> c.addComponent(true, b)).onError(e -> {
                seed.release();
                throw Exceptions.toException(e);
            });
        });
    }

    /**
     * Reduces the stream to a single {@code byte[]}.
     * <p>
     * This should only be used when it is known that the stream is small,
     * as this will effectively force the entire stream to be held in memory.
     *
     * @param publisher the byte stream
     * @return the bytes as a {@code byte[]}
     */
    public static Promise<byte[]> toByteArray(Publisher<? extends ByteBuf> publisher) {
        return compose(publisher).map(byteBuf -> {
            byte[] bytes = ByteBufUtil.getBytes(byteBuf);
            byteBuf.release();
            return bytes;
        });
    }

    /**
     * Converts the byte buf stream to a stream of {@code byte[]}.
     *
     * @param publisher the byte stream
     * @return a publisher of {@code byte[]}
     */
    public static Publisher<byte[]> toByteArrays(Publisher<? extends ByteBuf> publisher) {
        return Streams.map(publisher, b -> {
            byte[] bytes = ByteBufUtil.getBytes(b);
            b.release();
            return bytes;
        });
    }

}