All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.yahoo.slime.BinaryDecoder Maven / Gradle / Ivy
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.slime;
import static com.yahoo.slime.BinaryFormat.decode_double;
import static com.yahoo.slime.BinaryFormat.decode_meta;
import static com.yahoo.slime.BinaryFormat.decode_type;
import static com.yahoo.slime.BinaryFormat.decode_zigzag;
final class BinaryDecoder {
BufferedInput in;
private final SlimeInserter slimeInserter = new SlimeInserter(null);
private final ArrayInserter arrayInserter = new ArrayInserter(null);
private final ObjectSymbolInserter objectInserter = new ObjectSymbolInserter(null, 0);
public BinaryDecoder() {}
public Slime decode(byte[] bytes) {
return decode(bytes, 0, bytes.length);
}
public Slime decode(byte[] bytes, int offset, int length) {
Slime slime = new Slime();
in = new BufferedInput(bytes, offset, length);
decodeSymbolTable(in, slime.symbolTable());
decodeValue(slimeInserter.adjust(slime));
if (in.failed()) {
slime.wrap("partial_result");
slime.get().setData("offending_input", in.getOffending());
slime.get().setString("error_message", in.getErrorMessage());
}
return slime;
}
long read_bytes_le(int bytes) {
long value = 0;
int shift = 0;
for (int i = 0; i < bytes; ++i) {
long b = in.getByte();
value |= (b & 0xff) << shift;
shift += 8;
}
return value;
}
long read_bytes_be(int bytes) {
long value = 0;
int shift = 56;
for (int i = 0; i < bytes; ++i) {
long b = in.getByte();
value |= (b & 0xff) << shift;
shift -= 8;
}
return value;
}
Cursor decodeNIX(Inserter inserter) {
return inserter.insertNIX();
}
Cursor decodeBOOL(Inserter inserter, int meta) {
return inserter.insertBOOL(meta != 0);
}
Cursor decodeLONG(Inserter inserter, int meta) {
long encoded = read_bytes_le(meta);
return inserter.insertLONG(decode_zigzag(encoded));
}
Cursor decodeDOUBLE(Inserter inserter, int meta) {
long encoded = read_bytes_be(meta);
return inserter.insertDOUBLE(decode_double(encoded));
}
Cursor decodeSTRING(Inserter inserter, int meta) {
int size = in.read_size(meta);
byte[] image = in.getBytes(size);
return inserter.insertSTRING(image);
}
Cursor decodeDATA(Inserter inserter, int meta) {
int size = in.read_size(meta);
byte[] image = in.getBytes(size);
return inserter.insertDATA(image);
}
Cursor decodeARRAY(Inserter inserter, int meta) {
Cursor cursor = inserter.insertARRAY();
int size = in.read_size(meta);
for (int i = 0; i < size; ++i) {
decodeValue(arrayInserter.adjust(cursor));
}
return cursor;
}
Cursor decodeOBJECT(Inserter inserter, int meta) {
Cursor cursor = inserter.insertOBJECT();
int size = in.read_size(meta);
for (int i = 0; i < size; ++i) {
int symbol = in.read_cmpr_int();
decodeValue(objectInserter.adjust(cursor, symbol));
}
return cursor;
}
Cursor decodeValue(Inserter inserter, Type type, int meta) {
switch (type) {
case NIX: return decodeNIX(inserter);
case BOOL: return decodeBOOL(inserter, meta);
case LONG: return decodeLONG(inserter, meta);
case DOUBLE: return decodeDOUBLE(inserter, meta);
case STRING: return decodeSTRING(inserter, meta);
case DATA: return decodeDATA(inserter, meta);
case ARRAY: return decodeARRAY(inserter, meta);
case OBJECT: return decodeOBJECT(inserter, meta);
}
assert false : "should not be reached";
return null;
}
void decodeValue(Inserter inserter) {
byte b = in.getByte();
Cursor cursor = decodeValue(inserter, decode_type(b), decode_meta(b));
if (!cursor.valid()) {
in.fail("failed to decode value");
}
}
static void decodeSymbolTable(BufferedInput input, SymbolTable names) {
int numSymbols = input.read_cmpr_int();
final byte[] backing = input.getBacking();
for (int i = 0; i < numSymbols; ++i) {
int size = input.read_cmpr_int();
int offset = input.getPosition();
input.skip(size);
int symbol = names.insert(Utf8Codec.decode(backing, offset, size));
if (symbol != i) {
input.fail("duplicate symbols in symbol table");
return;
}
}
}
}