All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.l4.commons.io.Bytes Maven / Gradle / Ivy

There is a newer version: 1.2.2
Show newest version
package se.l4.commons.io;

import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;

import edu.umd.cs.findbugs.annotations.NonNull;

/**
 * Representation of a stream of bytes that can be opened.
 *
 * @author Andreas Holstenson
 *
 */
public interface Bytes
{
	/**
	 * Open an {@link InputStream} for this instance.
	 *
	 * @return
	 *   stream that can be read from, the consumer must close the stream when
	 *   reading is done
	 * @throws IOException
	 *   if unable to open byte data as input stream
	 */
	@NonNull
	InputStream asInputStream()
		throws IOException;

	/**
	 * Convert this instance to a byte array.
	 *
	 * @return
	 *   byte array
	 * @throws IOException
	 *   if unable to read the the byte data
	 */
	@NonNull
	byte[] toByteArray()
		throws IOException;

	/**
	 * Stream this instance to the given consumer.
	 *
	 * @param consumer
	 * @throws IOException
	 */
	default void asChunks(@NonNull ByteArrayConsumer consumer)
		throws IOException
	{
		asChunks(4096, consumer);
	}

	/**
	 * Stream this instance to the given consumer with a specific chunk size.
	 *
	 * @param size
	 * @param consumer
	 * @throws IOException
	 */
	default void asChunks(int size, @NonNull ByteArrayConsumer consumer)
		throws IOException
	{
		Objects.requireNonNull(consumer);
		if(size <= 0) throw new IllegalArgumentException("size must be a positive number");

		try(InputStream in = asInputStream())
		{
			byte[] buf = new byte[size];
			int len;
			while((len = in.read(buf)) != -1)
			{
				consumer.consume(buf, 0, len);
			}
		}
	}

	/**
	 * Open this instance as a {@link ExtendedDataInput}.
	 *
	 * @return
	 * @throws IOException
	 */
	@NonNull
	default ExtendedDataInput asDataInput()
		throws IOException
	{
		return new ExtendedDataInputStream(asInputStream());
	}

	/**
	 * Get an instance that represents no data.
	 *
	 * @return
	 *   instance of {@link Bytes} that contains no data
	 */
	@NonNull
	static Bytes empty()
	{
		return BytesOverByteArray.EMPTY;
	}

	/**
	 * Create an instance for the given array of bytes.
	 *
	 * @param byteArray
	 *   array containing the data that the instance should include. For
	 *   speed purposes the data is not copied by default, clone your array
	 *   if you intend to modify it later and want to keep the {@link Bytes}
	 *   instance unmodified
	 * @return
	 *   instance of {@link Bytes}
	 */
	@NonNull
	static Bytes create(@NonNull byte[] byteArray)
	{
		return create(byteArray, 0, byteArray.length);
	}

	/**
	 * Create an instance for the given array of bytes.
	 *
	 * @param byteArray
	 *   array containing the data that the instance should include. For
	 *   speed purposes the data is not copied by default, clone your array
	 *   if you intend to modify it later and want to keep the {@link Bytes}
	 *   instance unmodified
	 * @param offset
	 *   the offset to start reading byte data from
	 * @param length
	 *   the number of bytes to read from the array
	 * @return
	 *   instance of {@link Bytes}
	 */
	@NonNull
	static Bytes create(@NonNull byte[] byteArray, int offset, int length)
	{
		return new BytesOverByteArray(byteArray, offset, length);
	}

	/**
	 * Create an instance over the given input stream.
	 *
	 * @param supplier
	 *   supplier of {@link InputStream}, will be called every time the data
	 *   of the returned {@link Bytes} instance is opened
	 * @return
	 *   instance of {@link Bytes}
	 */
	@NonNull
	static Bytes create(@NonNull IOSupplier supplier)
	{
		return new InputStreamBytes(supplier);
	}

	/**
	 * Create an instance that will create data on demand. This will only call
	 * the creator when the contents of the returned instance is accessed.
	 *
	 * @param creator
	 *   creator that will be called whenever the {@link Bytes} data is requested
	 * @return
	 *   instance of {@link Bytes}
	 */
	@NonNull
	static Bytes lazyViaDataOutput(@NonNull IOConsumer creator)
	{
		return BytesBuilder.createViaLazyDataOutput(creator);
	}

	/**
	 * Create an instance that will create data on demand. This will only call
	 * the creator when the contents of the returned instance is accessed.
	 *
	 * @param creator
	 *   creator that will be called whenever the {@link Bytes} data is requested
	 * @param expectedSize
	 *   the expected size of the created byte data, used to allocated memory
	 *   for the data
	 * @return
	 */
	@NonNull
	static Bytes lazyViaDataOutput(@NonNull IOConsumer creator, int expectedSize)
	{
		return BytesBuilder.createViaLazyDataOutput(creator, expectedSize);
	}

	/**
	 * Create an instance by running the given function and storing the result
	 * in memory.
	 *
	 * @param creator
	 *   creator of the data
	 * @return
	 *   instance of {@link Bytes} with data stored in memory
	 * @throws IOException
	 *   if unable to create the data via {@code creator}
	 */
	@NonNull
	static Bytes viaDataOutput(@NonNull IOConsumer creator)
		throws IOException
	{
		return BytesBuilder.createViaDataOutput(creator);
	}

	/**
	 * Create an instance by running the given function and storing the result
	 * in memory.
	 *
	 * @param creator
	 *   creator of the data
	 * @param expectedSize
	 *   the expected amount of data, used to allocate initial memory
	 * @return
	 *   instance of {@link Bytes} with data stored in memory
	 * @throws IOException
	 * *   if unable to create the data via {@code creator}
	 */
	@NonNull
	static Bytes viaDataOutput(@NonNull IOConsumer creator, int expectedSize)
		throws IOException
	{
		return BytesBuilder.createViaDataOutput(creator, expectedSize);
	}

	/**
	 * Create a new instance of {@link Bytes} via a builder.
	 *
	 * @return
	 *   instance of builder
	 */
	@NonNull
	static BytesBuilder create()
	{
		return new BytesBuilder();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy