/*
 * Copyright 2014 - 2020 Rafael Winterhalter
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.bytebuddy.implementation.bytecode.assign.primitive;

import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.description.type.TypeDefinition;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.bytecode.StackManipulation;
import net.bytebuddy.implementation.bytecode.StackSize;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.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.
/** * This delegate is responsible for widening a primitive type to represent a <i>larger</i> primitive type. The * rules for this widening are equivalent to those in the <a href="http://docs.oracle.com/javase/specs/">JLS</a>. */
public enum PrimitiveWideningDelegate {
The widening delegate for boolean values.
/** * 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 byte values.
/** * 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 short values.
/** * 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 char values.
/** * 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 int values.
/** * 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 long values.
/** * 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 float values.
/** * 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 double values.
/** * 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 boolean.
/** * 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 byte.
/** * 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 short.
/** * 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 char.
/** * 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 int.
/** * 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 long.
/** * 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 float.
/** * 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 double.
/** * 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.
Params:
  • toBooleanStackManipulation – A stack manipulation that widens the type that is represented by this instance to a boolean.
  • toByteStackManipulation – A stack manipulation that widens the type that is represented by this instance to a byte.
  • toShortStackManipulation – A stack manipulation that widens the type that is represented by this instance to a short.
  • toCharacterStackManipulation – A stack manipulation that widens the type that is represented by this instance to a char.
  • toIntegerStackManipulation – A stack manipulation that widens the type that is represented by this instance to a int.
  • toLongStackManipulation – A stack manipulation that widens the type that is represented by this instance to a long.
  • toFloatStackManipulation – A stack manipulation that widens the type that is represented by this instance to a float.
  • toDoubleStackManipulation – A stack manipulation that widens the type that is represented by this instance to a double.
/** * 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.
Params:
  • typeDefinition – A non-void primitive type that is to be widened into another type.
Returns:A delegate for the given type.
/** * 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.
Params:
  • typeDefinition – A non-void primitive type that is the expected result of the widening operation.
Returns:A widening instruction or an illegal stack manipulation if such widening is not legitimate.
/** * 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); } }
A stack manipulation that widens a primitive type into a more general primitive type.
/** * A stack manipulation that widens a primitive type into a more general primitive type. */
@HashCodeAndEqualsPlugin.Enhance protected static class WideningStackManipulation implements StackManipulation {
The opcode for executing the conversion.
/** * The opcode for executing the conversion. */
private final int conversionOpcode;
The size change of applying the conversion.
/** * The size change of applying the conversion. */
private final Size size;
Creates a new widening stack manipulation.
Params:
  • conversionOpcode – The opcode for executing the conversion.
  • size – The size change of applying the conversion.
/** * 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; }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean isValid() { return true; }
{@inheritDoc}
/** * {@inheritDoc} */
public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) { methodVisitor.visitInsn(conversionOpcode); return size; } } }