Search in sources :

Example 1 with ForLoadedType

use of net.bytebuddy.description.type.TypeDescription.ForLoadedType in project curiostack by curioswitch.

the class DoParse method setFieldValue.

/**
 * Returns the {@link StackManipulation} for setting the value of a field. This will be all the
 * elements for a repeated field.
 *
 * @param info description of the field to set.
 * @param beforeReadField jump target for before reading a field, used once this field is
 *     completed being set.
 * @param locals the method local variables
 * @param fieldsByName the instance fields
 */
private static StackManipulation setFieldValue(ProtoFieldInfo info, Label beforeReadField, LocalVariables<LocalVariable> locals, Map<String, FieldDescription> fieldsByName) {
    if (info.isMapField()) {
        return setMapFieldValue(info, beforeReadField, locals, fieldsByName);
    } else {
        final StackManipulation setConcreteValue = invoke(info.setValueMethod());
        final StackManipulation setSingleValue;
        if (info.valueJavaType() == JavaType.MESSAGE) {
            setSingleValue = new StackManipulation.Compound(TypeCasting.to(new ForLoadedType(info.javaClass())), setConcreteValue);
        } else {
            setSingleValue = setConcreteValue;
        }
        if (info.descriptor().isRepeated()) {
            return setRepeatedFieldValue(info, beforeReadField, locals, fieldsByName, setSingleValue);
        } else {
            // builder.setFoo(readValue());
            return new StackManipulation.Compound(locals.load(LocalVariable.builder), locals.load(LocalVariable.parser), readValue(info, fieldsByName, locals), setSingleValue, Removal.SINGLE, new Goto(beforeReadField));
        }
    }
}
Also used : Goto(org.curioswitch.common.protobuf.json.bytebuddy.Goto) StackManipulation(net.bytebuddy.implementation.bytecode.StackManipulation) ForLoadedType(net.bytebuddy.description.type.TypeDescription.ForLoadedType)

Example 2 with ForLoadedType

use of net.bytebuddy.description.type.TypeDescription.ForLoadedType in project curiostack by curioswitch.

the class DoParse method setMapFieldValue.

/**
 * Returns the {@link StackManipulation} for setting the value of a map field.
 *
 * <p>Roughly equivalent to:
 *
 * <pre>{@code
 * ParseSupport.parseObjectStart(parser);
 * while (!ParseSupport.checkObjectEnd(parser.currentToken())) {
 *   builder.putFoo(readKey(), readValue());
 * }
 * }</pre>
 */
private static StackManipulation setMapFieldValue(ProtoFieldInfo info, Label beforeReadField, LocalVariables<LocalVariable> locals, Map<String, FieldDescription> fieldsByName) {
    final StackManipulation setConcreteValue = invoke(info.setValueMethod());
    final StackManipulation setMapEntry;
    if (info.valueJavaType() == JavaType.MESSAGE) {
        setMapEntry = new StackManipulation.Compound(TypeCasting.to(new ForLoadedType(info.javaClass())), setConcreteValue);
    } else {
        setMapEntry = setConcreteValue;
    }
    Label mapStart = new Label();
    return new StackManipulation.Compound(locals.load(LocalVariable.parser), ParseSupport_parseObjectStart, new SetJumpTargetLabel(mapStart), locals.load(LocalVariable.parser), Parser_currentToken, ParseSupport_checkObjectEnd, new IfTrue(beforeReadField), locals.load(LocalVariable.builder), locals.load(LocalVariable.parser), readValue(info.mapKeyField(), fieldsByName, locals), locals.load(LocalVariable.parser), Parser_nextToken, Removal.SINGLE, locals.load(LocalVariable.parser), readValue(info, fieldsByName, locals), setMapEntry, Removal.SINGLE, locals.load(LocalVariable.parser), Parser_nextToken, Removal.SINGLE, new Goto(mapStart));
}
Also used : Goto(org.curioswitch.common.protobuf.json.bytebuddy.Goto) StackManipulation(net.bytebuddy.implementation.bytecode.StackManipulation) ForLoadedType(net.bytebuddy.description.type.TypeDescription.ForLoadedType) SetJumpTargetLabel(org.curioswitch.common.protobuf.json.bytebuddy.SetJumpTargetLabel) Label(net.bytebuddy.jar.asm.Label) SetJumpTargetLabel(org.curioswitch.common.protobuf.json.bytebuddy.SetJumpTargetLabel) IfTrue(org.curioswitch.common.protobuf.json.bytebuddy.IfTrue)

