com.fitbur.bytebuddy.implementation.bytecode.assign.primitive.PrimitiveWideningDelegate Maven / Gradle / Ivy
The newest version!
package com.fitbur.bytebuddy.implementation.bytecode.assign.primitive;
import com.fitbur.bytebuddy.description.type.TypeDefinition;
import com.fitbur.bytebuddy.implementation.Implementation;
import com.fitbur.bytebuddy.implementation.bytecode.StackManipulation;
import com.fitbur.bytebuddy.implementation.bytecode.StackSize;
import com.fitbur.bytebuddy.jar.asm.MethodVisitor;
import com.fitbur.bytebuddy.jar.asm.Opcodes;
/**
* This delegate is responsible for widening a primitive type to represent a larger primitive type. The
* rules for this widening are equivalent to those in the JLS.
*/
public enum PrimitiveWideningDelegate {
/**
* The widening delegate for {@code boolean} values.
*/
BOOLEAN(StackManipulation.Trivial.INSTANCE, // to boolean
StackManipulation.Illegal.INSTANCE, // to byte
StackManipulation.Illegal.INSTANCE, // to short
StackManipulation.Illegal.INSTANCE, // to character
StackManipulation.Illegal.INSTANCE, // to integer
StackManipulation.Illegal.INSTANCE, // to long
StackManipulation.Illegal.INSTANCE, // to float
StackManipulation.Illegal.INSTANCE), // to double
/**
* The widening delegate for {@code byte} values.
*/
BYTE(StackManipulation.Illegal.INSTANCE, // to boolean
StackManipulation.Trivial.INSTANCE, // to byte
StackManipulation.Trivial.INSTANCE, // to short
StackManipulation.Illegal.INSTANCE, // to character
StackManipulation.Trivial.INSTANCE, // to integer
new WideningStackManipulation(Opcodes.I2L, StackSize.SINGLE.toIncreasingSize()), // to long
new WideningStackManipulation(Opcodes.I2F, StackSize.ZERO.toIncreasingSize()), // to float
new WideningStackManipulation(Opcodes.I2L, StackSize.SINGLE.toIncreasingSize())), // to double
/**
* The widening delegate for {@code short} values.
*/
SHORT(StackManipulation.Illegal.INSTANCE, // to boolean
StackManipulation.Illegal.INSTANCE, // to byte
StackManipulation.Trivial.INSTANCE, // to short
StackManipulation.Illegal.INSTANCE, // to character
StackManipulation.Trivial.INSTANCE, // to integer
new WideningStackManipulation(Opcodes.I2L, StackSize.SINGLE.toIncreasingSize()), // to long
new WideningStackManipulation(Opcodes.I2F, StackSize.ZERO.toIncreasingSize()), // to float
new WideningStackManipulation(Opcodes.I2D, StackSize.SINGLE.toIncreasingSize())), // to double
/**
* The widening delegate for {@code char} values.
*/
CHARACTER(StackManipulation.Illegal.INSTANCE, // to boolean
StackManipulation.Illegal.INSTANCE, // to byte
StackManipulation.Illegal.INSTANCE, // to short
StackManipulation.Trivial.INSTANCE, // to character
StackManipulation.Trivial.INSTANCE, // to integer
new WideningStackManipulation(Opcodes.I2L, StackSize.SINGLE.toIncreasingSize()), // to long
new WideningStackManipulation(Opcodes.I2F, StackSize.ZERO.toIncreasingSize()), // to float
new WideningStackManipulation(Opcodes.I2D, StackSize.SINGLE.toIncreasingSize())), // to double
/**
* The widening delegate for {@code int} values.
*/
INTEGER(StackManipulation.Illegal.INSTANCE, // to boolean
StackManipulation.Illegal.INSTANCE, // to byte
StackManipulation.Illegal.INSTANCE, // to short
StackManipulation.Illegal.INSTANCE, // to character
StackManipulation.Trivial.INSTANCE, // to integer
new WideningStackManipulation(Opcodes.I2L, StackSize.SINGLE.toIncreasingSize()), // to long
new WideningStackManipulation(Opcodes.I2F, StackSize.ZERO.toIncreasingSize()), // to float
new WideningStackManipulation(Opcodes.I2D, StackSize.SINGLE.toIncreasingSize())), // to double
/**
* The widening delegate for {@code long} values.
*/
LONG(StackManipulation.Illegal.INSTANCE, // to boolean
StackManipulation.Illegal.INSTANCE, // to byte
StackManipulation.Illegal.INSTANCE, // to short
StackManipulation.Illegal.INSTANCE, // to character
StackManipulation.Illegal.INSTANCE, // to integer
StackManipulation.Trivial.INSTANCE, // to long
new WideningStackManipulation(Opcodes.L2F, StackSize.SINGLE.toDecreasingSize()), // to float
new WideningStackManipulation(Opcodes.L2D, StackSize.ZERO.toIncreasingSize())), // to double
/**
* The widening delegate for {@code float} values.
*/
FLOAT(StackManipulation.Illegal.INSTANCE, // to boolean
StackManipulation.Illegal.INSTANCE, // to byte
StackManipulation.Illegal.INSTANCE, // to short
StackManipulation.Illegal.INSTANCE, // to character
StackManipulation.Illegal.INSTANCE, // to integer
StackManipulation.Illegal.INSTANCE, // to long
StackManipulation.Trivial.INSTANCE, // to float
new WideningStackManipulation(Opcodes.F2D, StackSize.SINGLE.toIncreasingSize())), // to double
/**
* The widening delegate for {@code double} values.
*/
DOUBLE(StackManipulation.Illegal.INSTANCE, // to boolean
StackManipulation.Illegal.INSTANCE, // to byte
StackManipulation.Illegal.INSTANCE, // to short
StackManipulation.Illegal.INSTANCE, // to character
StackManipulation.Illegal.INSTANCE, // to integer
StackManipulation.Illegal.INSTANCE, // to long
StackManipulation.Illegal.INSTANCE, // to float
StackManipulation.Trivial.INSTANCE); // to double
/**
* A stack manipulation that widens the type that is represented by this instance to a {@code boolean}.
*/
private final StackManipulation toBooleanStackManipulation;
/**
* A stack manipulation that widens the type that is represented by this instance to a {@code byte}.
*/
private final StackManipulation toByteStackManipulation;
/**
* A stack manipulation that widens the type that is represented by this instance to a {@code short}.
*/
private final StackManipulation toShortStackManipulation;
/**
* A stack manipulation that widens the type that is represented by this instance to a {@code char}.
*/
private final StackManipulation toCharacterStackManipulation;
/**
* A stack manipulation that widens the type that is represented by this instance to a {@code int}.
*/
private final StackManipulation toIntegerStackManipulation;
/**
* A stack manipulation that widens the type that is represented by this instance to a {@code long}.
*/
private final StackManipulation toLongStackManipulation;
/**
* A stack manipulation that widens the type that is represented by this instance to a {@code float}.
*/
private final StackManipulation toFloatStackManipulation;
/**
* A stack manipulation that widens the type that is represented by this instance to a {@code double}.
*/
private final StackManipulation toDoubleStackManipulation;
/**
* Creates a new primitive widening delegate.
*
* @param toBooleanStackManipulation A stack manipulation that widens the type that is represented by this
* instance to a {@code boolean}.
* @param toByteStackManipulation A stack manipulation that widens the type that is represented by this
* instance to a {@code byte}.
* @param toShortStackManipulation A stack manipulation that widens the type that is represented by this
* instance to a {@code short}.
* @param toCharacterStackManipulation A stack manipulation that widens the type that is represented by this
* instance to a {@code char}.
* @param toIntegerStackManipulation A stack manipulation that widens the type that is represented by this
* instance to a {@code int}.
* @param toLongStackManipulation A stack manipulation that widens the type that is represented by this
* instance to a {@code long}.
* @param toFloatStackManipulation A stack manipulation that widens the type that is represented by this
* instance to a {@code float}.
* @param toDoubleStackManipulation A stack manipulation that widens the type that is represented by this
* instance to a {@code double}.
*/
PrimitiveWideningDelegate(StackManipulation toBooleanStackManipulation,
StackManipulation toByteStackManipulation,
StackManipulation toShortStackManipulation,
StackManipulation toCharacterStackManipulation,
StackManipulation toIntegerStackManipulation,
StackManipulation toLongStackManipulation,
StackManipulation toFloatStackManipulation,
StackManipulation toDoubleStackManipulation) {
this.toBooleanStackManipulation = toBooleanStackManipulation;
this.toByteStackManipulation = toByteStackManipulation;
this.toShortStackManipulation = toShortStackManipulation;
this.toCharacterStackManipulation = toCharacterStackManipulation;
this.toIntegerStackManipulation = toIntegerStackManipulation;
this.toLongStackManipulation = toLongStackManipulation;
this.toFloatStackManipulation = toFloatStackManipulation;
this.toDoubleStackManipulation = toDoubleStackManipulation;
}
/**
* Locates the delegate that is capable of widening the given type into another type.
*
* @param typeDefinition A non-void primitive type that is to be widened into another type.
* @return A delegate for the given type.
*/
public static PrimitiveWideningDelegate forPrimitive(TypeDefinition typeDefinition) {
if (typeDefinition.represents(boolean.class)) {
return BOOLEAN;
} else if (typeDefinition.represents(byte.class)) {
return BYTE;
} else if (typeDefinition.represents(short.class)) {
return SHORT;
} else if (typeDefinition.represents(char.class)) {
return CHARACTER;
} else if (typeDefinition.represents(int.class)) {
return INTEGER;
} else if (typeDefinition.represents(long.class)) {
return LONG;
} else if (typeDefinition.represents(float.class)) {
return FLOAT;
} else if (typeDefinition.represents(double.class)) {
return DOUBLE;
} else {
throw new IllegalArgumentException("Not a primitive, non-void type: " + typeDefinition);
}
}
/**
* Attempts to widen the represented type into another type.
*
* @param typeDefinition A non-void primitive type that is the expected result of the widening operation.
* @return A widening instruction or an illegal stack manipulation if such widening is not legitimate.
*/
public StackManipulation widenTo(TypeDefinition typeDefinition) {
if (typeDefinition.represents(boolean.class)) {
return toBooleanStackManipulation;
} else if (typeDefinition.represents(byte.class)) {
return toByteStackManipulation;
} else if (typeDefinition.represents(short.class)) {
return toShortStackManipulation;
} else if (typeDefinition.represents(char.class)) {
return toCharacterStackManipulation;
} else if (typeDefinition.represents(int.class)) {
return toIntegerStackManipulation;
} else if (typeDefinition.represents(long.class)) {
return toLongStackManipulation;
} else if (typeDefinition.represents(float.class)) {
return toFloatStackManipulation;
} else if (typeDefinition.represents(double.class)) {
return toDoubleStackManipulation;
} else {
throw new IllegalArgumentException("Not a primitive non-void type: " + typeDefinition);
}
}
@Override
public String toString() {
return "PrimitiveWideningDelegate." + name();
}
/**
* A stack manipulation that widens a primitive type into a more general primitive type.
*/
protected static class WideningStackManipulation implements StackManipulation {
/**
* The opcode for executing the conversion.
*/
private final int conversionOpcode;
/**
* The size change of applying the conversion.
*/
private final Size size;
/**
* Creates a new widening stack manipulation.
*
* @param conversionOpcode The opcode for executing the conversion.
* @param size The size change of applying the conversion.
*/
protected WideningStackManipulation(int conversionOpcode, Size size) {
this.conversionOpcode = conversionOpcode;
this.size = size;
}
@Override
public boolean isValid() {
return true;
}
@Override
public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
methodVisitor.visitInsn(conversionOpcode);
return size;
}
@Override
public boolean equals(Object other) {
return this == other || !(other == null || getClass() != other.getClass())
&& conversionOpcode == ((WideningStackManipulation) other).conversionOpcode
&& size.equals(((WideningStackManipulation) other).size);
}
@Override
public int hashCode() {
return 31 * conversionOpcode + size.hashCode();
}
@Override
public String toString() {
return "PrimitiveWideningDelegate.WideningStackManipulation{" +
"conversionOpcode=" + conversionOpcode +
", size=" + size +
'}';
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy