use of net.morimekta.providence.descriptor.PEnumDescriptor in project providence by morimekta.
the class JsonSerializer method parseMapKey.
private Object parseMapKey(String key, PDescriptor keyType) throws SerializerException {
try {
switch(keyType.getType()) {
case BOOL:
if (key.equalsIgnoreCase("true")) {
return Boolean.TRUE;
} else if (key.equalsIgnoreCase("false")) {
return Boolean.FALSE;
}
throw new SerializerException("Invalid boolean value: \"" + Strings.escape(key) + "\"");
case BYTE:
return Byte.parseByte(key);
case I16:
return Short.parseShort(key);
case I32:
return Integer.parseInt(key);
case I64:
return Long.parseLong(key);
case DOUBLE:
try {
JsonTokenizer tokenizer = new JsonTokenizer(new ByteArrayInputStream(key.getBytes(StandardCharsets.US_ASCII)));
JsonToken token = tokenizer.next();
if (!token.isNumber()) {
throw new SerializerException("Unable to parse double from key \"" + key + "\"");
} else if (tokenizer.hasNext()) {
throw new SerializerException("Garbage after double: \"" + key + "\"");
}
return token.doubleValue();
} catch (SerializerException e) {
throw e;
} catch (JsonException | IOException e) {
throw new SerializerException(e, "Unable to parse double from key \"" + key + "\"");
}
case STRING:
return key;
case BINARY:
try {
return Binary.fromBase64(key);
} catch (IllegalArgumentException e) {
throw new SerializerException(e, "Unable to parse Base64 data");
}
case ENUM:
PEnumBuilder<?> eb = ((PEnumDescriptor<?>) keyType).builder();
if (Strings.isInteger(key)) {
eb.setById(Integer.parseInt(key));
} else {
eb.setByName(key);
}
if (readStrict && !eb.valid()) {
throw new SerializerException("\"%s\" is not a known enum value for %s", Strings.escape(key), keyType.getQualifiedName());
}
return eb.build();
case MESSAGE:
PMessageDescriptor<?, ?> st = (PMessageDescriptor<?, ?>) keyType;
if (!st.isSimple()) {
throw new SerializerException("Only simple structs can be used as map key. %s is not.", st.getQualifiedName());
}
ByteArrayInputStream input = new ByteArrayInputStream(key.getBytes(StandardCharsets.UTF_8));
try {
JsonTokenizer tokenizer = new JsonTokenizer(input);
if (JsonToken.kMapStart == tokenizer.expectSymbol("message start", JsonToken.kMapStart, JsonToken.kListStart)) {
return parseMessage(tokenizer, st);
} else {
return parseCompactMessage(tokenizer, st);
}
} catch (JsonException | IOException e) {
throw new SerializerException(e, "Error parsing message key: " + e.getMessage());
}
default:
throw new SerializerException("Illegal key type: %s", keyType.getType());
}
} catch (NumberFormatException nfe) {
throw new SerializerException(nfe, "Unable to parse numeric value %s", key);
}
}
use of net.morimekta.providence.descriptor.PEnumDescriptor in project providence by morimekta.
the class ProvidenceConfigParser method parseFieldValue.
@SuppressWarnings("unchecked")
Object parseFieldValue(Token next, Tokenizer tokenizer, ProvidenceConfigContext context, PDescriptor descriptor, boolean requireEnumValue) throws IOException {
try {
switch(descriptor.getType()) {
case BOOL:
if (TRUE.equals(next.asString())) {
return true;
} else if (FALSE.equals(next.asString())) {
return false;
} else if (next.isReferenceIdentifier()) {
return resolve(context, next, tokenizer, descriptor);
}
break;
case BYTE:
if (next.isReferenceIdentifier()) {
return resolve(context, next, tokenizer, descriptor);
} else if (next.isInteger()) {
return (byte) next.parseInteger();
}
break;
case I16:
if (next.isReferenceIdentifier()) {
return resolve(context, next, tokenizer, descriptor);
} else if (next.isInteger()) {
return (short) next.parseInteger();
}
break;
case I32:
if (next.isReferenceIdentifier()) {
return resolve(context, next, tokenizer, descriptor);
} else if (next.isInteger()) {
return (int) next.parseInteger();
}
break;
case I64:
if (next.isReferenceIdentifier()) {
return resolve(context, next, tokenizer, descriptor);
} else if (next.isInteger()) {
return next.parseInteger();
}
break;
case DOUBLE:
if (next.isReferenceIdentifier()) {
return resolve(context, next, tokenizer, descriptor);
} else if (next.isInteger() || next.isReal()) {
return next.parseDouble();
}
break;
case STRING:
if (next.isReferenceIdentifier()) {
return resolve(context, next, tokenizer, descriptor);
} else if (next.isStringLiteral()) {
return next.decodeLiteral(strict);
}
break;
case BINARY:
if (Token.B64.equals(next.asString())) {
tokenizer.expectSymbol("binary data enclosing start", Token.kParamsStart);
return Binary.fromBase64(tokenizer.readBinary(Token.kParamsEnd));
} else if (Token.HEX.equals(next.asString())) {
tokenizer.expectSymbol("binary data enclosing start", Token.kParamsStart);
return Binary.fromHexString(tokenizer.readBinary(Token.kParamsEnd));
} else if (next.isReferenceIdentifier()) {
return resolve(context, next, tokenizer, descriptor);
}
break;
case ENUM:
{
PEnumDescriptor ed = (PEnumDescriptor) descriptor;
PEnumValue value;
String name = next.asString();
if (next.isInteger()) {
value = ed.findById((int) next.parseInteger());
} else if (next.isIdentifier()) {
value = ed.findByName(name);
if (value == null && context.containsReference(name)) {
value = resolve(context, next, tokenizer, ed);
}
} else if (next.isReferenceIdentifier()) {
value = resolve(context, next, tokenizer, descriptor);
} else {
break;
}
if (value == null && (strict || requireEnumValue)) {
PEnumValue option = null;
if (next.isIdentifier()) {
for (PEnumValue o : ed.getValues()) {
if (o.getName().equalsIgnoreCase(name)) {
option = o;
break;
}
}
}
if (option != null) {
throw new TokenizerException(next, "No such enum value '%s' for %s, did you mean '%s'?", name, ed.getQualifiedName(), option.getName()).setLine(tokenizer.getLine());
}
throw new TokenizerException(next, "No such enum value '%s' for %s.", name, ed.getQualifiedName()).setLine(tokenizer.getLine());
}
return value;
}
case MESSAGE:
if (next.isReferenceIdentifier()) {
return resolve(context, next, tokenizer, descriptor);
} else if (next.isSymbol(Token.kMessageStart)) {
return parseMessage(tokenizer, context, ((PMessageDescriptor) descriptor).builder());
}
break;
case MAP:
{
if (next.isReferenceIdentifier()) {
Map resolved;
try {
// Make sure the reference is to a map.
resolved = resolve(context, next, tokenizer, descriptor);
} catch (ClassCastException e) {
throw new TokenizerException(next, "Reference %s is not a map field ", next.asString()).setLine(tokenizer.getLine());
}
return resolved;
} else if (next.isSymbol(Token.kMessageStart)) {
return parseMapValue(tokenizer, context, (PMap) descriptor, new LinkedHashMap());
}
break;
}
case SET:
{
if (next.isReferenceIdentifier()) {
return resolve(context, next, tokenizer, descriptor);
} else if (next.isSymbol(Token.kListStart)) {
@SuppressWarnings("unchecked") PSet<Object> ct = (PSet) descriptor;
Set<Object> value = new LinkedHashSet<>();
next = tokenizer.expect("set value or end");
while (!next.isSymbol(Token.kListEnd)) {
Object item = parseFieldValue(next, tokenizer, context, ct.itemDescriptor(), strict);
if (item != null) {
value.add(item);
}
// sets require separator, and allows separator after last.
if (tokenizer.expectSymbol("set separator or end", Token.kLineSep1, Token.kListEnd) == Token.kListEnd) {
break;
}
next = tokenizer.expect("set value or end");
}
return ct.builder().addAll(value).build();
}
break;
}
case LIST:
{
if (next.isReferenceIdentifier()) {
return resolve(context, next, tokenizer, descriptor);
} else if (next.isSymbol(Token.kListStart)) {
@SuppressWarnings("unchecked") PList<Object> ct = (PList) descriptor;
PList.Builder<Object> builder = ct.builder();
next = tokenizer.expect("list value or end");
while (!next.isSymbol(Token.kListEnd)) {
Object item = parseFieldValue(next, tokenizer, context, ct.itemDescriptor(), strict);
if (item != null) {
builder.add(item);
}
// lists require separator, and allows separator after last.
if (tokenizer.expectSymbol("list separator or end", Token.kLineSep1, Token.kListEnd) == Token.kListEnd) {
break;
}
next = tokenizer.expect("list value or end");
}
return builder.build();
}
break;
}
default:
{
throw new TokenizerException(next, descriptor.getType() + " not supported!").setLine(tokenizer.getLine());
}
}
} catch (ProvidenceConfigException e) {
throw new TokenizerException(next, e.getMessage()).setLine(tokenizer.getLine());
}
throw new TokenizerException(next, "Unhandled value \"%s\" for type %s", next.asString(), descriptor.getType()).setLine(tokenizer.getLine());
}
use of net.morimekta.providence.descriptor.PEnumDescriptor in project providence by morimekta.
the class MessageRowMapper method map.
@Override
public M map(ResultSet rs, StatementContext ctx) throws SQLException {
PMessageBuilder<M, F> builder = descriptor.builder();
for (int i = 1; i <= rs.getMetaData().getColumnCount(); ++i) {
if (!tableName.isEmpty() && !tableName.equalsIgnoreCase(rs.getMetaData().getTableName(i))) {
continue;
}
String name = rs.getMetaData().getColumnLabel(i).toUpperCase(Locale.US);
F field = fieldNameMapping.get(name);
if (field != null) {
int columnType = rs.getMetaData().getColumnType(i);
switch(field.getType()) {
case BOOL:
{
if (columnType == Types.BOOLEAN || columnType == Types.BIT) {
boolean b = rs.getBoolean(i);
if (!rs.wasNull()) {
builder.set(field, b);
}
} else {
int b = rs.getInt(i);
if (!rs.wasNull()) {
builder.set(field, b != 0);
}
}
break;
}
case BYTE:
{
byte b = rs.getByte(i);
if (!rs.wasNull()) {
builder.set(field, b);
}
break;
}
case I16:
{
short b = rs.getShort(i);
if (!rs.wasNull()) {
builder.set(field, b);
}
break;
}
case I32:
{
if (columnType == Types.TIMESTAMP) {
Timestamp ts = rs.getTimestamp(i);
if (ts != null) {
builder.set(field, (int) (ts.getTime() / 1000L));
}
} else {
int b = rs.getInt(i);
if (!rs.wasNull()) {
builder.set(field, b);
}
}
break;
}
case I64:
{
if (columnType == Types.TIMESTAMP) {
Timestamp ts = rs.getTimestamp(i);
if (ts != null) {
builder.set(field, ts.getTime());
}
} else {
long b = rs.getLong(i);
if (!rs.wasNull()) {
builder.set(field, b);
}
}
break;
}
case DOUBLE:
{
double b = rs.getDouble(i);
if (!rs.wasNull()) {
builder.set(field, b);
}
break;
}
case STRING:
{
builder.set(field, rs.getString(i));
break;
}
case BINARY:
{
switch(columnType) {
case Types.BINARY:
case Types.VARBINARY:
byte[] ts = rs.getBytes(i);
if (ts != null) {
builder.set(field, Binary.copy(ts));
}
break;
case Types.BLOB:
Blob blob = rs.getBlob(i);
if (blob != null) {
try {
builder.set(field, Binary.read(blob.getBinaryStream(), (int) blob.length()));
} catch (IOException e) {
throw new UncheckedIOException(e.getMessage(), e);
}
}
break;
case Types.CHAR:
case Types.VARCHAR:
case Types.NCHAR:
case Types.NVARCHAR:
{
String tmp = rs.getString(i);
if (tmp != null) {
builder.set(field, Binary.fromBase64(tmp));
}
break;
}
case Types.NULL:
break;
default:
throw new ResultSetException("Unknown column type " + rs.getMetaData().getColumnTypeName(i) + " for " + descriptor.getType().toString() + " field " + name + " in " + descriptor.getQualifiedName(), null, ctx);
}
break;
}
case ENUM:
{
int val = rs.getInt(i);
if (!rs.wasNull()) {
PEnumDescriptor ed = (PEnumDescriptor) field.getDescriptor();
builder.set(field, ed.findById(val));
}
break;
}
case MESSAGE:
{
try {
PMessageDescriptor<?, ?> md = (PMessageDescriptor) field.getDescriptor();
switch(columnType) {
case Types.BINARY:
case Types.VARBINARY:
byte[] data = rs.getBytes(i);
if (data != null) {
ByteArrayInputStream in = new ByteArrayInputStream(data);
builder.set(field, BINARY.deserialize(in, md));
}
break;
case Types.BLOB:
{
Blob blob = rs.getBlob(i);
if (blob != null) {
builder.set(field, BINARY.deserialize(blob.getBinaryStream(), md));
}
break;
}
case Types.CHAR:
case Types.VARCHAR:
case Types.NCHAR:
case Types.NVARCHAR:
{
String tmp = rs.getString(i);
if (tmp != null) {
StringReader reader = new StringReader(tmp);
builder.set(field, JSON.deserialize(reader, md));
}
break;
}
case Types.CLOB:
{
Clob clob = rs.getClob(i);
if (clob != null) {
builder.set(field, JSON.deserialize(clob.getCharacterStream(), md));
}
break;
}
case Types.NULL:
break;
default:
throw new ResultSetException("Unknown column type " + rs.getMetaData().getColumnTypeName(i) + " for " + descriptor.getType().toString() + " field " + name + " in " + descriptor.getQualifiedName(), null, ctx);
}
} catch (IOException e) {
throw new UncheckedIOException(e.getMessage(), e);
}
break;
}
case LIST:
case SET:
case MAP:
{
// ... woot?
}
case VOID:
default:
{
throw new ResultSetException("Unhandled column of type " + rs.getMetaData().getColumnTypeName(i) + " for " + descriptor.getType().toString() + " field " + name + " in " + descriptor.getQualifiedName(), null, ctx);
}
}
}
}
return builder.build();
}
use of net.morimekta.providence.descriptor.PEnumDescriptor in project providence by morimekta.
the class TProtocolSerializer method readTypedValue.
private Object readTypedValue(byte tType, PDescriptor type, TProtocol protocol, boolean allowNull) throws TException, SerializerException {
if (tType != forType(type.getType())) {
throw new SerializerException("Expected type " + asString(forType(type.getType())) + " but found " + asString(tType));
}
switch(tType) {
case BinaryType.BOOL:
return protocol.readBool();
case BinaryType.BYTE:
return protocol.readByte();
case BinaryType.I16:
return protocol.readI16();
case BinaryType.I32:
if (PType.ENUM == type.getType()) {
PEnumDescriptor<?> et = (PEnumDescriptor<?>) type;
PEnumBuilder<?> eb = et.builder();
int value = protocol.readI32();
eb.setById(value);
if (!eb.valid() && !allowNull) {
throw new SerializerException("Invalid enum value " + value + " for " + et.getQualifiedName());
}
return eb.build();
} else {
return protocol.readI32();
}
case BinaryType.I64:
return protocol.readI64();
case BinaryType.DOUBLE:
return protocol.readDouble();
case BinaryType.STRING:
if (type == PPrimitive.BINARY) {
ByteBuffer buffer = protocol.readBinary();
return Binary.wrap(buffer.array());
}
return protocol.readString();
case BinaryType.STRUCT:
return readMessage(protocol, (PMessageDescriptor<?, ?>) type);
case BinaryType.LIST:
TList listInfo = protocol.readListBegin();
PList<Object> lDesc = (PList<Object>) type;
PDescriptor liDesc = lDesc.itemDescriptor();
PList.Builder<Object> list = lDesc.builder();
for (int i = 0; i < listInfo.size; ++i) {
list.add(readTypedValue(listInfo.elemType, liDesc, protocol, false));
}
protocol.readListEnd();
return list.build();
case BinaryType.SET:
TSet setInfo = protocol.readSetBegin();
PSet<Object> sDesc = (PSet<Object>) type;
PDescriptor siDesc = sDesc.itemDescriptor();
PSet.Builder<Object> set = sDesc.builder();
for (int i = 0; i < setInfo.size; ++i) {
set.add(readTypedValue(setInfo.elemType, siDesc, protocol, false));
}
protocol.readSetEnd();
return set.build();
case BinaryType.MAP:
TMap mapInfo = protocol.readMapBegin();
PMap<Object, Object> mDesc = (PMap<Object, Object>) type;
PDescriptor mkDesc = mDesc.keyDescriptor();
PDescriptor miDesc = mDesc.itemDescriptor();
PMap.Builder<Object, Object> map = mDesc.builder();
for (int i = 0; i < mapInfo.size; ++i) {
Object key = readTypedValue(mapInfo.keyType, mkDesc, protocol, false);
Object val = readTypedValue(mapInfo.valueType, miDesc, protocol, false);
map.put(key, val);
}
protocol.readMapEnd();
return map.build();
default:
throw new SerializerException("Unsupported protocol field type: " + tType);
}
}
use of net.morimekta.providence.descriptor.PEnumDescriptor in project providence by morimekta.
the class FastBinarySerializer method readFieldValue.
@SuppressWarnings("unchecked")
private Object readFieldValue(@Nonnull LittleEndianBinaryReader in, int type, @Nullable PDescriptor descriptor) throws IOException {
switch(type) {
case NONE:
return Boolean.FALSE;
case TRUE:
return Boolean.TRUE;
case VARINT:
{
if (descriptor == null) {
in.readLongVarint();
return null;
}
switch(descriptor.getType()) {
case BOOL:
return in.readIntVarint() != 0;
case BYTE:
return (byte) in.readIntZigzag();
case I16:
return (short) in.readIntZigzag();
case I32:
return in.readIntZigzag();
case I64:
return in.readLongZigzag();
case ENUM:
{
PEnumBuilder<?> builder = ((PEnumDescriptor<?>) descriptor).builder();
builder.setById(in.readIntZigzag());
return builder.build();
}
default:
{
throw new SerializerException("");
}
}
}
case FIXED_64:
return in.expectDouble();
case BINARY:
{
int len = in.readIntVarint();
byte[] data = in.expectBytes(len);
if (descriptor != null) {
switch(descriptor.getType()) {
case STRING:
return new String(data, StandardCharsets.UTF_8);
case BINARY:
return Binary.wrap(data);
default:
throw new SerializerException("");
}
} else {
return null;
}
}
case MESSAGE:
if (descriptor == null) {
consumeMessage(in);
return null;
}
return readMessage(in, (PMessageDescriptor<?, ?>) descriptor);
case COLLECTION:
if (descriptor == null) {
final int len = in.readIntVarint();
final int tag = in.readIntVarint();
final int vtype = tag & 0x07;
final int ktype = tag > 0x07 ? tag >>> 3 : vtype;
for (int i = 0; i < len; ++i) {
if (i % 2 == 0) {
readFieldValue(in, ktype, null);
} else {
readFieldValue(in, vtype, null);
}
}
return null;
} else if (descriptor.getType() == PType.MAP) {
PMap<Object, Object> ct = (PMap<Object, Object>) descriptor;
PDescriptor kt = ct.keyDescriptor();
PDescriptor vt = ct.itemDescriptor();
PMap.Builder<Object, Object> out = ct.builder();
final int len = in.readIntVarint();
final int tag = in.readIntVarint();
final int vtype = tag & 0x07;
final int ktype = tag > 0x07 ? tag >>> 3 : vtype;
for (int i = 0; i < len; ++i, ++i) {
Object key = readFieldValue(in, ktype, kt);
Object value = readFieldValue(in, vtype, vt);
if (key != null && value != null) {
out.put(key, value);
} else if (readStrict) {
if (key == null) {
throw new SerializerException("Unknown enum key in map");
}
throw new SerializerException("Null value in map");
}
}
return out.build();
} else if (descriptor.getType() == PType.LIST) {
PList<Object> ct = (PList<Object>) descriptor;
PDescriptor it = ct.itemDescriptor();
PList.Builder<Object> out = ct.builder();
final int len = in.readIntVarint();
final int vtype = in.readIntVarint() & 0x07;
for (int i = 0; i < len; ++i) {
Object item = readFieldValue(in, vtype, it);
if (item != null) {
out.add(item);
} else if (readStrict) {
throw new SerializerException("Null value in list");
}
}
return out.build();
} else if (descriptor.getType() == PType.SET) {
PSet<Object> ct = (PSet<Object>) descriptor;
PDescriptor it = ct.itemDescriptor();
PSet.Builder<Object> out = ct.builder();
final int len = in.readIntVarint();
final int vtype = in.readIntVarint() & 0x07;
for (int i = 0; i < len; ++i) {
Object item = readFieldValue(in, vtype, it);
if (item != null) {
out.add(item);
} else if (readStrict) {
throw new SerializerException("Null value in set");
}
}
return out.build();
} else {
throw new SerializerException("Type " + descriptor.getType() + " not compatible with collection data");
}
default:
throw new Error("Unreachable code reached");
}
}
Aggregations