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

org.refcodes.serial.Sequence Maven / Gradle / Ivy

Go to download

Artifact providing generic (byte) serialization functionality including a TTY-/COM-Port implementation of the serial framework as well as a (local) loopback port.

The newest version!
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// /////////////////////////////////////////////////////////////////////////////
// This code is copyright (c) by Siegfried Steiner, Munich, Germany, distributed
// on an "AS IS" BASIS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, and licen-
// sed under the following (see "http://en.wikipedia.org/wiki/Multi-licensing")
// licenses:
// -----------------------------------------------------------------------------
// GNU General Public License, v3.0 ("http://www.gnu.org/licenses/gpl-3.0.html")
// -----------------------------------------------------------------------------
// Apache License, v2.0 ("http://www.apache.org/licenses/TEXT-2.0")
// -----------------------------------------------------------------------------
// Please contact the copyright holding author(s) of the software artifacts in
// question for licensing issues not being covered by the above listed licenses,
// also regarding commercial licensing models or regarding the compatibility
// with other open source licenses.
// /////////////////////////////////////////////////////////////////////////////

package org.refcodes.serial;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.refcodes.exception.UnhandledEnumBugException;
import org.refcodes.mixin.Bytes;
import org.refcodes.mixin.Clearable;
import org.refcodes.mixin.ConcatenateMode;
import org.refcodes.mixin.InputStreamAccessor;
import org.refcodes.mixin.LengthAccessor;
import org.refcodes.mixin.OutputStreamAccessor;
import org.refcodes.mixin.TruncateMode;
import org.refcodes.numerical.CrcAlgorithm;
import org.refcodes.numerical.Endianess;
import org.refcodes.numerical.NumericalUtility;

/**
 * A {@link Sequence} represents a bytes container providing means to apply
 * complex operations on that container's byte field.
 */
public interface Sequence extends LengthAccessor, Iterable, InputStreamAccessor, OutputStreamAccessor, Clearable, Bytes {

