blob: a4e6f495cc9aef74caa425c96bcccacb5ae33cf6 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package io.v.v23.vom;
import io.v.v23.vdl.VdlType;
import io.v.v23.vdl.VdlValue;
import io.v.v23.verror.VException;
import io.v.v23.vom.BinaryDecoder;
import io.v.v23.vom.BinaryEncoder;
import io.v.v23.vom.ConversionException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Type;
/**
* VomUtil contains convenience methods for VOM-encoding/decoding.
*/
public class VomUtil {
/**
* VOM-encodes the provided value using a new VOM-encoder.
*
* @param value value to be encoded
* @param type type of the provided value
* @return VOM-encoded value as a byte array
* @throws VException if there was an error encoding the value
*/
public static byte[] encode(Object value, Type type) throws VException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
BinaryEncoder encoder = new BinaryEncoder(out);
try {
encoder.encodeValue(type, value);
} catch (IOException e) {
VException ve = new VException(e.getMessage());
ve.initCause(e);
throw ve;
}
return out.toByteArray();
}
/**
* VOM-encodes the provided value using a new VOM-encoder.
*
* @param value value to be encoded
* @param type type of the provided value
* @return VOM-encoded value as a byte array
* @throws VException if there was an error encoding the value
*/
public static byte[] encode(Object value, VdlType type) throws VException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
BinaryEncoder encoder = new BinaryEncoder(out);
try {
encoder.encodeValue(type, value);
} catch (IOException e) {
VException ve = new VException(e.getMessage());
ve.initCause(e);
throw ve;
}
return out.toByteArray();
}
/**
* VOM-encodes the provided value using a new VOM-encoder, returning a hex-encoded string.
*
* @param value value to be encoded
* @param type type of the provided value
* @return VOM-encoded value in a hex-string format
* @throws VException if there was an error encoding the value
*/
public static String encodeToString(Object value, Type type) throws VException {
byte[] data = encode(value, type);
return bytesToHexString(data);
}
/**
* VOM-encodes the provided VDL value using a new VOM-encoder.
*
* @param value VDL value to be encoded
* @return VOM-encoded value as a byte array
* @throws VException if there was an error encoding the value
*/
public static byte[] encode(VdlValue value) throws VException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
BinaryEncoder encoder = new BinaryEncoder(out);
try {
encoder.encodeValue(value);
} catch (IOException e) {
VException ve = new VException(e.getMessage());
ve.initCause(e);
throw ve;
}
return out.toByteArray();
}
/**
* VOM-decodes the provided data using a new VOM-decoder.
*
* @param data VOM-encoded data
* @param type type of the object that the data should be decoded into
* @return VOM-decoded object
* @throws VException if there was an error decoding the data
*/
public static Object decode(byte[] data, Type type) throws VException {
BinaryDecoder decoder = new BinaryDecoder(new ByteArrayInputStream(data));
try {
return decoder.decodeValue(type);
} catch (IOException e) {
VException ve = new VException(e.getMessage());
ve.initCause(e);
throw ve;
} catch (ConversionException e) {
VException ve = new VException(e.getMessage());
ve.initCause(e);
throw ve;
}
}
/**
* VOM-decodes the provided data using a new VOM-decoder. A best effort is made to deduce the
* type of the encoded data.
*
* @param data VOM-encoded data
* @return VOM-decoded object
* @throws VException if there was an error decoding the data
*/
public static Object decode(byte[] data) throws VException {
BinaryDecoder decoder = new BinaryDecoder(new ByteArrayInputStream(data));
try {
return decoder.decodeValue();
} catch (IOException e) {
VException ve = new VException(e.getMessage());
ve.initCause(e);
throw ve;
} catch (ConversionException e) {
VException ve = new VException(e.getMessage());
ve.initCause(e);
throw ve;
}
}
/**
* VOM-decodes the provided data (stored as a hex string) using a new VOM-decoder.
*
* @param hex VOM-encoded data, stored as a hex string
* @param type type of the object that the data should be decoded into
* @return VOM-decoded object
* @throws VException if there was an error decoding the data
*/
public static Object decodeFromString(String hex, Type type) throws VException {
byte[] data = hexStringToBytes(hex);
return decode(data, type);
}
/**
* Returns a {@link VdlValue} corresponding to the given Java object of the provided type.
*
* @param obj a java object
* @param type type of the provided object
* @return {@link VdlValue} corresponding to the given Java object
* @throws VException if the {@link VdlValue} couldn't be computed.
*/
public static VdlValue valueOf(Object obj, Type type) throws VException {
byte[] data = VomUtil.encode(obj, type);
return (VdlValue) VomUtil.decode(data, VdlValue.class);
}
/**
* Returns a {@link VdlValue} corresponding to the given Java object of the provided type.
*
* @param obj a java object
* @param type type of the provided object
* @return {@link VdlValue} corresponding to the given Java object
* @throws VException if the {@link VdlValue} couldn't be computed.
*/
public static VdlValue valueOf(Object obj, VdlType type) throws VException {
byte[] data = VomUtil.encode(obj, type);
return (VdlValue) VomUtil.decode(data, VdlValue.class);
}
/**
* Encodes the provided byte array of data as a hex string.
*
* @param data arbitrary byte array
* @return hex string representation of the byte array
*/
public static String bytesToHexString(byte[] data) {
StringBuilder builder = new StringBuilder();
for (byte b : data) {
builder.append(String.format("%02x", b));
}
return builder.toString();
}
/**
* Decodes the provided data (stored as a hex string) into a byte array.
*
* @param hex hex string encoding of a byte array
* (encoded using {@link #bytesToHexString})
* @return decoded byte array
* @throws VException if there was an error decoding the hex string
*/
public static byte[] hexStringToBytes(String hex) throws VException {
if (hex.length() % 2 != 0) {
throw new VException("Hex strings must be multiples of 2 in length");
}
int outLen = hex.length() / 2;
byte[] dat = new byte[outLen];
for (int i = 0; i < outLen; i++) {
dat[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
}
return dat;
}
}