Example 3 with ForLoadedType

use of net.bytebuddy.description.type.TypeDescription.ForLoadedType in project curiostack by curioswitch.

the class DoParse method apply.

@Override
public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
    Map<String, FieldDescription> fieldsByName = CodeGenUtil.fieldsByName(implementationContext);
    // Fields stored in order of number, so to get the highest number we take the last field.
    FieldDescriptor lastField = Iterables.getLast(descriptor.getFields(), null);
    // Field numbers are 1 or greater so we will allocate the same size as the last field number
    // and subtract 1 when keeping track.
    int lastFieldNumber = lastField != null ? lastField.getNumber() : 0;
    int numFieldPresenceWords = lastFieldNumber / Integer.SIZE;
    if (lastFieldNumber % Integer.SIZE > 0) {
        numFieldPresenceWords++;
    }
    List<LocalVariable> fieldPresenceVars = new ArrayList<>();
    for (int i = 0; i < numFieldPresenceWords; i++) {
        fieldPresenceVars.add(new LocalVariable("setFieldBits" + i));
    }
    LocalVariables.Builder<LocalVariable> localsBuilder = LocalVariables.builderForMethod(instrumentedMethod, ObjectArrays.concat(LocalVariable.values(), Iterables.toArray(fieldPresenceVars, LocalVariable.class), LocalVariable.class)).add(builderClass, LocalVariable.builder).add(String.class, LocalVariable.fieldName);
    for (LocalVariable fieldPresenceVar : fieldPresenceVars) {
        localsBuilder.add(int.class, fieldPresenceVar);
    }
    LocalVariables<LocalVariable> locals = localsBuilder.build();
    List<StackManipulation> stackManipulations = new ArrayList<>();
    Label beforeReadField = new Label();
    Label finished = new Label();
    // Initialize local variables for this method, e.g.,
    // void doMerge(JsonParser parser, int currentDepth, Message.Builder messageBuilder) {
    // T builder = (T) messageBuilder;
    // String fieldName = null;
    // Object fieldNumberUnboxed = null;
    // int fieldNumber = 0;
    // int setFieldBits0 = 0;
    // int setFieldBits1 = 0;
    // ...
    stackManipulations.addAll(Arrays.asList(locals.initialize(), locals.load(LocalVariable.messageBuilder), TypeCasting.to(new ForLoadedType(builderClass)), locals.store(LocalVariable.builder)));
    // Begins the loop that reads fields from the JSON, reading the field name and computing its
    // hash, e.g.,
    // ...
    // while (parser.nextValue() != ParseSupport.checkObjectEnd) {
    // fieldName = parser.getCurrentName();
    // fieldNumberUnboxed = FIELD_NUMBERS.get(fieldName):
    // if (fieldNumberUnboxed == null) {
    // ParseSupport.throwIfUnknownField(fieldName, descriptor.getFullName());
    // return
    // }
    // fieldNumber = (int) fieldNumberUnboxed;
    // ...
    stackManipulations.addAll(Arrays.asList(new SetJumpTargetLabel(beforeReadField), locals.load(LocalVariable.parser), Parser_nextValue, ParseSupport_checkObjectEnd, new IfTrue(finished), locals.load(LocalVariable.parser), Parser_getCurrentName, locals.store(LocalVariable.fieldName)));
    for (FieldDescriptor f : descriptor.getFields()) {
        Label afterNameCheck = new Label();
        Label afterField = new Label();
        ProtoFieldInfo field = new ProtoFieldInfo(f, prototype);
        int fieldNumberZeroBased = field.descriptor().getNumber() - 1;
        LocalVariable fieldPresenceVar = fieldPresenceVars.get(fieldNumberZeroBased / Integer.SIZE);
        int fieldPreserveVarBitIndex = fieldNumberZeroBased % Integer.SIZE;
        // if-statement for checking whether the current JSON field name matches this field, e.g.,
        // if (fieldName == String.intern(field.getName())
        // || fieldName == String.intern(field.getJsonName()) {
        // ...
        // } else if ...
        stackManipulations.addAll(Arrays.asList(locals.load(LocalVariable.fieldName), new TextConstant(field.descriptor().getJsonName()), new IfRefsEqual(afterNameCheck), locals.load(LocalVariable.fieldName), new TextConstant(field.descriptor().getName()), new IfRefsNotEqual(afterField), new SetJumpTargetLabel(afterNameCheck)));
        // Check whether we have already seen this field in the JSON, which is not allowed. e.g.,
        // setFieldBitsN = ParseSupport.throwIfFieldAlreadyWritten(
        // setFieldBitsN, 0x1 << field.getNumber() % 8);
        stackManipulations.addAll(Arrays.asList(locals.load(fieldPresenceVar), IntegerConstant.forValue(0x1 << fieldPreserveVarBitIndex), new TextConstant(field.descriptor().getFullName()), ParseSupport_throwIfFieldAlreadyWritten, locals.store(fieldPresenceVar)));
        // ParseSupport.throwIfOneofAlreadyWritten(builder.getSomeOneofCase(), field.getFullName());
        if (field.isInOneof()) {
            try {
                stackManipulations.addAll(Arrays.asList(locals.load(LocalVariable.builder), invoke(builderClass.getDeclaredMethod(field.getOneOfCaseMethodName())), new TextConstant(field.descriptor().getFullName()), ParseSupport_throwIfOneofAlreadyWritten));
            } catch (NoSuchMethodException e) {
                throw new IllegalStateException("Could not find oneof case method.", e);
            }
        }
        // }
        if (mustSkipNull(field.descriptor())) {
            stackManipulations.addAll(Arrays.asList(locals.load(LocalVariable.parser), ParseSupport_checkNull, new IfTrue(beforeReadField)));
        }
        StackManipulation setValue = setFieldValue(field, beforeReadField, locals, fieldsByName);
        stackManipulations.add(setValue);
        stackManipulations.add(new SetJumpTargetLabel(afterField));
    }
    if (ignoringUnknownFields) {
        // If we found no corresponding field number, jump back to the beginning of the while loop.
        stackManipulations.add(new Goto(beforeReadField));
    } else {
        // If we found no corresponding field number, throw an exception.
        stackManipulations.addAll(Arrays.asList(locals.load(LocalVariable.fieldName), new TextConstant(descriptor.getFullName()), ParseSupport_throwIfUnknownField));
    }
    // End of the field processing while loop.
    stackManipulations.add(new SetJumpTargetLabel(finished));
    stackManipulations.add(MethodReturn.VOID);
    StackManipulation.Size operandStackSize = new StackManipulation.Compound(stackManipulations).apply(methodVisitor, implementationContext);
    return new Size(operandStackSize.getMaximalSize(), locals.stackSize());
}
Also used : StackManipulation(net.bytebuddy.implementation.bytecode.StackManipulation) ForLoadedType(net.bytebuddy.description.type.TypeDescription.ForLoadedType) ArrayList(java.util.ArrayList) SetJumpTargetLabel(org.curioswitch.common.protobuf.json.bytebuddy.SetJumpTargetLabel) Label(net.bytebuddy.jar.asm.Label) FieldDescriptor(com.google.protobuf.Descriptors.FieldDescriptor) IfRefsEqual(org.curioswitch.common.protobuf.json.bytebuddy.IfRefsEqual) Goto(org.curioswitch.common.protobuf.json.bytebuddy.Goto) IfRefsNotEqual(org.curioswitch.common.protobuf.json.bytebuddy.IfRefsNotEqual) TextConstant(net.bytebuddy.implementation.bytecode.constant.TextConstant) FieldDescription(net.bytebuddy.description.field.FieldDescription) SetJumpTargetLabel(org.curioswitch.common.protobuf.json.bytebuddy.SetJumpTargetLabel) IfTrue(org.curioswitch.common.protobuf.json.bytebuddy.IfTrue)

