/*
* 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.model.Byteable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.ObjectOutput;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Map;
import java.util.RandomAccess;
/**
* @author peter.lawrey
*/
public interface RandomDataOutput extends ObjectOutput, RandomAccess, BytesCommon {
/**
* Copies the contents of a RandomDataInput from the position to the limit.
*
* <p> This method transfers the bytes remaining in the given source
* buffer into this buffer. If there are more bytes remaining in the
* source buffer than in this buffer, that is, if
* <tt>src.remaining()</tt> <tt>></tt> <tt>remaining()</tt>,
* then no bytes are transferred and a {@link
* java.nio.BufferOverflowException} is thrown.
*
* <p> Otherwise, this method copies
* <i>n</i> = <tt>src.remaining()</tt> bytes from the given
* buffer into this buffer, starting at each buffer's current position.
* The positions of both buffers are then incremented by <i>n</i>.
*
* <p> In other words, an invocation of this method of the form
* <tt>dst.write(src)</tt> has exactly the same effect as the loop
*
* <pre>
* while (src.hasRemaining())
* dst.writeByte(src.readByte());
* </pre>
* @param bytes to copy
*/
void write(RandomDataInput bytes);
/**
* Copy from one Bytes to another, moves the position of "this" RandomDataOutput by the length.
* The position of the RandomDataInput is not used or altered.
*
* @param bytes to copy
* @param position to copy from
* @param length to copy
*/
void write(RandomDataInput bytes, long position, long length);
/**
* Copies the contents of a Byteable from the offset for maxSize bytes, moves the position of "this" RandomDataOutput by the maxSize
*
* @param byteable to copy
*/
void write(@NotNull Byteable byteable);
/**
* Writes to the output stream the eight low-order bits of the argument <code>b</code>. The 24 high-order bits of
* <code>b</code> are ignored.
*
* @param b the byte to be written.
*/
@Override
void write(int b);
/**
* Writes to the output stream the eight low- order bits of the argument <code>v</code>. The 24 high-order bits of
* <code>v</code> are ignored. (This means that <code>writeByte</code> does exactly the same thing as
* <code>write</code> for an integer argument.) The byte written by this method may be read by the
* <code>readByte</code> method of interface <code>DataInput</code>, which will then return a <code>byte</code>
* equal to <code>(byte)v</code>.
*
* @param v the byte value to be written.
*/
@Override
void writeByte(int v);
/**
* Writes to the output stream the eight low- order bits of the argument <code>v</code>. The 24 high-order bits of
* <code>v</code> are ignored. (This means that <code>writeByte</code> does exactly the same thing as
* <code>write</code> for an integer argument.) The byte written by this method may be read by the
* <code>readUnsignedByte</code> method of interface <code>DataInput</code>, which will then return a
* <code>byte</code> equal to <code>(byte)v</code>.
*
* @param v the byte value to be written.
*/
void writeUnsignedByte(int v);
/**
* Writes to the output stream the eight low-order bits of the argument <code>b</code>. The 24 high-order bits of
* <code>b</code> are ignored.
*
* @param offset to write byte
* @param b the byte to be written.
*/
void writeByte(long offset, int b);
/**
* Writes to the output stream the eight low- order bits of the argument <code>v</code>. The 24 high-order bits of
* <code>v</code> are ignored. (This means that <code>writeByte</code> does exactly the same thing as
* <code>write</code> for an integer argument.) The byte written by this method may be read by the
* <code>readUnsignedByte</code> method of interface <code>DataInput</code>, which will then return a
* <code>byte</code> equal to <code>v & 0xFF</code>.
*
* @param offset to write byte
* @param v the unsigned byte value to be written.
*/
void writeUnsignedByte(long offset, int v);
/**
* Writes to the output stream all the bytes in array <code>bytes</code>. If <code>bytes</code> is
* <code>null</code>, a <code>NullPointerException</code> is thrown. If <code>bytes.length</code> is zero, then no
* bytes are written. Otherwise, the byte <code>bytes[0]</code> is written first, then <code>bytes[1]</code>, and so
* on; the last byte written is <code>bytes[bytes.length-1]</code>.
*
* @param bytes the data.
*/
@Override
void write(byte[] bytes);
/**
* Writes to the output stream all the bytes in array <code>bytes</code>. If <code>bytes</code> is
* <code>null</code>, a <code>NullPointerException</code> is thrown. If <code>bytes.length</code> is zero, then no
* bytes are written. Otherwise, the byte <code>bytes[0]</code> is written first, then <code>bytes[1]</code>, and so
* on; the last byte written is <code>bytes[bytes.length-1]</code>.
*
* @param offset to be written
* @param bytes the data.
*/
void write(long offset, byte[] bytes);
void write(long offset, Bytes bytes);
/**
* Writes <code>len</code> bytes from array <code>bytes</code>, in order, to the output stream. If
* <code>bytes</code> is <code>null</code>, a <code>NullPointerException</code> is thrown. If <code>off</code> is
* negative, or <code>len</code> is negative, or <code>off+len</code> is greater than the length of the array
* <code>bytes</code>, then an <code>IndexOutOfBoundsException</code> is thrown. If <code>len</code> is zero, then
* no bytes are written. Otherwise, the byte <code>bytes[off]</code> is written first, then
* <code>bytes[off+1]</code>, and so on; the last byte written is <code>bytes[off+len-1]</code>.
*
* @param bytes the data.
* @param off the start offset in the data.
* @param len the number of bytes to write.
*/
@Override
void write(byte[] bytes, int off, int len);
void write(long offset, byte[] bytes, int off, int len);
void write(@NotNull char[] data);
void write(@NotNull char[] data, int off, int len);
/**
* Writes a <code>boolean</code> value to this output stream. If the argument <code>v</code> is <code>true</code>,
* the value <code>(byte)1</code> is written; if <code>v</code> is <code>false</code>, the value
* <code>(byte)0</code> is written. The byte written by this method may be read by the <code>readBoolean</code>
* method of interface <code>DataInput</code>, which will then return a <code>boolean</code> equal to
* <code>v</code>.
*
* @param v the boolean to be written.
*/
@Override
void writeBoolean(boolean v);
/**
* Writes a <code>boolean</code> value to this output stream. If the argument <code>v</code> is <code>true</code>,
* the value <code>(byte)1</code> is written; if <code>v</code> is <code>false</code>, the value
* <code>(byte)0</code> is written. The byte written by this method may be read by the <code>readBoolean</code>
* method of interface <code>DataInput</code>, which will then return a <code>boolean</code> equal to
* <code>v</code>.
*
* @param offset to write boolean
* @param v the boolean to be written.
*/
void writeBoolean(long offset, boolean v);
/**
* Writes two bytes to the output stream to represent the value of the argument. The byte values to be written, in
* the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code> </pre> <p>
* The bytes written by this method may be read by the <code>readShort</code> method of interface
* <code>DataInput</code> , which will then return a <code>short</code> equal to <code>(short)v</code>.
*
* @param v the <code>short</code> value to be written.
*/
@Override
void writeShort(int v);
/**
* Writes two bytes to the output stream to represent the value of the argument. The byte values to be written, in
* the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code> </pre> <p>
* The bytes written by this method may be read by the <code>readShort</code> method of interface
* <code>DataInput</code> , which will then return a <code>short</code> equal to <code>(short)v</code>.
*
* @param offset to be written to
* @param v the <code>short</code> value to be written.
*/
void writeShort(long offset, int v);
/**
* Writes two bytes to the output stream to represent the value of the argument. The byte values to be written, in
* the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code> </pre> <p>
* The bytes written by this method may be read by the <code>readUnsignedShort</code> method of interface
* <code>RandomDataInput</code> , which will then return a <code>short</code> equal to <code>(short)v</code>.
*
* @param v the unsigned <code>short</code> value to be written.
*/
void writeUnsignedShort(int v);
/**
* Writes two bytes to the output stream to represent the value of the argument. The byte values to be written, in
* the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code> </pre> <p>
* The bytes written by this method may be read by the <code>readShort</code> method of interface
* <code>RandomDataInput</code> , which will then return a <code>short</code> equal to <code>(short)v</code>.
*
* @param offset to be written to
* @param v the unsigned <code>short</code> value to be written.
*/
void writeUnsignedShort(long offset, int v);
/**
* Writes one or three bytes as follows; Short.MIN_VALUE => Byte.MIN_VALUE, Short.MAX_VALUE => Byte.MAX_VALUE,
* Short.MIN_VALUE+2 to Short.MAX_VALUE-1 => writeByte(x), default => writeByte(Byte.MIN_VALUE+1;
* writeShort(x)
*
* <p>The bytes written by this method may be read by the <code>readCompactShort</code> method of interface
* <code>RandomDataInput</code> , which will then return a <code>short</code> equal to <code>(short)v</code>.
*
* @param v the <code>short</code> value to be written.
*/
void writeCompactShort(int v);
/**
* Writes one or three bytes as follows; 0 to 254 => writeByte(x); otherwise writeByte(255); writeByteShort(x);
*
* <p>The bytes written by this method may be read by the <code>readCompactUnsignedShort</code> method of interface
* <code>RandomDataInput</code> , which will then return a <code>short</code> equal to <code>v & 0xFFFF</code>.
*
* @param v the unsigned <code>short</code> value to be written.
*/
void writeCompactUnsignedShort(int v);
/**
* Writes a <code>char</code> value, which is comprised of two bytes, to the output stream. The byte values to be
* written, in the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code></pre><p>
* The bytes written by this method may be read by the <code>readChar</code> method of interface
* <code>DataInput</code> , which will then return a <code>char</code> equal to <code>(char)v</code>.
*
* @param v the <code>char</code> value to be written.
*/
@Override
void writeChar(int v);
/**
* Writes a <code>char</code> value, which is comprised of two bytes, to the output stream. The byte values to be
* written, in the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code></pre><p>
* The bytes written by this method may be read by the <code>readChar</code> method of interface
* <code>DataInput</code> , which will then return a <code>char</code> equal to <code>(char)v</code>.
*
* @param offset to be written to
* @param v the <code>char</code> value to be written.
*/
void writeChar(long offset, int v);
/**
* Writes an <code>int</code> value, which is comprised of three bytes, to the output stream. The byte values to be
* written, in the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 16))
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code></pre><p>
* The bytes written by this method may be read by the <code>readInt24</code> method of interface
* <code>RandomDataInput</code> , which will then return an <code>int</code> equal to <code>v</code>.
*
* @param v the <code>int</code> value to be written.
*/
void writeInt24(int v);
/**
* Writes an <code>int</code> value, which is comprised of three bytes, to the output stream. The byte values to be
* written, in the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 16))
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code></pre><p>
* The bytes written by this method may be read by the <code>readInt24</code> method of interface
* <code>RandomDataInput</code> , which will then return an <code>int</code> equal to <code>v</code>.
*
* @param offset to be written to
* @param v the <code>int</code> value to be written.
*/
void writeInt24(long offset, int v);
/**
* Writes an <code>int</code> value, which is comprised of four bytes, to the output stream. The byte values to be
* written, in the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 24))
* (byte)(0xff & (v >> 16))
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code></pre><p>
* The bytes written by this method may be read by the <code>readInt</code> method of interface
* <code>DataInput</code> , which will then return an <code>int</code> equal to <code>v</code>.
*
* @param v the <code>int</code> value to be written.
*/
@Override
void writeInt(int v);
/**
* Writes an <code>int</code> value, which is comprised of four bytes, to the output stream. The byte values to be
* written, in the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 24))
* (byte)(0xff & (v >> 16))
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code></pre><p>
* The bytes written by this method may be read by the <code>readInt</code> method of interface
* <code>DataInput</code> , which will then return an <code>int</code> equal to <code>v</code>.
*
* @param offset to be written to
* @param v the <code>int</code> value to be written.
*/
void writeInt(long offset, int v);
/**
* Writes an <code>int</code> value, which is comprised of four bytes, to the output stream. The byte values to be
* written, in the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 24))
* (byte)(0xff & (v >> 16))
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code></pre><p>
* The bytes written by this method may be read by the <code>readUnsignedInt</code> method of interface
* <code>RandomDataInput</code> , which will then return an <code>long</code> equal to <code>v &
* 0xFFFFFFFF</code>.
*
* @param v the <code>int</code> value to be written.
*/
void writeUnsignedInt(long v);
/**
* Writes an <code>int</code> value, which is comprised of four bytes, to the output stream. The byte values to be
* written, in the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 24))
* (byte)(0xff & (v >> 16))
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code></pre><p>
* The bytes written by this method may be read by the <code>readUnsignedInt</code> method of interface
* <code>RandomDataInput</code> , which will then return an <code>long</code> equal to <code>v &
* 0xFFFFFFFF</code>.
*
* @param offset to be written to
* @param v the <code>int</code> value to be written.
*/
void writeUnsignedInt(long offset, long v);
/**
* Writes two or six bytes as follows; Integer.MIN_VALUE => Short.MIN_VALUE, Integer.MAX_VALUE =>
* Short.MAX_VALUE, Short.MIN_VALUE+2 to Short.MAX_VALUE-1 => writeShort(x), default =>
* writeShort(Short.MIN_VALUE+1; writeInt(x)
*
* <p>The bytes written by this method may be read by the <code>readCompactInt</code> method of interface
* <code>RandomDataInput</code> , which will then return a <code>int</code> equal to <code>v</code>.
*
* @param v the <code>int</code> value to be written.
*/
void writeCompactInt(int v);
/**
* Writes two or six bytes as follows; 0 to (1 << 16) - 2 => writeInt(x), otherwise writeShort(-1);
* writeInt(x)
*
* <p>The bytes written by this method may be read by the <code>readCompactUnsignedInt</code> method of interface
* <code>RandomDataInput</code> , which will then return a <code>int</code> equal to <code>v &
* 0xFFFFFFFF</code>.
*
* @param v the <code>short</code> value to be written.
*/
void writeCompactUnsignedInt(long v);
/**
* Same as writeInt but include an ordered write barrier. This means all writes will be visible on a read barrier
* if this write is visible. This might not be visible to be same thread for some clock cycles so an immediate read
* could see an old value
*
* <p>This is much faster than a volatile write which stalls the pipeline. The data is visible to other threads at the
* same time.
*
* @param v value to write
*/
void writeOrderedInt(int v);
/**
* Same as writeInt but include an ordered write barrier. This means all writes will be visible on a read barrier
* if this write is visible. This might not be visible to be same thread for some clock cycles so an immediate read
* could see an old value
*
* <p>This is much faster than <code>writeVolatileInt</code> as the volatile write stalls the pipeline. The data is
* visible to other threads at the same time.
*
* @param offset to write to
* @param v value to write
*/
void writeOrderedInt(long offset, int v);
/**
* Perform a compare and set operation. The value is set to <code>x</code> provided the <code>expected</code> value
* is set already. This operation is atomic.
*
* @param offset to write to.
* @param expected to expect
* @param x to set if expected was found
* @return true if set, false if the value was not expected
*/
boolean compareAndSwapInt(long offset, int expected, int x);
/**
* Atomically adds the given value to the current value.
*
* @param offset of the int value to use.
* @param delta the value to add
* @return the previous value
*/
int getAndAdd(long offset, int delta);
/**
* Atomically adds the given value to the current value.
*
* @param offset of the int value to use.
* @param delta the value to add
* @return the updated value
*/
int addAndGetInt(long offset, int delta);
/**
* Writes a <code>long</code> value, which is comprised of eight bytes, to the output stream. The byte values to be
* written, in the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 40))
* (byte)(0xff & (v >> 32))
* (byte)(0xff & (v >> 24))
* (byte)(0xff & (v >> 16))
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code></pre><p>
* The bytes written by this method may be read by the <code>readInt48</code> method of interface
* <code>RandomDataInput</code> , which will then return a <code>long</code> equal to <code>v & ((1L << 48)
* - 1)</code>.
*
* @param v the <code>long</code> value to be written.
*/
void writeInt48(long v);
/**
* Writes a <code>long</code> value, which is comprised of eight bytes, to the output stream. The byte values to be
* written, in the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 40))
* (byte)(0xff & (v >> 32))
* (byte)(0xff & (v >> 24))
* (byte)(0xff & (v >> 16))
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code></pre><p>
* The bytes written by this method may be read by the <code>readInt48</code> method of interface
* <code>RandomDataInput</code> , which will then return a <code>long</code> equal to <code>v & ((1L << 48)
* - 1)</code>.
*
* @param offset to be written to
* @param v the <code>long</code> value to be written.
*/
void writeInt48(long offset, long v);
/**
* Writes a <code>long</code> value, which is comprised of eight bytes, to the output stream. The byte values to be
* written, in the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 56))
* (byte)(0xff & (v >> 48))
* (byte)(0xff & (v >> 40))
* (byte)(0xff & (v >> 32))
* (byte)(0xff & (v >> 24))
* (byte)(0xff & (v >> 16))
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code></pre><p>
* The bytes written by this method may be read by the <code>readLong</code> method of interface
* <code>DataInput</code> , which will then return a <code>long</code> equal to <code>v</code>.
*
* @param v the <code>long</code> value to be written.
*/
@Override
void writeLong(long v);
/**
* Writes a <code>long</code> value, which is comprised of eight bytes, to the output stream. The byte values to be
* written, in the order shown for big endian machines and the opposite for little endian, are:
* <pre><code>
* (byte)(0xff & (v >> 56))
* (byte)(0xff & (v >> 48))
* (byte)(0xff & (v >> 40))
* (byte)(0xff & (v >> 32))
* (byte)(0xff & (v >> 24))
* (byte)(0xff & (v >> 16))
* (byte)(0xff & (v >> 8))
* (byte)(0xff & v)
* </code></pre><p>
* The bytes written by this method may be read by the <code>readLong</code> method of interface
* <code>DataInput</code> , which will then return a <code>long</code> equal to <code>v</code>.
*
* @param offset to be written to
* @param v the <code>long</code> value to be written.
*/
void writeLong(long offset, long v);
/**
* Writes four or twelve bytes as follows Long.MIN_VALUE => Integer.MIN_VALUE, Long.MAX_VALUE =>
* Integer.MAX_VALUE, Integer.MIN_VALUE+2 to Integer.MAX_VALUE-1 => writeInt(x), default =>
* writeInt(Integer.MIN_VALUE+1; writeLong(x)
*
* <p>The bytes written by this method may be read by the <code>readCompactLong</code> method of interface
* <code>RandomDataInput</code> , which will then return a <code>long</code> equal to <code>v</code>.
*
* @param v the <code>long</code> value to be written.
*/
void writeCompactLong(long v);
/**
* Same as writeLong but include an ordered write barrier. This means all writes will be visible on a read barrier
* if this write is visible. This might not be visible to be same thread for some clock cycles so an immediate read
* could see an old value
*
* <p>This is much faster than a volatile write which stalls the pipeline. The data is visible to other threads at the
* same time.
*
* @param v value to write
*/
void writeOrderedLong(long v);
/**
* Same as writeLong but include an ordered write barrier. This means all writes will be visible on a read barrier
* if this write is visible. This might not be visible to be same thread for some clock cycles so an immediate read
* could see an old value
*
* <p>This is much faster than a volatile write which stalls the pipeline. The data is visible to other threads at the
* same time.
*
* @param offset to be written to
* @param v value to write
*/
void writeOrderedLong(long offset, long v);
/**
* Perform a compare and set operation. The value is set to <code>x</code> provided the <code>expected</code> value
* is set already. This operation is atomic.
*
* @param offset to write to.
* @param expected to expect
* @param x to set if expected was found
* @return true if set, false if the value was not expected
*/
boolean compareAndSwapLong(long offset, long expected, long x);
/**
* Perform a compare and set operation. The value is set to <code>x</code> provided the <code>expected</code> value
* is set already. This operation is atomic.
*
* @param offset to write to.
* @param expected to expect
* @param x to set if expected was found
* @return true if set, false if the value was not expected
*/
boolean compareAndSwapDouble(long offset, double expected, double x);
/**
* Stop bit encoding numbers. This will write the same number of bytes
* whether you used a byte, short or int.
*
* @param n the number to write
*/
void writeStopBit(long n);
/**
* Writes a <code>float</code> value, which is comprised of four bytes, to the output stream. It does this as if it
* first converts this <code>float</code> value to an <code>int</code> in exactly the manner of the
* <code>Float.floatToIntBits</code> method and then writes the <code>int</code> value in exactly the manner of the
* <code>writeInt</code> method. The bytes written by this method may be read by the <code>readFloat</code> method
* of interface <code>DataInput</code>, which will then return a <code>float</code> equal to <code>v</code>.
*
* @param v the <code>float</code> value to be written.
*/
@Override
void writeFloat(float v);
/**
* Writes a <code>float</code> value, which is comprised of four bytes, to the output stream. It does this as if it
* first converts this <code>float</code> value to an <code>int</code> in exactly the manner of the
* <code>Float.floatToIntBits</code> method and then writes the <code>int</code> value in exactly the manner of the
* <code>writeInt</code> method. The bytes written by this method may be read by the <code>readFloat</code> method
* of interface <code>DataInput</code>, which will then return a <code>float</code> equal to <code>v</code>.
*
* @param offset to write to
* @param v the <code>float</code> value to be written.
*/
void writeFloat(long offset, float v);
/**
* Same as writeFloat but include an ordered write barrier. This means all writes will be visible on a read barrier
* if this write is visible. This might not be visible to be same thread for some clock cycles so an immediate read
* could see an old value
*
* <p>This is much faster than a volatile write which stalls the pipeline. The data is visible to other threads at the
* same time.
*
* @param offset to write to
* @param v value to write
*/
void writeOrderedFloat(long offset, float v);
/**
* Writes a <code>double</code> value, which is comprised of eight bytes, to the output stream. It does this as if
* it first converts this <code>double</code> value to a <code>long</code> in exactly the manner of the
* <code>Double.doubleToLongBits</code> method and then writes the <code>long</code> value in exactly the manner of
* the <code>writeLong</code> method. The bytes written by this method may be read by the <code>readDouble</code>
* method of interface <code>DataInput</code>, which will then return a <code>double</code> equal to
* <code>v</code>.
*
* @param v the <code>double</code> value to be written.
*/
@Override
void writeDouble(double v);
/**
* Writes a <code>double</code> value, which is comprised of eight bytes, to the output stream. It does this as if
* it first converts this <code>double</code> value to a <code>long</code> in exactly the manner of the
* <code>Double.doubleToLongBits</code> method and then writes the <code>long</code> value in exactly the manner of
* the <code>writeLong</code> method. The bytes written by this method may be read by the <code>readDouble</code>
* method of interface <code>DataInput</code>, which will then return a <code>double</code> equal to
* <code>v</code>.
*
* @param offset to write to
* @param v the <code>double</code> value to be written.
*/
void writeDouble(long offset, double v);
/**
* <p>
* Writes four or twelve bytes as follow;
* </p><pre><code>
* if ((float) d == d) {
* writeFloat((float) d);
* } else {
* writeFloat(Float.NaN);
* writeDouble(d);
* }
* </code></pre>
* The bytes written by this method may be read by the <code>readCompactDouble</code> method of interface
* <code>RandomDataInput</code> , which will then return a <code>double</code> equal to <code>v</code>.
*
* @param v the <code>double</code> value to be written.
*/
void writeCompactDouble(double v);
/**
* Same as writeDouble but include an ordered write barrier. This means all writes will be visible on a read
* barrier if this write is visible. This might not be visible to be same thread for some clock cycles so an
* immediate read could see an old value
*
* <p>This is much faster than a volatile write which stalls the pipeline. The data is visible to other threads at the
* same time.
*
* @param offset to write to
* @param v value to write
*/
void writeOrderedDouble(long offset, double v);
/**
* Writes a string to the output stream. For every character in the string <code>s</code>, taken in order, one byte
* is written to the output stream. If <code>s</code> is <code>null</code>, a <code>NullPointerException</code> is
* thrown.<p> If <code>s.length</code> is zero, then no bytes are written. Otherwise, the character
* <code>s[0]</code> is written first, then <code>s[1]</code>, and so on; the last character written is
* <code>s[s.length-1]</code>. For each character, one byte is written, the low-order byte, in exactly the manner of
* the <code>writeByte</code> method . The high-order eight bits of each character in the string are ignored.
*
* @param s the string of bytes to be written. Cannot be null.
*/
@Override
void writeBytes(@NotNull String s);
/**
* Writes every character in the string <code>s</code>, to the output stream, in order, two bytes per character. If
* <code>s</code> is <code>null</code>, a <code>NullPointerException</code> is thrown. If <code>s.length</code> is
* zero, then no characters are written. Otherwise, the character <code>s[0]</code> is written first, then
* <code>s[1]</code>, and so on; the last character written is <code>s[s.length-1]</code>. For each character, two
* bytes are actually written, high-order byte first, in exactly the manner of the <code>writeChar</code> method.
*
* @param s the string value to be written. Cannot be null.
* @see #writeChars(CharSequence)
*/
@Override
void writeChars(@NotNull String s);
/**
* Writes chars of the given {@code CharSequence} to the bytes, without encoding.
*
* @param cs the {@code CharSequence} to be written. Cannot be null.
* @see #writeChars(String)
*/
void writeChars(@NotNull CharSequence cs);
/**
* Writes two bytes of length information to the output stream, followed by the <a
* href="DataInput.html#modified-utf-8">modified UTF-8</a> representation of every character in the string
* <code>s</code>. If <code>s</code> is <code>null</code>, a <code>NullPointerException</code> is thrown. Each
* character in the string <code>s</code> is converted to a group of one, two, or three bytes, depending on the
* value of the character.<p> If a character <code>c</code> is in the range <code>\u0001</code> through
* <code>\u007f</code>, it is represented by one byte:
* <pre>(byte)c </pre> <p>
* If a character <code>c</code> is <code>\u0000</code> or is in the range <code>\u0080</code> through
* <code>\u07ff</code>, then it is represented by two bytes, to be written
* in the order shown:<pre><code>
* (byte)(0xc0 | (0x1f & (c >> 6)))
* (byte)(0x80 | (0x3f & c))
* </code></pre> <p> If a character
* <code>c</code> is in the range <code>\u0800</code> through <code>uffff</code>, then it is represented by
* three bytes, to be written
* in the order shown:<pre><code>
* (byte)(0xe0 | (0x0f & (c >> 12)))
* (byte)(0x80 | (0x3f & (c >> 6)))
* (byte)(0x80 | (0x3f & c))
* </code></pre> <p> First,
* the total number of bytes needed to represent all the characters of <code>s</code> is calculated. If this number
* is larger than <code>65535</code>, then a <code>UTFDataFormatException</code> is thrown. Otherwise, this length
* is written to the output stream in exactly the manner of the <code>writeShort</code> method; after this, the
* one-, two-, or three-byte representation of each character in the string <code>s</code> is written.<p> The bytes
* written by this method may be read by the <code>readUTF</code> method of interface <code>DataInput</code> , which
* will then return a <code>String</code> equal to <code>s</code>.
*
* @param s the string value to be written. Cannot be null
*/
@Override
void writeUTF(@NotNull String s);
/**
* Write the same encoding as <code>writeUTF</code> with the following changes. 1) The length is stop bit encoded
* i.e. one byte longer for short strings, but is not limited in length. 2) The string can be null.
*
* @param s the string value to be written. Can be null.
* @throws IllegalArgumentException if there is not enough space left
*/
void writeUTFΔ(@Nullable CharSequence s) throws IllegalArgumentException;
/**
* Write the same encoding as <code>writeUTF</code> with the following changes. 1) The length is stop bit encoded
* i.e. one byte longer for short strings, but is not limited in length. 2) The string can be null.
*
* @param offset to write to
* @param maxSize maximum number of bytes to use
* @param s the string value to be written. Can be null.
* @throws IllegalStateException if the size is too large.
*/
void writeUTFΔ(long offset, int maxSize, @Nullable CharSequence s) throws IllegalStateException;
void write8bitText(@Nullable CharSequence s);
/**
* Copies the contents of a ByteBuffer from the position to the limit.
*
* <p> This method transfers the bytes remaining in the given source
* buffer into this buffer. If there are more bytes remaining in the
* source buffer than in this buffer, that is, if
* <tt>src.remaining()</tt> <tt>></tt> <tt>remaining()</tt>,
* then no bytes are transferred and a {@link
* java.nio.BufferOverflowException} is thrown.
*
* <p> Otherwise, this method copies
* <i>n</i> = <tt>src.remaining()</tt> bytes from the given
* buffer into this buffer, starting at each buffer's current position.
* The positions of both buffers are then incremented by <i>n</i>.
*
* <p> In other words, an invocation of this method of the form
* <tt>dst.write(src)</tt> has exactly the same effect as the loop
*
* <pre>
* while (src.hasRemaining())
* dst.writeByte(src.get());
* </pre>
*
* @param bb to copy.
*/
void write(@NotNull ByteBuffer bb);
/**
* Write the object in a form which can be uniquely recreated by readEnum. This type of "enumerable objects" has
* the following constraints; 1) each object must have a one to one mapping with a toString() representation, 2) be
* immutable, 3) ideally appears more than once, 4) Must have a constructor which takes a single String or a
* <code>valueOf(String)</code> method.
*
* @param e to enumerate
* @param <E> element class
*/
<E> void writeEnum(@Nullable E e);
/**
* Write an ordered collection of "enumerable objects" (See writeEnum). This writes the stop bit encoded length,
* followed by multiple calls to <code>writeEnum</code> All the elements must be of the same type.
*
* <p>This can be read by the <code>readList</code> method of <code>RandomInputStream</code> and the reader must know
* the type of each element. You can send the class first by using <code>writeEnum</code> of the element class
*
* @param <E> the class of the list elements
* @param list to be written
*/
<E> void writeList(@NotNull Collection<E> list);
/**
* Write the keys and values of a Map of "enumerable objects" (See writeEnum). This writes the stop bit encoded
* length, followed by multiple calls to <code>writeEnum</code> for each key and value. All the keys must be of the
* same type. All values must be of the same type.
*
* @param <K> the class of the map keys
* @param <V> the class of the map values
* @param map to write out
*/
<K, V> void writeMap(@NotNull Map<K, V> map);
// ObjectOutput
/**
* Write an object as either an "enumerable object" or a Serializable/Externalizable object using Java
* Serialization. Java Serialization is <i>much</i> slower but sometimes more convenient than using
* BytesMarshallable.
*
* @param object to write
*/
@Override
void writeObject(@Nullable Object object);
/**
* Write an object with the assumption that the objClass will be provided when the class is read.
*
* @param <OBJ> the class of the object to write
* @param objClass class to write
* @param obj to write
*/
<OBJ> void writeInstance(@NotNull Class<OBJ> objClass, @NotNull OBJ obj);
/**
* Copy data from an Object from bytes start to end.
*
* @param object to copy from
* @param start first byte inclusive
* @param end last byte exclusive.
*/
void writeObject(Object object, int start, int end);
/**
* fill the Bytes with zeros, and clear the position.
*
* @return this
*/
Bytes zeroOut();
/**
* fill the Bytes with zeros.
*
* @param start first byte to zero out
* @param end the first byte after the last to zero out (exclusive bound)
* @return this
*/
Bytes zeroOut(long start, long end);
/**
* fill the Bytes with zeros, and clear the position, avoiding touching pages unnecessarily
*
* @param start first byte to zero out
* @param end the first byte after the last to zero out (exclusive bound)
* @param ifNotZero only set to zero after checking the value is not zero.
* @return this
*/
Bytes zeroOut(long start, long end, boolean ifNotZero);
/**
* Check the end of the stream has not overflowed. Otherwise this doesn't do anything.
*/
@Override
void flush();
/**
* The same as calling finish();
*/
@Override
void close();
void writeEnum(long offset, int len, Object object);
}