/*
* Copyright 2016 higherfrequencytrading.com
*
* 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 net.openhft.lang.io;
import net.openhft.lang.io.serialization.ObjectSerializer;
import net.openhft.lang.model.constraints.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* @author peter.lawrey
*/
public interface BytesCommon {
/**
* @return the offset read/written which must be >= limit()
*/
long position();
/**
* @param position to skip to
* @return this bytes object back
* @throws java.lang.IllegalArgumentException if positions < 0 || position >= limit
*/
Bytes position(long position) throws IllegalArgumentException;
/**
* @return the current limit which must be >= capacity()
*/
long limit();
/**
* @param limit the new limit which must be >= capacity()
* @return this bytes object back
*/
Bytes limit(long limit);
/**
* @return space available
*/
long capacity();
/**
* @return space remaining in bytes
*/
long remaining();
/**
* Mark the end of the message if writing and check we are at the end of the message if reading.
*
* @throws IndexOutOfBoundsException if too much data was written.
*/
void finish() throws IndexOutOfBoundsException;
/**
* @return has finish been called.
*/
boolean isFinished();
/**
* Clears this buffer. The position is set to zero, the limit is set to
* the capacity, and the mark is discarded.
*
* <p> Invoke this method before using a sequence of channel-read or
* <i>put</i> operations to fill this buffer. For example:
* <pre>{@code
* buf.clear(); // Prepare buffer for reading
* in.read(buf); // Read data
* }</pre>
*
* <p>This method does not actually erase the data in the buffer, but it
* is named as if it did because it will most often be used in situations
* in which that might as well be the case. </p>
*
* @return This buffer
*/
Bytes clear();
/**
* Flips this buffer. The limit is set to the current position and then
* the position is set to zero. If the mark is defined then it is
* discarded.
*
* <p> After a sequence of channel-read or <i>put</i> operations, invoke
* this method to prepare for a sequence of channel-write or relative
* <i>get</i> operations. For example:
* <pre>{@code
* buf.put(magic); // Prepend header
* in.read(buf); // Read data into rest of buffer
* buf.flip(); // Flip buffer
* out.write(buf); // Write header + data to channel
* }</pre>
*
* <p> This method is often used in conjunction with the {@link
* java.nio.ByteBuffer#compact compact} method when transferring data from
* one place to another. </p>
*
* @return This buffer
*/
Bytes flip();
/**
* @return Byte order for reading binary
*/
@NotNull
ByteOrder byteOrder();
/**
* @return these Bytes as an InputStream
*/
@NotNull
InputStream inputStream();
/**
* @return these Bytes as an OutputStream
*/
@NotNull
OutputStream outputStream();
/**
* @return the factory for marshallers.
*/
@NotNull
ObjectSerializer objectSerializer();
/**
* @throws IndexOutOfBoundsException if the bounds of the Bytes has been exceeded.
*/
void checkEndOfBuffer() throws IndexOutOfBoundsException;
/**
* Access every page to ensure those pages are in memory.
*
* @return this.
*/
Bytes load();
/**
* Write a portion of the Bytes to an Appendable for printing.
*
* @param sb to append to
* @param start first byte
* @param position where to place a cursor or 0 = none.
* @param end last byte to append.
*/
void toString(Appendable sb, long start, long position, long end);
/**
* Align the position address to a power of 2.
*
* @param alignment power of 2 to align to.
*/
void alignPositionAddr(int alignment);
/**
* Creates a new bytes whose content is a shared subsequence of this bytes'
* content.
*
* <p>The content of the new bytes will start at this bytes' current
* position. Changes to this bytes' content will be visible in the new bytes,
* and vice versa; the two bytes' position and limit values will be
* independent.
*
* <p>The new bytes' position will be zero, its capacity and its limit
* will be the number of bytes remaining in this bytes.
*
* <p>{@code slice()} is equivalent of {@code slice(0, remaining())}.
*
* @return the new bytes
* @see #slice(long, long)
*/
Bytes slice();
/**
* Returns a {@code ByteBuffer} whose content is a shared subsequence of this bytes' content.
*
* <p>The content of the returned {@code ByteBuffer} will start at this bytes' current
* position. Changes to this bytes' content will be visible in the returned {@code ByteBuffer},
* and vice versa; this bytes' and the returned {@code ByteBuffer}'s position and limit values
* will be independent.
*
* <p>The returned {@code ByteBuffer}'s position will be zero, its capacity and its limit
* will be the number of bytes remaining in this bytes.
*
* <p>If this bytes object is able to reuse to given {@code toReuse} {@code ByteBuffer}, it will
* be reused and returned back from this method, otherwise a new {@code ByteBuffer} instance
* is created and returned.
*
* @param toReuse a {@code ByteBuffer} to reuse
* @return a {@code ByteBuffer} view of this {@code Bytes}
* @see #slice()
* @see ByteBuffer#slice()
*/
ByteBuffer sliceAsByteBuffer(@Nullable ByteBuffer toReuse);
/**
* Creates a new bytes whose content is a shared subsequence of this bytes'
* content.
*
* <p>The content of the new bytes will start at this bytes' current
* {@link #position()}{@code + offset}. Changes to this bytes' content
* will be visible in the new bytes, and vice versa; the two bytes'
* position and limit values will be independent.
*
* <p>The new bytes' position will be zero, its capacity and its limit
* will be equal to {@code length}.
*
* <p>{@code offset} can be negative (if current bytes' position is positive)
* and {@code length} can run out of current bytes' limit, the restriction
* is that new bytes' should be within this bytes' absolute bounds.
*
* @param offset relative offset of the new bytes from the current bytes'
* position
* @param length capacity of the new bytes
* @return the new bytes
* @see #slice()
*/
Bytes slice(long offset, long length);
@NotNull
String toDebugString();
String toDebugString(long limit);
String toHexString(long limit);
}