Example 4 with ForLoadedType

use of net.bytebuddy.description.type.TypeDescription.ForLoadedType in project beam by apache.

the class AvroByteBuddyUtils method readAndConvertParameter.

private static StackManipulation readAndConvertParameter(Class<?> constructorParameterType, int index) {
    TypeConversionsFactory typeConversionsFactory = new AvroTypeConversionFactory();
    // The types in the AVRO-generated constructor might be the types returned by Beam's Row class,
    // so we have to convert the types used by Beam's Row class.
    // We know that AVRO generates constructor parameters in the same order as fields
    // in the schema, so we can just add the parameters sequentially.
    TypeConversion<Type> convertType = typeConversionsFactory.createTypeConversion(true);
    // Map the AVRO-generated type to the one Beam will use.
    ForLoadedType convertedType = new ForLoadedType((Class) convertType.convert(TypeDescriptor.of(constructorParameterType)));
    // This will run inside the generated creator. Read the parameter and convert it to the
    // type required by the SpecificRecord constructor.
    StackManipulation readParameter = new StackManipulation.Compound(MethodVariableAccess.REFERENCE.loadFrom(1), IntegerConstant.forValue(index), ArrayAccess.REFERENCE.load(), TypeCasting.to(convertedType));
    // Convert to the parameter accepted by the SpecificRecord constructor.
    return typeConversionsFactory.createSetterConversions(readParameter).convert(TypeDescriptor.of(constructorParameterType));
}
Also used : DynamicType(org.apache.beam.vendor.bytebuddy.v1_11_0.net.bytebuddy.dynamic.DynamicType) ForLoadedType(org.apache.beam.vendor.bytebuddy.v1_11_0.net.bytebuddy.description.type.TypeDescription.ForLoadedType) Type(java.lang.reflect.Type) StackManipulation(org.apache.beam.vendor.bytebuddy.v1_11_0.net.bytebuddy.implementation.bytecode.StackManipulation) ForLoadedType(org.apache.beam.vendor.bytebuddy.v1_11_0.net.bytebuddy.description.type.TypeDescription.ForLoadedType) AvroTypeConversionFactory(org.apache.beam.sdk.schemas.utils.AvroUtils.AvroTypeConversionFactory) TypeConversionsFactory(org.apache.beam.sdk.schemas.utils.ByteBuddyUtils.TypeConversionsFactory)