	// /////////////////////////////////////////////////////////////////////////
	// METHODS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Appends the given bytes to the end of this {@link Sequence}. Beware: This
	 * {@link Sequence} is modified! If you do not wish to modify this
	 * {@link Sequence}, please use {@link #toAppend(byte...)}.
	 * 
	 * @param aBytes The bytes to be appended.
	 */
	default void append( byte... aBytes ) {
		append( aBytes, 0, aBytes.length );
	}

	/**
	 * Appends the given bytes to the end of this {@link Sequence}. Beware: This
	 * {@link Sequence} is modified! If you do not wish to modify this
	 * {@link Sequence}, please use {@link #toAppend(byte[], int, int)}.
	 * 
	 * @param aBytes The bytes to be appended.
	 * @param aOffset The offset from where to start collecting the bytes.
	 * @param aLength The number of bytes to be appended.
	 */
	void append( byte[] aBytes, int aOffset, int aLength );

	/**
	 * Appends the given {@link Sequence} to the end of this {@link Sequence}.
	 * Beware: This {@link Sequence} is modified! If you do not wish to modify
	 * this {@link Sequence}, please use {@link #toAppend(Sequence)}.
	 * 
	 * @param aSequence The {@link Sequence} to be appended.
	 */
	void append( Sequence aSequence );

	/**
	 * Sets all bytes in the {@link Sequence} to zero.
	 */
	@Override
	default void clear() {
		clear( (byte) 0 );
	}

	/**
	 * Sets all bytes in the {@link Sequence} to the provided value.
	 * 
	 * @param aValue The value with which to zero out this {@link Sequence}.
	 */
	default void clear( byte aValue ) {
		for ( int i = 0; i < getLength(); i++ ) {
			setByteAt( i, (byte) 0 );
		}
	}

	/**
	 * Concatenates the given bytes with this {@link Sequence} according to the
	 * provided {@link ConcatenateMode} . Beware: This {@link Sequence} is
	 * modified! If you do not wish to modify this {@link Sequence}, please use
	 * {@link #toConcatenate(ConcatenateMode, byte...)}.
	 * 
	 * @param aConcatenateMode The concatenation mode to be used.
	 * @param aBytes The bytes to be concatenated with.
	 */
	default void concatenate( ConcatenateMode aConcatenateMode, byte... aBytes ) {
		switch ( aConcatenateMode ) {
		case PREPEND -> {
			prepend( aBytes );
			return;
		}
		case APPEND -> {
			append( aBytes );
			return;
		}
		default -> throw new UnhandledEnumBugException( aConcatenateMode );
		}
	}

	/**
	 * Concatenates the given bytes with this {@link Sequence} according to the
	 * provided {@link ConcatenateMode} . Beware: This {@link Sequence} is
	 * modified! If you do not wish to modify this {@link Sequence}, please use
	 * {@link #toConcatenate(ConcatenateMode, byte[], int, int)}.
	 *
	 * @param aConcatenateMode The concatenation mode to be used.
	 * @param aBytes The bytes to be concatenated with.
	 * @param aOffset The offset from where to start collecting the bytes.
	 * @param aLength The number of bytes to be concatenated.
	 */
	default void concatenate( ConcatenateMode aConcatenateMode, byte[] aBytes, int aOffset, int aLength ) {
		switch ( aConcatenateMode ) {
		case PREPEND -> {
			prepend( aBytes, aOffset, aLength );
			return;
		}
		case APPEND -> {
			append( aBytes, aOffset, aLength );
			return;
		}
		default -> throw new UnhandledEnumBugException( aConcatenateMode );
		}
	}

	/**
	 * Concatenates the given {@link Sequence} with this {@link Sequence}
	 * according to the provided {@link ConcatenateMode} . Beware: This
	 * {@link Sequence} is modified! If you do not wish to modify this
	 * {@link Sequence}, please use
	 * {@link #toConcatenate(Sequence, ConcatenateMode)}.
	 *
	 * @param aSequence The {@link Sequence} to be concatenated with.
	 * @param aConcatenateMode The concatenation mode to be used.
	 */
	default void concatenate( Sequence aSequence, ConcatenateMode aConcatenateMode ) {
		switch ( aConcatenateMode ) {
		case PREPEND -> {
			prepend( aSequence );
			return;
		}
		case APPEND -> {
			append( aSequence );
			return;
		}
		default -> throw new UnhandledEnumBugException( aConcatenateMode );
		}
	}

	/**
	 * Empties the {@link Sequence} to end up being of length 0.
	 */
	void empty();

	/**
	 * Returns the byte at the given index in the {@link Sequence}.
	 * 
	 * @param aIndex The index of the byte to retrieve.
	 * 
	 * @return The byte being retrieved.
	 * 
	 * @throws IndexOutOfBoundsException thrown in case the given index is out
	 *         of bounds.
	 */
	byte getByteAt( int aIndex );

	/**
	 * Creates an {@link InputStream} backed by this {@link Sequence}.
	 * {@inheritDoc}
	 */
	@Override
	default InputStream getInputStream() {
		return new SequenceInputStream( this );
	}

	/**
	 * Creates an {@link OutputStream} backed by this {@link Sequence}.
	 * {@inheritDoc}
	 */
	@Override
	default OutputStream getOutputStream() {
		return new SequenceOutputStream( this );
	}

	/**
	 * Writes the given bytes into this {@link Sequence}. If the
	 * {@link Sequence} is too small for the bytes to fit into, then the
	 * {@link Sequence} is extended accordingly.
	 * 
	 * @param aBytes The byte array where to copy the bytes from.
	 */
	default void overwrite( byte[] aBytes ) {
		overwrite( 0, aBytes, 0, aBytes.length );
	}

	/**
	 * Writes the given bytes into this {@link Sequence}. If the
	 * {@link Sequence} is too small for the bytes to fit into, then the
	 * {@link Sequence} is extended accordingly.
	 * 
	 * @param aBytes The byte array where to copy the bytes from.
	 * @param aLength The number of bytes to be copied starting at offset 0.
	 */
	default void overwrite( byte[] aBytes, int aLength ) {
		overwrite( 0, aBytes, 0, aLength );
	}

	/**
	 * Writes the given bytes into this {@link Sequence}. If the
	 * {@link Sequence} is too small for the bytes to fit into, then the
	 * {@link Sequence} is extended accordingly.
	 * 
	 * @param aOffset The offset where to start writing the bytes to.
	 * @param aBytes The byte array where to copy the bytes from.
	 */
	default void overwrite( int aOffset, byte[] aBytes ) {
		overwrite( aOffset, aBytes, 0, aBytes.length );
	}

	/**
	 * Writes the given bytes into this {@link Sequence}. If the
	 * {@link Sequence} is too small for the bytes to fit into, then the
	 * {@link Sequence} is extended accordingly.
	 * 
	 * @param aOffset The offset where to start writing the bytes to.
	 * @param aBytes The byte array where to copy the bytes from.
	 * @param aBytesOffset The offset in the byte array where to start copying.
	 * @param aLength The number of bytes to be copied.
	 */
	default void overwrite( int aOffset, byte[] aBytes, int aBytesOffset, int aLength ) {
		final int theDeltaLength = ( aOffset + aLength ) - getLength();
		if ( theDeltaLength > 0 ) {
			append( new byte[theDeltaLength] );
		}
		for ( int i = 0; i < aLength; i++ ) {
			setByteAt( aOffset + i, aBytes[i + aBytesOffset] );
		}
	}

	/**
	 * Writes the given {@link Sequence} into this {@link Sequence}. If the
	 * {@link Sequence} is too small for the given {@link Sequence}'s bytes to
	 * fit into, then this {@link Sequence} is extended accordingly.
	 * 
	 * @param aOffset The offset where to start writing the given
	 *        {@link Sequence}'s bytes to.
	 * @param aSequence The given {@link Sequence} where to copy the bytes from.
	 */
	default void overwrite( int aOffset, Sequence aSequence ) {
		final byte[] theBytes = aSequence.toBytes();
		overwrite( aOffset, theBytes, 0, theBytes.length );
	}

	/**
	 * Writes the given bytes into this {@link Sequence}. If the
	 * {@link Sequence} is too small for the bytes to fit into, then the
	 * {@link Sequence} is extended accordingly.
	 * 
	 * @param aOffset The offset where to start writing the bytes to.
	 * @param aSequence The given {@link Sequence} where to copy the bytes from.
	 * @param aSequenceOffset The offset in the byte array where to start
	 *        copying.
	 * @param aLength The number of bytes to be copied.
	 */
	default void overwrite( int aOffset, Sequence aSequence, int aSequenceOffset, int aLength ) {
		final int theDeltaLength = ( aOffset + aLength ) - getLength();
		if ( theDeltaLength > 0 ) {
			append( new byte[theDeltaLength] );
		}
		for ( int i = 0; i < aLength; i++ ) {
			setByteAt( aOffset + i, aSequence.getByteAt( i + aSequenceOffset ) );
		}
	}

	/**
	 * Writes the given {@link Sequence} into this {@link Sequence}. If the
	 * {@link Sequence} is too small for the given {@link Sequence}'s bytes to
	 * fit into, then this {@link Sequence} is extended accordingly.
	 * 
	 * @param aSequence The given {@link Sequence} where to copy the bytes from.
	 */
	default void overwrite( Sequence aSequence ) {
		final byte[] theBytes = aSequence.toBytes();
		overwrite( 0, theBytes, 0, theBytes.length );
	}

	/**
	 * Writes the given bytes into this {@link Sequence}. If the
	 * {@link Sequence} is too small for the bytes to fit into, then the
	 * {@link Sequence} is extended accordingly.
	 * 
	 * @param aSequence The {@link Sequence} where to copy the bytes from.
	 * @param aLength The number of bytes to be copied starting at offset 0.
	 */
	default void overwrite( Sequence aSequence, int aLength ) {
		overwrite( 0, aSequence, 0, aLength );
	}

	/**
	 * Prepends the given bytes the beginning of this {@link Sequence}. Beware:
	 * This {@link Sequence} is modified! If you do not wish to modify this
	 * {@link Sequence}, please use {@link #toPrepend(byte...)}.
	 * 
	 * @param aBytes The bytes to be prepended.
	 */
	default void prepend( byte... aBytes ) {
		prepend( aBytes, 0, aBytes.length );
	}

	/**
	 * Prepends the given bytes to the beginning of this {@link Sequence}.
	 * Beware: This {@link Sequence} is modified! If you do not wish to modify
	 * this {@link Sequence}, please use {@link #toPrepend(byte[], int, int)}.
	 * 
	 * @param aBytes The bytes to be prepended.
	 * @param aOffset The offset from where to start collecting the bytes.
	 * @param aLength The number of bytes to be prepended.
	 */
	void prepend( byte[] aBytes, int aOffset, int aLength );

	/**
	 * Prepends the given {@link Sequence} to the beginning of this
	 * {@link Sequence}. Beware: This {@link Sequence} is modified! If you do
	 * not wish to modify this {@link Sequence}, please use
	 * {@link #toPrepend(Sequence)}.
	 * 
	 * @param aSequence The {@link Sequence} to be prepended.
	 */
	void prepend( Sequence aSequence );

	/**
	 * Replaces the given bytes with this byte array.
	 * 
	 * @param aBytes The byte array where to copy the bytes from.
	 */
	default void replace( byte[] aBytes ) {
		replace( aBytes, 0, aBytes.length );
	}

	/**
	 * Replaces the given bytes with this byte array.
	 * 
	 * @param aBytes The byte array where to copy the bytes from.
	 * @param aLength The number of bytes to be copied starting with offset 0.
	 */
	default void replace( byte[] aBytes, int aLength ) {
		replace( aBytes, 0, aLength );
	}

	/**
	 * Replaces the given bytes with this byte array.
	 * 
	 * @param aBytes The byte array where to copy the bytes from.
	 * @param aOffset The offset in the byte array where to start copying.
	 * @param aLength The number of bytes to be copied.
	 */
	void replace( byte[] aBytes, int aOffset, int aLength );

	/**
	 * Replaces the given {@link Sequence} into this {@link Sequence}.
	 * 
	 * @param aSequence The given {@link Sequence} where to copy the bytes from.
	 */
	default void replace( Sequence aSequence ) {
		replace( aSequence, 0, aSequence.getLength() );
	}

	/**
	 * Replaces the given bytes with this {@link Sequence}.
	 * 
	 * @param aSequence The given {@link Sequence} where to copy the bytes from.
	 * @param aLength The number of bytes to be copied starting with offset 0.
	 */
	default void replace( Sequence aSequence, int aLength ) {
		replace( aSequence, 0, aLength );
	}

	/**
	 * Replaces the given bytes with this {@link Sequence}.
	 * 
	 * @param aSequence The given {@link Sequence} where to copy the bytes from.
	 * @param aOffset The offset in the byte array where to start copying.
	 * @param aLength The number of bytes to be copied.
	 */
	void replace( Sequence aSequence, int aOffset, int aLength );

	/**
	 * Sets the byte at the given index in the {@link Sequence}.
	 * 
	 * @param aIndex The index of the byte to set.
	 * @param aByte The byte to set at the given index.
	 * 
	 * @throws IndexOutOfBoundsException thrown in case the given index is out
	 *         of bounds.
	 */
	void setByteAt( int aIndex, byte aByte );

	/**
	 * Appends the given bytes to the end of this {@link Sequence}. This
	 * {@link Sequence} is not modified and a new {@link Sequence} is returned.
	 * 
	 * @param aBytes The bytes to be appended.
	 * 
	 * @return The according {@link Sequence}.
	 */
	default Sequence toAppend( byte... aBytes ) {
		return toAppend( aBytes, 0, aBytes.length );
	}

	/**
	 * Appends the given bytes to the end of this {@link Sequence}. This
	 * {@link Sequence} is not modified and a new {@link Sequence} is returned.
	 * 
	 * @param aBytes The bytes to be appended.
	 * @param aOffset The offset from where to start collecting the bytes.
	 * @param aLength The number of bytes to be appended.
	 * 
	 * @return The according {@link Sequence}.
	 */
	Sequence toAppend( byte[] aBytes, int aOffset, int aLength );

	/**
	 * Appends the given {@link Sequence} to the end of this {@link Sequence}.
	 * This {@link Sequence} is not modified and a new {@link Sequence} is
	 * returned.
	 * 
	 * @param aSequence The {@link Sequence} to be appended.
	 * 
	 * @return The according {@link Sequence}.
	 */
	Sequence toAppend( Sequence aSequence );

	/**
	 * Retrieves a continuous array of bytes from the {@link Sequence}.
	 * 
	 * @return The according byte array.
	 */
	@Override
	default byte[] toBytes() {
		final byte[] theBytes = new byte[getLength()];
		for ( int i = 0; i < theBytes.length; i++ ) {
			theBytes[i] = getByteAt( i );
		}
		return theBytes;
	}

	/**
	 * Retrieves a continuous array of bytes from the {@link Sequence}, starting
	 * with the byte at the given offset and containing the given number of
	 * bytes.
	 * 
	 * @param aOffset The offset from where to start collecting the bytes.
	 * @param aLength The length of the byte array to be returned.
	 * 
	 * @return The according bytes.
	 * 
	 * @throws IndexOutOfBoundsException thrown in case the length overshot the
	 *         available bytes.
	 */
	default byte[] toBytes( int aOffset, int aLength ) {
		// if ( aOffset + aLength > getLength() ) aLength = getLength() - aOffset;
		// if ( aLength < 0) aLength = 0;
		final byte[] theChunk = new byte[aLength];
		for ( int i = 0; i < theChunk.length; i++ ) {
			theChunk[i] = getByteAt( aOffset + i );
		}
		return theChunk;
	}

	/**
	 * Retrieves a continuous array of bytes from the {@link Sequence}, starting
	 * with the byte at the given offset and covering the given number of bytes.
	 * The bytes are stored in the provided bytes array starting at the given
	 * bytes' offset.
	 * 
	 * @param aOffset The offset from where to start collecting the bytes.
	 * @param aLength The number of bytes to be copied.
	 * @param aBytes The byte array where to copy the bytes to.
	 * @param aBytesOffset The offset in the byte array where to start copying.
	 */
	default void toBytes( int aOffset, int aLength, byte[] aBytes, int aBytesOffset ) {
		for ( int i = 0; i < aLength; i++ ) {
			aBytes[i + aBytesOffset] = getByteAt( aOffset + i );
		}
	}

	/**
	 * Creates a deep clone of this {@link Sequence}.
	 * 
	 * @return The deep clone.
	 */
	Sequence toClone();

	/**
	 * Concatenates the given bytes with this {@link Sequence} according to the
	 * provided {@link ConcatenateMode}. This {@link Sequence} is not modified
	 * and a new {@link Sequence} is returned.
	 * 
	 * @param aConcatenateMode The concatenation mode to be used.
	 * @param aBytes The bytes to be concatenated with.
	 * 
	 * @return The according {@link Sequence}.
	 */
	default Sequence toConcatenate( ConcatenateMode aConcatenateMode, byte... aBytes ) {
		return switch ( aConcatenateMode ) {
		case PREPEND -> toPrepend( aBytes );
		case APPEND -> toAppend( aBytes );
		};
	}

	/**
	 * Concatenates the given bytes with this {@link Sequence} according to the
	 * provided {@link ConcatenateMode}. This {@link Sequence} is not modified
	 * and a new {@link Sequence} is returned.
	 * 
	 * @param aConcatenateMode The concatenation mode to be used.
	 * @param aBytes The bytes to be concatenated.
	 * @param aOffset The offset from where to start collecting the bytes.
	 * @param aLength The number of bytes to be concatenated with.
	 * 
	 * @return The according {@link Sequence}.
	 */
	default Sequence toConcatenate( ConcatenateMode aConcatenateMode, byte[] aBytes, int aOffset, int aLength ) {
		return switch ( aConcatenateMode ) {
		case PREPEND -> toPrepend( aBytes, aOffset, aLength );
		case APPEND -> toAppend( aBytes, aOffset, aLength );
		};
	}

	/**
	 * Concatenates the given {@link Sequence} with this {@link Sequence}
	 * according to the provided {@link ConcatenateMode}. This {@link Sequence}
	 * is not modified and a new {@link Sequence} is returned.
	 * 
	 * @param aSequence The {@link Sequence} to be concatenated with.
	 * @param aConcatenateMode The concatenation mode to be used.
	 * 
	 * @return The according {@link Sequence}.
	 */
	default Sequence toConcatenate( Sequence aSequence, ConcatenateMode aConcatenateMode ) {
		return switch ( aConcatenateMode ) {
		case PREPEND -> toPrepend( aSequence );
		case APPEND -> toAppend( aSequence );
		};
	}

	/**
	 * Calculates the CRC checksum as byte array for this {@link Sequence}.
	 * 
	 * @param aCrcAlgorithm The {@link CrcAlgorithm} to be used when calculating
	 *        the CRC checksum.
	 * @param aEndianess The {@link Endianess} (little endian or big endian) to
	 *        be used for the byte array representation of the CRC checksum.
	 * 
	 * @return The CRC checksum of the {@link Sequence}.
	 */
	byte[] toCrcBytes( CrcAlgorithm aCrcAlgorithm, Endianess aEndianess );

	/**
	 * Calculates the CRC checksum as byte array for this {@link Sequence}.
	 * 
	 * @param aCrcChecksum The CRC checksum from which to continue calculating
	 *        the checksum,
	 * @param aCrcAlgorithm The {@link CrcAlgorithm} to be used when calculating
	 *        the CRC checksum.
	 * @param aEndianess The {@link Endianess} (little endian or big endian) to
	 *        be used for the byte array representation of the CRC checksum.
	 * 
	 * @return The CRC checksum of the {@link Sequence}.
	 */
	byte[] toCrcBytes( long aCrcChecksum, CrcAlgorithm aCrcAlgorithm, Endianess aEndianess );

	/**
	 * Calculates the CRC checksum for this {@link Sequence}.
	 * 
	 * @param aCrcAlgorithm The {@link CrcAlgorithm} to be used when calculating
	 *        the CRC checksum.
	 * 
	 * @return The CRC checksum of the {@link Sequence}.
	 */
	long toCrcChecksum( CrcAlgorithm aCrcAlgorithm );

	/**
	 * Calculates the CRC checksum for this {@link Sequence}.
	 * 
	 * @param aCrcChecksum The CRC checksum from which to continue calculating
	 *        the checksum,
	 * @param aCrcAlgorithm The {@link CrcAlgorithm} to be used when calculating
	 *        the CRC checksum.
	 * 
	 * @return The CRC checksum of the {@link Sequence}.
	 */
	long toCrcChecksum( long aCrcChecksum, CrcAlgorithm aCrcAlgorithm );

	/**
	 * Converts this {@link Sequence} to a hexadecimal {@link String}
	 * representation.
	 * 
	 * @return The according {@link String}.
	 */
	default String toHexString() {
		return toHexString( " " );
	}

	/**
	 * Converts this {@link Sequence} to a hexadecimal {@link String}
	 * representation.
	 * 
	 * @param aSeparator The separator to separate two hex bytes from each other
	 *        or null if no separator is to be used.
	 * 
	 * @return The according {@link String}.
	 */
	default String toHexString( String aSeparator ) {
		final int theSize = getLength();
		final StringBuilder theBuffer = new StringBuilder();
		for ( int i = 0; i < theSize; i++ ) {
			theBuffer.append( NumericalUtility.toHexString( getByteAt( i ) ) );
			if ( i < theSize - 1 ) {
				theBuffer.append( aSeparator );
			}
		}
		return theBuffer.toString();
	}

	/**
	 * Creates an {@link InputStream} form this {@link Sequence} without being
	 * backed by this {@link Sequence}, e.g. reading from the returned
	 * {@link InputStream} does not affect this {@link Sequence} (in contrast to
	 * the {@link InputStream} returned by the method
	 * {@link #getInputStream()}).
	 * 
	 * @return The according {@link InputStream} not affecting this
	 *         {@link Sequence}.
	 */
	default InputStream toInputStream() {
		return new ByteArraySequence( this.toBytes().clone() ).getInputStream();
	}

	/**
	 * Writes the given bytes into a copy of this {@link Sequence}. If the
	 * {@link Sequence} is too small for the bytes to fit into, then the
	 * {@link Sequence} is extended accordingly.
	 * 
	 * @param aBytes The byte array where to copy the bytes from.
	 * 
	 * @return The according {@link Sequence}.
	 */
	default Sequence toOverwrite( byte[] aBytes ) {
		return toOverwrite( 0, aBytes, 0, aBytes.length );
	}

	/**
	 * Writes the given bytes into a copy of this {@link Sequence}. If the
	 * {@link Sequence} is too small for the bytes to fit into, then the
	 * {@link Sequence} is extended accordingly.
	 *
	 * @param aBytes The byte array where to copy the bytes from.
	 * @param aLength The number of bytes to be copied starting with offset 0.
	 * 
	 * @return The according {@link Sequence}.
	 */
	default Sequence toOverwrite( byte[] aBytes, int aLength ) {
		return toOverwrite( 0, aBytes, 0, aLength );
	}

	/**
	 * Writes the given bytes into a copy of this {@link Sequence}. If the
	 * {@link Sequence} is too small for the bytes to fit into, then the
	 * {@link Sequence} is extended accordingly.
	 * 
	 * @param aOffset The offset where to start writing the bytes to.
	 * @param aBytes The byte array where to copy the bytes from.
	 * 
	 * @return The according {@link Sequence}.
	 */
	default Sequence toOverwrite( int aOffset, byte[] aBytes ) {
		return toOverwrite( aOffset, aBytes, 0, aBytes.length );
	}

	/**
	 * Writes the given bytes into a copy of this {@link Sequence}. If the
	 * {@link Sequence} is too small for the bytes to fit into, then the
	 * {@link Sequence} is extended accordingly.
	 * 
	 * @param aOffset The offset where to start writing the bytes to.
	 * @param aBytes The byte array where to copy the bytes from.
	 * @param aBytesOffset The offset in the byte array where to start copying.
	 * @param aLength The number of bytes to be copied.
	 * 
	 * @return The according {@link Sequence}.
	 */
	Sequence toOverwrite( int aOffset, byte[] aBytes, int aBytesOffset, int aLength );

	/**
	 * Writes the given bytes into a copy of this {@link Sequence}. If the
	 * {@link Sequence} is too small for the bytes to fit into, then the
	 * {@link Sequence} is extended accordingly.
	 * 
	 * @param aOffset The offset where to start writing the bytes to.
	 * @param aSequence The {@link Sequence} where to copy the bytes from.
	 * 
	 * @return The according {@link Sequence}.
	 */
	default Sequence toOverwrite( int aOffset, Sequence aSequence ) {
		return toOverwrite( aOffset, aSequence, 0, aSequence.getLength() );
	}

	/**
	 * Writes the given {@link Sequence} into a copy of this {@link Sequence}.
	 * If the {@link Sequence} is too small for the bytes to fit into, then the
	 * {@link Sequence} is extended accordingly.
	 * 
	 * @param aOffset The offset where to start writing the bytes to.
	 * @param aSequence The {@link Sequence} where to copy the bytes from.
	 * @param aBytesOffset The offset in the {@link Sequence} where to start
	 *        copying.
	 * @param aLength The number of bytes to be copied.
	 * 
	 * @return The according {@link Sequence}.
	 */
	Sequence toOverwrite( int aOffset, Sequence aSequence, int aBytesOffset, int aLength );

	/**
	 * Writes the given bytes into a copy of this {@link Sequence}. If the
	 * {@link Sequence} is too small for the bytes to fit into, then the
	 * {@link Sequence} is extended accordingly.
	 * 
	 * @param aSequence The {@link Sequence} where to copy the bytes from.
	 * 
	 * @return The according {@link Sequence}.
	 */
	default Sequence toOverwrite( Sequence aSequence ) {
		return toOverwrite( 0, aSequence, 0, aSequence.getLength() );
	}

	/**
	 * Writes the given bytes into a copy of this {@link Sequence}. If the
	 * {@link Sequence} is too small for the bytes to fit into, then the
	 * {@link Sequence} is extended accordingly.
	 *
	 * @param aSequence The {@link Sequence} where to copy the bytes from.
	 * @param aLength The number of bytes to be copied starting with offset 0.
	 * 
	 * @return The according {@link Sequence}.
	 */
	default Sequence toOverwrite( Sequence aSequence, int aLength ) {
		return toOverwrite( 0, aSequence, 0, aLength );
	}

	/**
	 * Prepends the given bytes to the beginning of this {@link Sequence}. This
	 * {@link Sequence} is not modified and a new {@link Sequence} is returned.
	 * 
	 * @param aBytes The bytes to be prepended.
	 * 
	 * @return The according {@link Sequence}.
	 */
	default Sequence toPrepend( byte... aBytes ) {
		return toPrepend( aBytes, 0, aBytes.length );
	}

	/**
	 * Prepends the given bytes to the beginning of this {@link Sequence}. This
	 * {@link Sequence} is not modified and a new {@link Sequence} is returned.
	 * 
	 * @param aBytes The bytes to be prepended.
	 * @param aOffset The offset from where to start collecting the bytes.
	 * @param aLength The number of bytes to be prepended.
	 * 
	 * @return The according {@link Sequence}.
	 */
	Sequence toPrepend( byte[] aBytes, int aOffset, int aLength );

	/**
	 * Prepends the given {@link Sequence} to the beginning of this
	 * {@link Sequence}. This {@link Sequence} is not modified and a new
	 * {@link Sequence} is returned.
	 * 
	 * @param aSequence The {@link Sequence} to be prepended.
	 * 
	 * @return The according {@link Sequence}.
	 */
	Sequence toPrepend( Sequence aSequence );

	/**
	 * Retrieves a new {@link Sequence} from this {@link Sequence}, starting
	 * with the byte at the given offset and containing the given number of
	 * bytes.
	 * 
	 * @param aOffset The offset from where to start collecting the bytes.
	 * @param aLength The length of the byte array to be returned.
	 * 
	 * @return The according {@link TransmissionSequenceException}.
	 * 
	 * @throws IndexOutOfBoundsException thrown in case the length overshot the
	 *         available bytes.
	 */
	Sequence toSequence( int aOffset, int aLength );

	/**
	 * Returns a new {@link Sequence} truncated by the given number of bytes
	 * from the right or from the left of both, according to the given
	 * {@link TruncateMode}. If the number of bytes exceeds the actual length of
	 * the {@link Sequence}, then the Sequence will end up being empty.
	 * 
	 * @param aLength The number of bytes to truncate according to the
	 *        {@link TruncateMode}.
	 * @param aTruncateMode The {@link TruncateMode} to use for truncating the
	 *        {@link Sequence}.
	 * 
	 * @return The newly created truncated {@link Sequence}.
	 */
	default Sequence toTruncate( int aLength, TruncateMode aTruncateMode ) {
		Sequence theSequence = null;
		if ( aTruncateMode.isHead() ) {
			theSequence = toTruncateHead( aLength );
		}
		if ( aTruncateMode.isTail() ) {
			if ( theSequence == null ) {
				theSequence = toTruncateTail( aLength );
			}
			else {
				theSequence.truncateTail( aLength );
			}
		}
		return theSequence;
	}

	/**
	 * Returns a new {@link Sequence} truncated by the given number of bytes
	 * from the left. If the number of bytes exceeds the actual length of the
	 * {@link Sequence}, then the new {@link Sequence} will end up being empty.
	 * 
	 * @param aLength The number of bytes to truncate from the left.
	 * 
	 * @return The newly created truncated {@link Sequence}.
	 */
	Sequence toTruncateHead( int aLength );

	/**
	 * Returns a new {@link Sequence} truncated by the given number of bytes
	 * from the right. If the number of bytes exceeds the actual length of the
	 * {@link Sequence}, then the new {@link Sequence} will end up being empty.
	 * 
	 * @param aLength The number of bytes to truncate from the right.
	 * 
	 * @return The newly created truncated {@link Sequence}.
	 */
	Sequence toTruncateTail( int aLength );

	/**
	 * Truncates the {@link Sequence} by the given number of bytes from the
	 * right or from the left of both, according to the given
	 * {@link TruncateMode}. If the number of bytes exceeds the actual length of
	 * the {@link Sequence}, then the {@link Sequence} will end up being empty.
	 * 
	 * @param aLength The number of bytes to truncate according to the
	 *        {@link TruncateMode}.
	 * @param aTruncateMode The {@link TruncateMode} to use for truncating the
	 *        {@link Sequence}.
	 */
	default void truncate( int aLength, TruncateMode aTruncateMode ) {
		if ( aTruncateMode.isHead() ) {
			truncateHead( aLength );
		}
		if ( aTruncateMode.isTail() ) {
			truncateTail( aLength );
		}
	}

	/**
	 * Truncates the {@link Sequence} by the given number of bytes from the
	 * left. If the number of bytes exceeds the actual length of the
	 * {@link Sequence}, then the {@link Sequence} will end up being empty.
	 * 
	 * @param aLength The number of bytes to truncate from the left.
	 */
	void truncateHead( int aLength );

	/**
	 * Truncates the {@link Sequence} by the given number of bytes from the
	 * right. If the number of bytes exceeds the actual length of the
	 * {@link Sequence}, then the {@link Sequence} will end up being empty.
	 * 
	 * @param aLength The number of bytes to truncate from the right.
	 */
	void truncateTail( int aLength );

	/**
	 * Builder method for the {@link #append(byte...)} method.
	 * 
	 * @param aBytes The bytes to be appended.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withAppend( byte... aBytes ) {
		append( aBytes );
		return this;
	}

	/**
	 * Builder method for the {@link #append(byte...)} method.
	 * 
	 * @param aBytes The bytes to be appended.
	 * @param aOffset The offset from where to start collecting the bytes.
	 * @param aLength The number of bytes to be appended.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withAppend( byte[] aBytes, int aOffset, int aLength ) {
		append( aBytes, aOffset, aLength );
		return this;
	}

	/**
	 * Builder method for the {@link #append(Sequence)} method.
	 * 
	 * @param aSequence The {@link Sequence} to be appended.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withAppend( Sequence aSequence ) {
		append( aSequence );
		return this;
	}

	/**
	 * Builder method for the {@link #concatenate(ConcatenateMode, byte...)}
	 * method.
	 * 
	 * @param aConcatenateMode The concatenation mode to be used.
	 * @param aBytes The bytes to be concatenated with.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withConcatenate( ConcatenateMode aConcatenateMode, byte... aBytes ) {
		concatenate( aConcatenateMode, aBytes );
		return this;
	}

	/**
	 * Builder method for the {@link #concatenate(Sequence, ConcatenateMode)}
	 * method.
	 *
	 * @param aSequence The {@link Sequence} to be concatenated with
	 * @param aConcatenateMode The concatenation mode to be used.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withConcatenate( Sequence aSequence, ConcatenateMode aConcatenateMode ) {
		prepend( aSequence );
		return this;
	}

	/**
	 * Builder method for the {@link #overwrite(byte[])} method.
	 * 
	 * @param aBytes The byte array where to copy the bytes from.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withOverwrite( byte[] aBytes ) {
		overwrite( 0, aBytes );
		return this;
	}

	/**
	 * Builder method for the {@link #overwrite(Sequence, int)} method.
	 * 
	 * @param aBytes The bytes where to copy the bytes from.
	 * @param aLength The number of bytes to be copied starting at offset 0.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withOverwrite( byte[] aBytes, int aLength ) {
		overwrite( aBytes, aLength );
		return this;
	}

	/**
	 * Builder method for the {@link #overwrite(int, byte[])} method.
	 * 
	 * @param aOffset The offset where to start writing the bytes to.
	 * @param aBytes The byte array where to copy the bytes from.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withOverwrite( int aOffset, byte[] aBytes ) {
		overwrite( aOffset, aBytes );
		return this;
	}

	/**
	 * Builder method for the {@link #overwrite(int, byte[], int, int)} method.
	 * 
	 * @param aOffset The offset where to start writing the bytes to.
	 * @param aBytes The byte array where to copy the bytes from.
	 * @param aBytesOffset The offset in the byte array where to start copying.
	 * @param aLength The number of bytes to be copied.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withOverwrite( int aOffset, byte[] aBytes, int aBytesOffset, int aLength ) {
		overwrite( aOffset, aBytes, aBytesOffset, aLength );
		return this;
	}

	/**
	 * Builder method for the {@link #overwrite(int, Sequence)} method.
	 * 
	 * @param aOffset The offset where to start writing the bytes to.
	 * @param aSequence The {@link Sequence} where to copy the bytes from.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withOverwrite( int aOffset, Sequence aSequence ) {
		overwrite( aOffset, aSequence );
		return this;
	}

	/**
	 * Builder method for the {@link #overwrite(int, Sequence, int, int)}
	 * method.
	 * 
	 * @param aOffset The offset where to start writing the bytes to.
	 * @param aSequence The {@link Sequence} where to copy the bytes from.
	 * @param aSequenceOffset The offset in the byte array where to start
	 *        copying.
	 * @param aLength The number of bytes to be copied.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withOverwrite( int aOffset, Sequence aSequence, int aSequenceOffset, int aLength ) {
		overwrite( aOffset, aSequence, aSequenceOffset, aLength );
		return this;
	}

	/**
	 * Builder method for the {@link #overwrite(Sequence)} method.
	 * 
	 * @param aSequence The {@link Sequence} where to copy the bytes from.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withOverwrite( Sequence aSequence ) {
		overwrite( 0, aSequence );
		return this;
	}

	/**
	 * Builder method for the {@link #overwrite(Sequence, int)} method.
	 * 
	 * @param aSequence The {@link Sequence} where to copy the bytes from.
	 * @param aLength The number of bytes to be copied starting at offset 0.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withOverwrite( Sequence aSequence, int aLength ) {
		overwrite( aSequence, aLength );
		return this;
	}

	/**
	 * Builder method for the {@link #prepend(byte...)} method.
	 * 
	 * @param aBytes The bytes to be prepended.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withPrepend( byte... aBytes ) {
		prepend( aBytes );
		return this;
	}

	/**
	 * Builder method for the {@link #prepend(byte...)} method.
	 * 
	 * @param aBytes The bytes to be prepended.
	 * @param aOffset The offset from where to start collecting the bytes.
	 * @param aLength The number of bytes to be prepended.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withPrepend( byte[] aBytes, int aOffset, int aLength ) {
		prepend( aBytes, aOffset, aLength );
		return this;
	}

	/**
	 * Builder method for the {@link #prepend(Sequence)} method.
	 * 
	 * @param aSequence The {@link Sequence} to be prepended.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withPrepend( Sequence aSequence ) {
		prepend( aSequence );
		return this;
	}

	/**
	 * Builder method for the {@link #replace(byte[])} method.
	 * 
	 * @param aBytes The byte array where to copy the bytes from.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withReplace( byte[] aBytes ) {
		replace( aBytes );
		return this;
	}

	/**
	 * Builder method for the {@link #replace(byte[], int, int)} method.
	 * 
	 * @param aBytes The byte array where to copy the bytes from.
	 * @param aLength The number of bytes to be copied starting at offset 0.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withReplace( byte[] aBytes, int aLength ) {
		replace( aBytes, 0, aLength );
		return this;
	}

	/**
	 * Builder method for the {@link #replace(Sequence, int, int)} method.
	 * 
	 * @param aSequence The byte {@link Sequence} where to copy the bytes from.
	 * @param aLength The number of bytes to be copied starting at offset 0.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withReplace( Sequence aSequence, int aLength ) {
		replace( aSequence, 0, aLength );
		return this;
	}

	/**
	 * Builder method for the {@link #replace(byte[], int, int)} method.
	 * 
	 * @param aBytes The byte array where to copy the bytes from.
	 * @param aOffset The offset in the byte array where to start copying.
	 * @param aLength The number of bytes to be copied.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withReplace( byte[] aBytes, int aOffset, int aLength ) {
		replace( aBytes, aOffset, aLength );
		return this;
	}

	/**
	 * Builder method for the {@link #replace(Sequence)} method.
	 * 
	 * @param aSequence The {@link Sequence} where to copy the bytes from.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withReplace( Sequence aSequence ) {
		replace( aSequence );
		return this;
	}

	/**
	 * Builder method for the {@link #replace(Sequence, int, int)} method.
	 * 
	 * @param aSequence The {@link Sequence} where to copy the bytes from.
	 * @param aOffset The offset in the byte array where to start copying.
	 * @param aLength The number of bytes to be copied.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withReplace( Sequence aSequence, int aOffset, int aLength ) {
		replace( aSequence, aOffset, aLength );
		return this;
	}

	/**
	 * Builder method for the {@link #truncate(int, TruncateMode)} method.
	 * 
	 * @param aLength The number of bytes to truncate according to the
	 *        {@link TruncateMode}.
	 * @param aTruncateMode The {@link TruncateMode} to use for truncating the
	 *        {@link Sequence}.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withTruncate( int aLength, TruncateMode aTruncateMode ) {
		truncate( aLength, aTruncateMode );
		return this;
	}

	/**
	 * Builder method for the {@link #truncateHead(int)} method.
	 * 
	 * @param aLength The number of bytes to truncate.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withTruncateHead( int aLength ) {
		truncateHead( aLength );
		return this;
	}

	/**
	 * Builder method for the {@link #truncateTail(int)} method.
	 * 
	 * @param aLength The number of bytes to truncate.
	 * 
	 * @return This instance as of the builder pattern.
	 */
	default Sequence withTruncateTail( int aLength ) {
		truncateTail( aLength );
		return this;
	}

	/**
	 * Writes the content of the Sequence to the provided {@link OutputStream}.
	 * 
	 * @param aOutputStream The {@link OutputStream} where to write to.
	 * 
	 * @throws IOException thrown in case of I/O problems.
	 */
	void writeTo( OutputStream aOutputStream ) throws IOException;

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy