/*
* Copyright (c) 2015-2016, Christoph Engelbert (aka noctarius) and
* contributors. All rights reserved.
*
* 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 com.noctarius.tengi.spi.serialization.codec.impl;
import com.noctarius.tengi.core.impl.Validate;
import com.noctarius.tengi.core.serialization.debugger.SerializationDebugger;
import com.noctarius.tengi.spi.buffer.MemoryBuffer;
import com.noctarius.tengi.spi.buffer.ReadableMemoryBuffer;
import com.noctarius.tengi.spi.buffer.WritableMemoryBuffer;
import com.noctarius.tengi.spi.serialization.Protocol;
import com.noctarius.tengi.spi.serialization.codec.Codec;
import com.noctarius.tengi.spi.serialization.codec.impl.utf8.UTF8Codec;
public class DefaultCodec
implements Codec {
private final SerializationDebugger debugger = SerializationDebugger.instance();
private final Protocol protocol;
private MemoryBuffer memoryBuffer;
public DefaultCodec setMemoryBuffer(MemoryBuffer memoryBuffer) {
this.memoryBuffer = memoryBuffer;
return this;
}
public DefaultCodec(Protocol protocol) {
this(protocol, null);
}
public DefaultCodec(Protocol protocol, MemoryBuffer memoryBuffer) {
this.protocol = protocol;
this.memoryBuffer = memoryBuffer;
}
@Override
public void readBytes(byte[] bytes) {
memoryBuffer.readBytes(bytes);
}
@Override
public void readBytes(byte[] bytes, int offset, int length) {
memoryBuffer.readBytes(bytes, offset, length);
}
@Override
public boolean readBoolean() {
return memoryBuffer.readByte() == 0 ? false : true;
}
@Override
public boolean[] readBitSet() {
return BitSetCompressor.readBitSet(memoryBuffer);
}
@Override
public byte readByte() {
return memoryBuffer.readByte();
}
@Override
public short readUnsignedByte() {
return (short) (memoryBuffer.readByte() & 0xFF);
}
@Override
public short readShort() {
return ByteOrderUtils.getShort(memoryBuffer);
}
@Override
public char readChar() {
return (char) readShort();
}
@Override
public int readInt32() {
return ByteOrderUtils.getInt(memoryBuffer);
}
@Override
public int readCompressedInt32() {
return Int32Compressor.readInt32(memoryBuffer);
}
@Override
public long readInt64() {
return ByteOrderUtils.getLong(memoryBuffer);
}
@Override
public long readCompressedInt64() {
return Int64Compressor.readInt64(memoryBuffer);
}
@Override
public float readFloat() {
return Float.intBitsToFloat(readInt32());
}
@Override
public double readDouble() {
return Double.longBitsToDouble(readInt64());
}
@Override
public String readString() {
try {
// TODO Pool buffers
return UTF8Codec.readUTF(this, new byte[1024]);
} catch (Exception e) {
RuntimeException ex = new IndexOutOfBoundsException(e.getLocalizedMessage());
ex.setStackTrace(e.getStackTrace());
throw ex;
}
}
@Override
public <O> O readObject()
throws Exception {
if (SerializationDebugger.Debugger.ENABLED) {
debugger.push(protocol, this);
}
O object = protocol.readObject("object", this);
if (SerializationDebugger.Debugger.ENABLED) {
debugger.pop();
}
return object;
}
@Override
public <O> O readNullableObject()
throws Exception {
return protocol.readNullable(this, (d, p) -> {
if (SerializationDebugger.Debugger.ENABLED) {
debugger.push(protocol, d);
}
O object = readObject();
if (SerializationDebugger.Debugger.ENABLED) {
debugger.pop();
}
return object;
});
}
@Override
public ReadableMemoryBuffer getReadableMemoryBuffer() {
return memoryBuffer;
}
@Override
public void writeBytes(byte[] bytes) {
memoryBuffer.writeBytes(bytes);
}
@Override
public void writeBytes(byte[] bytes, int offset, int length) {
memoryBuffer.writeBytes(bytes, offset, length);
}
@Override
public void writeBoolean(boolean value) {
memoryBuffer.writeByte(value ? 1 : 0);
}
@Override
public void writeBitSet(boolean[] values) {
BitSetCompressor.writeBitSet(values, memoryBuffer);
}
@Override
public void writeByte(int value) {
memoryBuffer.writeByte(value);
}
@Override
public void writeUnsignedByte(short value) {
Validate.greaterOrEqual("value", 0, value);
Validate.lowerOrEqual("value", 255, value);
memoryBuffer.writeByte(value);
}
@Override
public void writeShort(short value) {
ByteOrderUtils.putShort(value, memoryBuffer);
}
@Override
public void writeChar(char value) {
writeShort((short) value);
}
@Override
public void writeInt32(int value) {
ByteOrderUtils.putInt(value, memoryBuffer);
}
@Override
public void writeCompressedInt32(int value) {
Int32Compressor.writeInt32(value, memoryBuffer);
}
@Override
public void writeInt64(long value) {
ByteOrderUtils.putLong(value, memoryBuffer);
}
@Override
public void writeCompressedInt64(long value) {
Int64Compressor.writeInt64(value, memoryBuffer);
}
@Override
public void writeFloat(float value) {
writeInt32(Float.floatToRawIntBits(value));
}
@Override
public void writeDouble(double value) {
writeInt64(Double.doubleToRawLongBits(value));
}
@Override
public void writeString(String value) {
try {
// TODO Pool buffers
UTF8Codec.writeUTF(this, value, new byte[1024]);
} catch (Exception e) {
RuntimeException ex = new IndexOutOfBoundsException(e.getLocalizedMessage());
ex.setStackTrace(e.getStackTrace());
throw ex;
}
}
@Override
public void writeObject(Object object)
throws Exception {
if (SerializationDebugger.Debugger.ENABLED) {
debugger.push(protocol, this, object);
}
protocol.writeObject("object", object, this);
if (SerializationDebugger.Debugger.ENABLED) {
debugger.pop();
}
}
@Override
public void writeNullableObject(Object object)
throws Exception {
protocol.writeNullable(object, this, (o, e, p) -> {
if (SerializationDebugger.Debugger.ENABLED) {
debugger.push(protocol, this, object);
}
writeObject("object", object);
if (SerializationDebugger.Debugger.ENABLED) {
debugger.pop();
}
});
}
@Override
public WritableMemoryBuffer getWritableMemoryBuffer() {
return memoryBuffer;
}
}