Example 5 with ForLoadedType

use of net.bytebuddy.description.type.TypeDescription.ForLoadedType in project curiostack by curioswitch.

the class DoWrite method apply.

@Override
public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
    Map<String, FieldDescription> fieldsByName = CodeGenUtil.fieldsByName(implementationContext);
    List<StackManipulation> stackManipulations = new ArrayList<>();
    final StackManipulation getDefaultInstance;
    try {
        getDefaultInstance = invoke(messageClass.getDeclaredMethod("getDefaultInstance"));
    } catch (NoSuchMethodException e) {
        throw new IllegalStateException("Could not find getDefaultInstance on a Message class.");
    }
    LocalVariables<LocalVariable> locals = LocalVariables.builderForMethod(instrumentedMethod, LocalVariable.values()).add(Iterator.class, LocalVariable.iterator).add(Map.Entry.class, LocalVariable.entry).build();
    stackManipulations.add(locals.initialize());
    // based on the includeDefaults parameter.
    for (FieldDescriptor f : descriptor.getFields()) {
        ProtoFieldInfo field = new ProtoFieldInfo(f, prototype);
        StackManipulation getValue = new StackManipulation.Compound(locals.load(LocalVariable.message), invoke(field.getValueMethod()));
        Label afterSerializeField = new Label();
        // }
        if (!includeDefaults || // one-of).
        field.isInOneof() || // a message has itself as a sub-field.
        (field.descriptor().isOptional() && field.valueJavaType() == JavaType.MESSAGE)) {
            stackManipulations.add(checkDefaultValue(field, locals, getValue, getDefaultInstance, afterSerializeField));
        }
        stackManipulations.addAll(Arrays.asList(locals.load(LocalVariable.gen), FieldAccess.forField(fieldsByName.get(CodeGenUtil.fieldNameForSerializedFieldName(field))).read(), JsonGenerator_writeFieldName_SerializableString));
        // gen.writeEndObject();
        if (field.isMapField()) {
            final StackManipulation keyToString;
            switch(field.mapKeyField().descriptor().getType()) {
                case INT32:
                case SINT32:
                case SFIXED32:
                    keyToString = Integer_toString;
                    break;
                case INT64:
                case SINT64:
                case SFIXED64:
                    keyToString = Long_toString;
                    break;
                case BOOL:
                    keyToString = Boolean_toString;
                    break;
                case UINT32:
                case FIXED32:
                    keyToString = new StackManipulation.Compound(SerializeSupport_normalizeUnsignedInt32, Long_toString);
                    break;
                case UINT64:
                case FIXED64:
                    keyToString = SerializeSupport_normalizeUnsignedInt64;
                    break;
                case STRING:
                    keyToString = Trivial.INSTANCE;
                    break;
                default:
                    throw new IllegalStateException("Unexpected map key type: " + field.mapKeyField().descriptor().getType());
            }
            final Label loopStart = new Label();
            final Label loopEnd = new Label();
            final StackManipulation printValue = printValue(fieldsByName, field);
            final StackManipulation printMapFieldValue = new StackManipulation.Compound(locals.load(LocalVariable.gen), JsonGenerator_writeStartObject, getValue, Map_entrySet, Set_iterator, locals.store(LocalVariable.iterator), new SetJumpTargetLabel(loopStart), locals.load(LocalVariable.iterator), Iterator_hasNext, new IfFalse(loopEnd), locals.load(LocalVariable.iterator), Iterator_next, TypeCasting.to(new ForLoadedType(Entry.class)), locals.store(LocalVariable.entry), locals.load(LocalVariable.gen), locals.load(LocalVariable.entry), Map_Entry_getKey, unbox(field.mapKeyField()), keyToString, JsonGenerator_writeFieldName_String, locals.load(LocalVariable.entry), Map_Entry_getValue, unbox(field.valueField()), locals.load(LocalVariable.gen), printValue, new Goto(loopStart), new SetJumpTargetLabel(loopEnd), locals.load(LocalVariable.gen), JsonGenerator_writeEndObject);
            stackManipulations.add(printMapFieldValue);
        } else {
            // Simply calls the SerializeSupport method that prints out this field. Any iteration will
            // be handled there.
            // 
            // e.g.,
            // SerializeSupport.printUnsignedInt32(message.getFoo());
            // SerializeSupport.printRepeatedString(message.getBar());
            final StackManipulation printValue = printValue(fieldsByName, field);
            stackManipulations.addAll(Arrays.asList(getValue, locals.load(LocalVariable.gen), printValue));
        }
        stackManipulations.add(new SetJumpTargetLabel(afterSerializeField));
    }
    stackManipulations.add(MethodReturn.VOID);
    StackManipulation.Size operandStackSize = new StackManipulation.Compound(stackManipulations).apply(methodVisitor, implementationContext);
    return new Size(operandStackSize.getMaximalSize(), locals.stackSize());
}
Also used : Goto(org.curioswitch.common.protobuf.json.bytebuddy.Goto) StackManipulation(net.bytebuddy.implementation.bytecode.StackManipulation) ForLoadedType(net.bytebuddy.description.type.TypeDescription.ForLoadedType) ArrayList(java.util.ArrayList) SetJumpTargetLabel(org.curioswitch.common.protobuf.json.bytebuddy.SetJumpTargetLabel) Label(net.bytebuddy.jar.asm.Label) SerializableString(com.fasterxml.jackson.core.SerializableString) ByteString(com.google.protobuf.ByteString) FieldDescription(net.bytebuddy.description.field.FieldDescription) FieldDescriptor(com.google.protobuf.Descriptors.FieldDescriptor) Entry(java.util.Map.Entry) SetJumpTargetLabel(org.curioswitch.common.protobuf.json.bytebuddy.SetJumpTargetLabel) IfFalse(org.curioswitch.common.protobuf.json.bytebuddy.IfFalse)

Aggregations

ForLoadedType (net.bytebuddy.description.type.TypeDescription.ForLoadedType)4 StackManipulation (net.bytebuddy.implementation.bytecode.StackManipulation)4 Goto (org.curioswitch.common.protobuf.json.bytebuddy.Goto)4 Label (net.bytebuddy.jar.asm.Label)3 SetJumpTargetLabel (org.curioswitch.common.protobuf.json.bytebuddy.SetJumpTargetLabel)3 FieldDescriptor (com.google.protobuf.Descriptors.FieldDescriptor)2 ArrayList (java.util.ArrayList)2 FieldDescription (net.bytebuddy.description.field.FieldDescription)2 IfTrue (org.curioswitch.common.protobuf.json.bytebuddy.IfTrue)2 SerializableString (com.fasterxml.jackson.core.SerializableString)1 ByteString (com.google.protobuf.ByteString)1 Type (java.lang.reflect.Type)1 Entry (java.util.Map.Entry)1 TextConstant (net.bytebuddy.implementation.bytecode.constant.TextConstant)1 AvroTypeConversionFactory (org.apache.beam.sdk.schemas.utils.AvroUtils.AvroTypeConversionFactory)1 TypeConversionsFactory (org.apache.beam.sdk.schemas.utils.ByteBuddyUtils.TypeConversionsFactory)1 ForLoadedType (org.apache.beam.vendor.bytebuddy.v1_11_0.net.bytebuddy.description.type.TypeDescription.ForLoadedType)1 DynamicType (org.apache.beam.vendor.bytebuddy.v1_11_0.net.bytebuddy.dynamic.DynamicType)1 StackManipulation (org.apache.beam.vendor.bytebuddy.v1_11_0.net.bytebuddy.implementation.bytecode.StackManipulation)1 IfFalse (org.curioswitch.common.protobuf.json.bytebuddy.IfFalse)1