mirror of
https://github.com/OpenHFT/Chronicle-Map.git
synced 2021-09-13 01:26:12 +00:00
HCOLL-136 HCOLL-137 Improved BytesReader, BytesWriter and BytesInterop docs [dc]
This commit is contained in:
@@ -22,15 +22,30 @@ import net.openhft.lang.io.Bytes;
|
||||
import net.openhft.lang.model.Byteable;
|
||||
|
||||
/**
|
||||
* Marshaller for byte sequences, which are copied to off-heap {@link Bytes}
|
||||
* in a very straightforward manner, e. g. {@link Byteable Byteables}, {@code byte[]} arrays,
|
||||
* {@code Bytes} themselves. The criterion of this interface applicability --
|
||||
* {@link Object#equals(Object)} implementation shouldn't require deserialization and any garbage creation.
|
||||
* Writer for objects, which themselves are bytes sequence in some sense:
|
||||
* {@link Byteable Byteables}, {@code byte[]} arrays, other primitive arrays, "flat" objects
|
||||
* (with primitives fields only), particularly boxed primitive types.
|
||||
*
|
||||
* <p>This interface is called "BytesInterop" because it allows to work with object as they
|
||||
* are already marshalled to {@code Bytes}: {@linkplain #startsWith(Bytes, Object) compare}
|
||||
* with other {@code Bytes}, i. e. interoperate objects and {@code Bytes}.
|
||||
*
|
||||
* @param <E> type of marshalled objects
|
||||
*/
|
||||
public interface BytesInterop<E> extends BytesWriter<E> {
|
||||
|
||||
/**
|
||||
* Checks if the given {@code bytes} starts (from the {@code bytes}' {@linkplain
|
||||
* Bytes#position() position}) with the byte sequence the given object
|
||||
* {@linkplain #write(Bytes, Object) is serialized} to, without actual serialization.
|
||||
*
|
||||
* @param bytes the bytes to check if starts with the serialized form of the given object.
|
||||
* {@code bytes}' is positioned at the first byte to compare. {@code bytes}' limit
|
||||
* is unspecified. {@code bytes}' position and limit shouldn't be altered during
|
||||
* this call.
|
||||
* @param e the object to serialize virtually and compare with the given {@code bytes}
|
||||
* @return if the given {@code bytes} starts with the given {@code e} object's serialized form
|
||||
*/
|
||||
boolean startsWith(Bytes bytes, E e);
|
||||
|
||||
long hash(E e);
|
||||
|
||||
@@ -18,13 +18,86 @@
|
||||
|
||||
package net.openhft.chronicle.hash.serialization;
|
||||
|
||||
import net.openhft.chronicle.hash.ChronicleHash;
|
||||
import net.openhft.lang.io.Bytes;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Deserializer (object from {@link Bytes}, mirroring the {@link BytesWriter}, i. e. assuming the
|
||||
* length of the serialized form isn't written in the beginning of the serialized form itself,
|
||||
* but managed by {@link ChronicleHash} implementation and passed to the reading methods.
|
||||
*
|
||||
* <p>Implementation example:<pre><code>
|
||||
* class LongPair { long first, second; }
|
||||
*
|
||||
* enum LongPairArrayReader implements BytesReader<LongPair[]> {
|
||||
* INSTANCE;
|
||||
*
|
||||
* @Override
|
||||
* public LongPair[] read(Bytes bytes, long size) {
|
||||
* return read(bytes, size, null);
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public LongPair[] read(Bytes bytes, long size, LongPair[] toReuse) {
|
||||
* int resLen = (int) (size / 16L);
|
||||
* LongPair[] res;
|
||||
* if (toReuse != null) {
|
||||
* if (toReuse.length == resLen) {
|
||||
* res = toReuse;
|
||||
* } else {
|
||||
* res = Arrays.copyOf(toReuse, resLen);
|
||||
* }
|
||||
* } else {
|
||||
* res = new LongPair[resLen];
|
||||
* }
|
||||
* for (int i = 0; i < resLen; i++) {
|
||||
* LongPair pair = res[i];
|
||||
* if (pair == null)
|
||||
* res[i] = pair = new LongPair();
|
||||
* pair.first = bytes.readLong();
|
||||
* pair.second = bytes.readLong();
|
||||
* }
|
||||
* return res;
|
||||
* }
|
||||
* }</code></pre>
|
||||
*
|
||||
* @param <E> the type of the object demarshalled
|
||||
* @see BytesWriter
|
||||
*/
|
||||
public interface BytesReader<E> extends Serializable {
|
||||
|
||||
/**
|
||||
* Reads and returns the object from {@code [position(), position() + size]} bytes of the given
|
||||
* {@link Bytes}.
|
||||
*
|
||||
* <p>Implementation of this method should increment the {@code bytes}' position by the given
|
||||
* size, i. e. "consume" the bytes of the deserialized object. It must not alter the
|
||||
* {@code bytes}' {@link Bytes#limit() limit} and contents.
|
||||
*
|
||||
* @param bytes the {@code Bytes} to read the object from
|
||||
* @param size the size of the serialized form of the returned object
|
||||
* @return the object read from the bytes
|
||||
* @see BytesWriter#write(Bytes, Object)
|
||||
* @see #read(Bytes, long, Object)
|
||||
*/
|
||||
E read(Bytes bytes, long size);
|
||||
|
||||
E read(Bytes bytes, long size, E e);
|
||||
/**
|
||||
* Similar to {@link #read(Bytes, long)}, but should attempt to reuse the given object, i. e.
|
||||
* to read the deserialized data into the given instance. If it is possible, this objects than
|
||||
* returned from this method. If it isn't possible for any reason, a new object should be
|
||||
* created and returned, just like in {@link #read(Bytes, long)} method. The given object could
|
||||
* be {@code null}, in this case this method should behave exactly the same as
|
||||
* {@link #read(Bytes, long)} method does.
|
||||
*
|
||||
* @param bytes the {@code Bytes} to read the object from
|
||||
* @param size the size of the serialized form of the returned object
|
||||
* @param toReuse the object to read the deserialized data into
|
||||
* @return the object read from the bytes, either reused or newly created
|
||||
* @see #read(Bytes, long)
|
||||
*/
|
||||
E read(Bytes bytes, long size, @Nullable E toReuse);
|
||||
}
|
||||
|
||||
@@ -18,13 +18,66 @@
|
||||
|
||||
package net.openhft.chronicle.hash.serialization;
|
||||
|
||||
import net.openhft.chronicle.hash.ChronicleHash;
|
||||
import net.openhft.lang.io.Bytes;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Serializer (object to {@link Bytes} writer) which 1) knows the length of serialized form
|
||||
* of any object before actual serialization 2) doesn't include that length in the serialized
|
||||
* form itself, assuming it will be passed by the {@link ChronicleHash} into
|
||||
* {@link BytesReader#read(Bytes, long)} deserialization method.
|
||||
*
|
||||
* <p>Implementation example: <pre><code>
|
||||
* class LongPair { long first, second; }
|
||||
*
|
||||
* enum LongPairArrayWriter implements BytesWriter<LongPair[]> {
|
||||
* INSTANCE;
|
||||
*
|
||||
* @Override
|
||||
* public long size(LongPair[] longPairs) {
|
||||
* return longPairs.length * 16L;
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public void write(Bytes bytes, LongPair[] longPairs) {
|
||||
* for (LongPair pair : longPairs) {
|
||||
* bytes.writeLong(pair.first);
|
||||
* bytes.writeLong(pair.second);
|
||||
* }
|
||||
* }
|
||||
* }</code></pre>
|
||||
*
|
||||
* @param <E> the type of the object marshalled
|
||||
* @see BytesReader
|
||||
* @see BytesInterop
|
||||
*/
|
||||
public interface BytesWriter<E> extends Serializable {
|
||||
|
||||
/**
|
||||
* Returns the length (in bytes) of the serialized form of the given object. Serialization form
|
||||
* in terms of this interface, i. e. how much bytes are written to {@code bytes} on
|
||||
* {@link #write(Bytes, Object) write(bytes, e)} call.
|
||||
*
|
||||
* @param e the object which serialized form length should be returned
|
||||
* @return the length (in bytes) of the serialized form of the given object
|
||||
*/
|
||||
long size(E e);
|
||||
|
||||
/**
|
||||
* Serializes the given object to the given {@code bytes}, without writing the length of the
|
||||
* serialized form itself.
|
||||
*
|
||||
* <p>Implementation of this method should increment the {@code bytes}' {@linkplain
|
||||
* Bytes#position() position} by {@link #size(Object) size(e)}. The given object should
|
||||
* be written into these range between the initial {@code bytes}' position and the position
|
||||
* after this method call returns. Implementation of this method must not alter the
|
||||
* {@code bytes}' {@linkplain Bytes#limit() limit} and contents outside of the specified range.
|
||||
*
|
||||
* @param bytes the {@code Bytes} to write the given object to
|
||||
* @param e the object to serialize to the given bytes
|
||||
* @see BytesReader#read(Bytes, long)
|
||||
*/
|
||||
void write(Bytes bytes, E e);
|
||||
}
|
||||
|
||||
+6
-6
@@ -16,7 +16,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.openhft.chronicle.hash.serialization.impl;
|
||||
package net.openhft.chronicle.hash.serialization.internal;
|
||||
|
||||
import net.openhft.chronicle.hash.serialization.BytesInterop;
|
||||
import net.openhft.chronicle.hash.serialization.BytesReader;
|
||||
@@ -59,10 +59,10 @@ public enum ByteArrayMarshaller implements BytesInterop<byte[]>, BytesReader<byt
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] read(Bytes bytes, long size, byte[] ba) {
|
||||
if (ba == null || size != ba.length)
|
||||
ba = new byte[(int) size];
|
||||
bytes.read(ba);
|
||||
return ba;
|
||||
public byte[] read(Bytes bytes, long size, byte[] toReuse) {
|
||||
if (toReuse == null || size != toReuse.length)
|
||||
toReuse = new byte[(int) size];
|
||||
bytes.read(toReuse);
|
||||
return toReuse;
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -16,7 +16,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.openhft.chronicle.hash.serialization.impl;
|
||||
package net.openhft.chronicle.hash.serialization.internal;
|
||||
|
||||
import net.openhft.chronicle.hash.serialization.AgileBytesMarshaller;
|
||||
import net.openhft.chronicle.hash.serialization.Hasher;
|
||||
@@ -114,13 +114,13 @@ public class ByteableMarshaller<E extends Byteable> implements AgileBytesMarshal
|
||||
}
|
||||
|
||||
@Override
|
||||
public E read(Bytes bytes, long size, E e) {
|
||||
public E read(Bytes bytes, long size, E toReuse) {
|
||||
try {
|
||||
if (e == null)
|
||||
e = getInstance();
|
||||
setBytesAndOffset(e, bytes);
|
||||
if (toReuse == null)
|
||||
toReuse = getInstance();
|
||||
setBytesAndOffset(toReuse, bytes);
|
||||
bytes.skip(size);
|
||||
return e;
|
||||
return toReuse;
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
+17
-3
@@ -16,13 +16,27 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.openhft.chronicle.hash.serialization;
|
||||
package net.openhft.chronicle.hash.serialization.internal;
|
||||
|
||||
import net.openhft.chronicle.hash.serialization.BytesReader;
|
||||
import net.openhft.lang.io.Bytes;
|
||||
import net.openhft.lang.io.serialization.BytesMarshaller;
|
||||
|
||||
/**
|
||||
* Utility methods returning {@link BytesReader} implementations.
|
||||
*/
|
||||
public final class BytesReaders {
|
||||
|
||||
/**
|
||||
* Returns a {@link BytesReader} wrapping the given {@link BytesMarshaller}. One of the
|
||||
* bridge methods between general serialization API from {@link net.openhft.lang} and
|
||||
* reader - writer - interop API, specific for ChronicleHashes,
|
||||
* from {@link net.openhft.chronicle.hash.serialization} package.
|
||||
*
|
||||
* @param marshaller the actual reading implementation
|
||||
* @param <E> type of the objects marshalled
|
||||
* @return a {@code BytesReader} wrapping the given {@code BytesMarshaller}
|
||||
*/
|
||||
public static <E> BytesReader<E> fromBytesMarshaller(BytesMarshaller<E> marshaller) {
|
||||
return new SimpleBytesReader<E>(marshaller);
|
||||
}
|
||||
@@ -42,8 +56,8 @@ public final class BytesReaders {
|
||||
}
|
||||
|
||||
@Override
|
||||
public E read(Bytes bytes, long size, E e) {
|
||||
return marshaller.read(bytes, e);
|
||||
public E read(Bytes bytes, long size, E toReuse) {
|
||||
return marshaller.read(bytes, toReuse);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -16,7 +16,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.openhft.chronicle.hash.serialization.impl;
|
||||
package net.openhft.chronicle.hash.serialization.internal;
|
||||
|
||||
import net.openhft.chronicle.hash.serialization.BytesInterop;
|
||||
import net.openhft.chronicle.hash.serialization.BytesReader;
|
||||
@@ -49,11 +49,11 @@ public enum CharArrayMarshaller implements BytesInterop<char[]>, BytesReader<cha
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] read(Bytes bytes, long size, char[] chars) {
|
||||
if (chars == null || chars.length != size)
|
||||
chars = new char[(int) size];
|
||||
bytes.readFully(chars);
|
||||
return chars;
|
||||
public char[] read(Bytes bytes, long size, char[] toReuse) {
|
||||
if (toReuse == null || toReuse.length != size)
|
||||
toReuse = new char[(int) size];
|
||||
bytes.readFully(toReuse);
|
||||
return toReuse;
|
||||
}
|
||||
|
||||
@Override
|
||||
+10
-10
@@ -16,7 +16,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.openhft.chronicle.hash.serialization.impl;
|
||||
package net.openhft.chronicle.hash.serialization.internal;
|
||||
|
||||
import net.openhft.chronicle.hash.serialization.BytesReader;
|
||||
import net.openhft.lang.io.AbstractBytes;
|
||||
@@ -78,14 +78,14 @@ public final class CharSequenceReader<S extends CharSequence>
|
||||
}
|
||||
|
||||
@Override
|
||||
public S read(Bytes bytes, long size, S s) {
|
||||
public S read(Bytes bytes, long size, S toReuse) {
|
||||
Appendable appendable;
|
||||
if (s instanceof Appendable) {
|
||||
appendable = (Appendable) s;
|
||||
if (s instanceof StringBuilder) {
|
||||
((StringBuilder) s).setLength(0);
|
||||
} else if (s instanceof StringBuffer) {
|
||||
((StringBuffer) s).setLength(0);
|
||||
if (toReuse instanceof Appendable) {
|
||||
appendable = (Appendable) toReuse;
|
||||
if (toReuse instanceof StringBuilder) {
|
||||
((StringBuilder) toReuse).setLength(0);
|
||||
} else if (toReuse instanceof StringBuffer) {
|
||||
((StringBuffer) toReuse).setLength(0);
|
||||
}
|
||||
} else {
|
||||
sb.setLength(0);
|
||||
@@ -96,8 +96,8 @@ public final class CharSequenceReader<S extends CharSequence>
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
if (appendable == s)
|
||||
return s;
|
||||
if (appendable == toReuse)
|
||||
return toReuse;
|
||||
return interner.intern(sb);
|
||||
}
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.openhft.chronicle.hash.serialization.impl;
|
||||
package net.openhft.chronicle.hash.serialization.internal;
|
||||
|
||||
import net.openhft.chronicle.hash.serialization.BytesWriter;
|
||||
import net.openhft.lang.io.AbstractBytes;
|
||||
+2
-2
@@ -16,7 +16,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.openhft.chronicle.hash.serialization.impl;
|
||||
package net.openhft.chronicle.hash.serialization.internal;
|
||||
|
||||
import net.openhft.chronicle.hash.serialization.AgileBytesMarshaller;
|
||||
import net.openhft.chronicle.hash.serialization.Hasher;
|
||||
@@ -68,7 +68,7 @@ public enum DoubleMarshaller implements AgileBytesMarshaller<Double> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double read(Bytes bytes, long size, Double e) {
|
||||
public Double read(Bytes bytes, long size, Double toReuse) {
|
||||
return read(bytes, size);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -16,7 +16,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.openhft.chronicle.hash.serialization.impl;
|
||||
package net.openhft.chronicle.hash.serialization.internal;
|
||||
|
||||
import net.openhft.chronicle.hash.serialization.AgileBytesMarshaller;
|
||||
import net.openhft.chronicle.hash.serialization.Hasher;
|
||||
@@ -66,7 +66,7 @@ public enum IntegerMarshaller implements AgileBytesMarshaller<Integer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer read(Bytes bytes, long size, Integer e) {
|
||||
public Integer read(Bytes bytes, long size, Integer toReuse) {
|
||||
return bytes.readInt();
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -16,7 +16,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.openhft.chronicle.hash.serialization.impl;
|
||||
package net.openhft.chronicle.hash.serialization.internal;
|
||||
|
||||
import net.openhft.chronicle.hash.serialization.AgileBytesMarshaller;
|
||||
import net.openhft.chronicle.hash.serialization.Hasher;
|
||||
@@ -66,7 +66,7 @@ public enum LongMarshaller implements AgileBytesMarshaller<Long> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long read(Bytes bytes, long size, Long e) {
|
||||
public Long read(Bytes bytes, long size, Long toReuse) {
|
||||
return bytes.readLong();
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -16,7 +16,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.openhft.chronicle.hash.serialization.impl;
|
||||
package net.openhft.chronicle.hash.serialization.internal;
|
||||
|
||||
import net.openhft.chronicle.hash.serialization.AgileBytesMarshaller;
|
||||
import net.openhft.lang.io.Bytes;
|
||||
@@ -66,7 +66,7 @@ public enum VoidMarshaller implements AgileBytesMarshaller<Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void read(Bytes bytes, long size, Void aVoid) {
|
||||
public Void read(Bytes bytes, long size, Void toReuse) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2014 Higher Frequency Trading http://www.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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Classes, which should be part of the parent {@code net.openhft.chronicle.hash.serialization}
|
||||
* package, but shouldn't be used in the user code (in 99% of cases). This package isn't
|
||||
* documented in published javadocs.
|
||||
*/
|
||||
package net.openhft.chronicle.hash.serialization.internal;
|
||||
@@ -21,7 +21,7 @@ package net.openhft.chronicle.map;
|
||||
import net.openhft.lang.threadlocal.Provider;
|
||||
import net.openhft.lang.threadlocal.ThreadLocalCopies;
|
||||
import net.openhft.chronicle.hash.serialization.*;
|
||||
import net.openhft.chronicle.hash.serialization.impl.*;
|
||||
import net.openhft.chronicle.hash.serialization.internal.*;
|
||||
import net.openhft.lang.io.Bytes;
|
||||
import net.openhft.lang.io.serialization.BytesMarshallable;
|
||||
import net.openhft.lang.io.serialization.BytesMarshaller;
|
||||
|
||||
@@ -42,7 +42,7 @@ enum DummyValueMarshaller implements AgileBytesMarshaller<DummyValue> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DummyValue read(Bytes bytes, long size, DummyValue dummyValue) {
|
||||
public DummyValue read(Bytes bytes, long size, DummyValue toReuse) {
|
||||
return DUMMY_VALUE;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user