use of net.morimekta.providence.PMessage in project providence by morimekta.
the class FastBinarySerializer method deserialize.
@Nonnull
@Override
@SuppressWarnings("unchecked")
public <Message extends PMessage<Message, Field>, Field extends PField> PServiceCall<Message, Field> deserialize(@Nonnull InputStream is, @Nonnull PService service) throws SerializerException {
String methodName = null;
int sequence = 0;
PServiceCallType type = null;
try {
LittleEndianBinaryReader in = new LittleEndianBinaryReader(is);
// Max method name length: 255 chars.
int tag = in.readIntVarint();
int len = tag >>> 3;
int typeKey = tag & 0x07;
methodName = new String(in.expectBytes(len), UTF_8);
sequence = in.readIntVarint();
type = PServiceCallType.findById(typeKey);
if (type == null) {
throw new SerializerException("Invalid call type " + typeKey).setExceptionType(PApplicationExceptionType.INVALID_MESSAGE_TYPE);
} else if (type == PServiceCallType.EXCEPTION) {
PApplicationException ex = readMessage(in, PApplicationException.kDescriptor);
return (PServiceCall<Message, Field>) new PServiceCall<>(methodName, type, sequence, ex);
}
PServiceMethod method = service.getMethod(methodName);
if (method == null) {
throw new SerializerException("No such method %s on %s", methodName, service.getQualifiedName()).setExceptionType(PApplicationExceptionType.UNKNOWN_METHOD);
}
@SuppressWarnings("unchecked") PMessageDescriptor<Message, Field> descriptor = isRequestCallType(type) ? method.getRequestType() : method.getResponseType();
if (descriptor == null) {
throw new SerializerException("No such %s descriptor for %s", isRequestCallType(type) ? "request" : "response", service.getQualifiedName()).setExceptionType(PApplicationExceptionType.UNKNOWN_METHOD);
}
Message message = readMessage(in, descriptor);
return new PServiceCall<>(methodName, type, sequence, message);
} catch (SerializerException e) {
throw new SerializerException(e).setCallType(type).setMethodName(methodName).setSequenceNo(sequence);
} catch (IOException e) {
throw new SerializerException(e, e.getMessage()).setCallType(type).setMethodName(methodName).setSequenceNo(sequence);
}
}
use of net.morimekta.providence.PMessage in project providence by morimekta.
the class FastBinarySerializer method writeContainerEntry.
@SuppressWarnings("unchecked")
private int writeContainerEntry(LittleEndianBinaryWriter out, int typeid, PDescriptor descriptor, Object value) throws IOException {
switch(typeid) {
case VARINT:
{
if (value instanceof Boolean) {
return out.writeVarint(((Boolean) value ? 1 : 0));
} else if (value instanceof Number) {
return out.writeZigzag(((Number) value).longValue());
} else if (value instanceof PEnumValue) {
return out.writeZigzag(((PEnumValue) value).asInteger());
} else {
throw new SerializerException("");
}
}
case FIXED_64:
{
return out.writeDouble((Double) value);
}
case BINARY:
{
if (value instanceof CharSequence) {
byte[] bytes = ((String) value).getBytes(StandardCharsets.UTF_8);
int len = out.writeVarint(bytes.length);
out.write(bytes);
return len + bytes.length;
} else if (value instanceof Binary) {
Binary bytes = (Binary) value;
int len = out.writeVarint(bytes.length());
bytes.write(out);
return len + bytes.length();
} else {
throw new SerializerException("");
}
}
case MESSAGE:
{
return writeMessage(out, (PMessage) value);
}
case COLLECTION:
{
if (value instanceof Map) {
Map<Object, Object> map = (Map<Object, Object>) value;
PMap<?, ?> desc = (PMap<?, ?>) descriptor;
int ktype = itemType(desc.keyDescriptor());
int vtype = itemType(desc.itemDescriptor());
int len = out.writeVarint(map.size() * 2);
len += out.writeVarint(ktype << 3 | vtype);
for (Map.Entry<Object, Object> entry : map.entrySet()) {
len += writeContainerEntry(out, ktype, desc.keyDescriptor(), entry.getKey());
len += writeContainerEntry(out, vtype, desc.itemDescriptor(), entry.getValue());
}
return len;
} else if (value instanceof Collection) {
Collection<Object> coll = (Collection<Object>) value;
PContainer<?> desc = (PContainer<?>) descriptor;
int vtype = itemType(desc.itemDescriptor());
int len = out.writeVarint(coll.size());
len += out.writeVarint(vtype);
for (Object item : coll) {
len += writeContainerEntry(out, vtype, desc.itemDescriptor(), item);
}
return len;
} else {
throw new SerializerException("");
}
}
default:
throw new SerializerException("");
}
}
use of net.morimekta.providence.PMessage in project providence by morimekta.
the class SerializerTest method setUpData.
@BeforeClass
public static void setUpData() throws IOException, ExceptionFields {
MessageGenerator gen = new MessageGenerator().addFactory(f -> {
if (f.equals(Operand._Field.OPERATION)) {
return () -> Operation.builder().setOperator(Operator.ADD).addToOperands(Operand.withNumber(123)).addToOperands(Operand.withNumber(321)).build();
}
return null;
});
if (operation == null) {
operation = gen.generate(Operation.kDescriptor);
}
if (containers == null) {
containers = new ArrayList<>();
for (int i = 0; i < 1; ++i) {
containers.add(gen.generate(Containers.kDescriptor));
}
}
serviceCalls = new ArrayList<>();
/**
* Temporary setup needed to generate
*/
ContainerService.Iface impl = pC -> {
if (pC == null) {
throw new PApplicationException("", PApplicationExceptionType.INTERNAL_ERROR);
}
if (pC.mutate().presentFields().isEmpty()) {
throw gen.generate(ExceptionFields.kDescriptor);
}
return CompactFields.builder().setName("" + pC.hashCode()).setId(pC.hashCode()).build();
};
PProcessor processor = new ContainerService.Processor(impl);
PServiceCallHandler handler = new PServiceCallHandler() {
@Nullable
@Override
@SuppressWarnings("unchecked")
public <Request extends PMessage<Request, RequestField>, Response extends PMessage<Response, ResponseField>, RequestField extends PField, ResponseField extends PField> PServiceCall<Response, ResponseField> handleCall(PServiceCall<Request, RequestField> call, PService service) throws IOException {
serviceCalls.add(call);
try {
PServiceCall response = processor.handleCall(call, service);
serviceCalls.add(response);
return response;
} catch (PApplicationException e) {
PServiceCall ex = new PServiceCall(call.getMethod(), PServiceCallType.EXCEPTION, call.getSequence(), e);
serviceCalls.add(ex);
return ex;
}
}
};
ContainerService.Client client = new ContainerService.Client(handler);
client.load(gen.generate(Containers.kDescriptor));
try {
client.load(Containers.builder().build());
} catch (ExceptionFields e) {
// ignore.
}
try {
// NPE -> PApplicationException
client.load(null);
} catch (PApplicationException e) {
// ignore.
}
}
use of net.morimekta.providence.PMessage in project providence by morimekta.
the class HasFieldValue method describeMismatch.
@Override
public void describeMismatch(Object o, Description mismatchDescription) {
if (o == null) {
mismatchDescription.appendText("got null message");
} else {
if (!(o instanceof PMessage)) {
mismatchDescription.appendText("instance is not a message");
return;
}
List<String> stack = new ArrayList<>();
for (int i = 0; i < path.length; ++i) {
stack.add(path[i]);
String path = Strings.join(".", stack);
if (!(o instanceof PMessage)) {
mismatchDescription.appendText("field \'" + path + "\' is not a message");
return;
}
PMessage actual = (PMessage) o;
PField field = actual.descriptor().findFieldByName(this.path[i]);
if (field == null) {
mismatchDescription.appendText("field path \'" + path + "\' is not valid");
return;
}
if (!actual.has(field.getId())) {
mismatchDescription.appendText("field \'" + path + "\' is missing");
return;
}
o = actual.get(field.getId());
}
}
}
use of net.morimekta.providence.PMessage in project providence by morimekta.
the class HasFieldValue method matches.
@Override
public boolean matches(Object o) {
if (o == null) {
return false;
}
for (int i = 0; i < path.length; ++i) {
if (!(o instanceof PMessage)) {
return false;
}
PMessage actual = (PMessage) o;
PField field = actual.descriptor().findFieldByName(path[i]);
if (field == null) {
return false;
}
if (!actual.has(field.getId())) {
return false;
}
o = actual.get(field.getId());
}
return true;
}
Aggregations