@Override
 public Byte toObject(
     byte[] b,
     int o,
     int l,
     PDataType actualType,
     SortOrder sortOrder,
     Integer maxLength,
     Integer scale) {
   if (l == 0) {
     return null;
   }
   if (equalsAny(
       actualType,
       PDouble.INSTANCE,
       PUnsignedDouble.INSTANCE,
       PFloat.INSTANCE,
       PUnsignedFloat.INSTANCE,
       PLong.INSTANCE,
       PUnsignedLong.INSTANCE,
       PInteger.INSTANCE,
       PUnsignedInt.INSTANCE,
       PSmallint.INSTANCE,
       PUnsignedSmallint.INSTANCE,
       PTinyint.INSTANCE,
       PUnsignedTinyint.INSTANCE)) {
     return actualType.getCodec().decodeByte(b, o, sortOrder);
   } else if (actualType == PDecimal.INSTANCE) {
     BigDecimal bd = (BigDecimal) actualType.toObject(b, o, l, actualType, sortOrder);
     return bd.byteValueExact();
   }
   throwConstraintViolationException(actualType, this);
   return null;
 }
  /**
   * Converts a {@link BigDecimal} value into the requested return type if possible.
   *
   * @param value the value
   * @param returnType the class of the returned value; it must be one of {@link BigDecimal}, {@link
   *     Double}, {@link Float}, {@link BigInteger}, {@link Long}, {@link Integer}, {@link Short},
   *     or {@link Byte}
   * @return the converted value
   * @throws IllegalArgumentException if the conversion is not possible or would lead to loss of
   *     data
   * @throws ClassCastException if the return type is not allowed
   */
  protected static <T> T convertDecimal(final BigDecimal value, final Class<T> returnType)
      throws IllegalArgumentException, ClassCastException {

    if (returnType.isAssignableFrom(BigDecimal.class)) {
      return returnType.cast(value);
    } else if (returnType.isAssignableFrom(Double.class)) {
      final double doubleValue = value.doubleValue();
      if (BigDecimal.valueOf(doubleValue).compareTo(value) == 0) {
        return returnType.cast(doubleValue);
      } else {
        throw new IllegalArgumentException();
      }
    } else if (returnType.isAssignableFrom(Float.class)) {
      final Float floatValue = value.floatValue();
      if (BigDecimal.valueOf(floatValue).compareTo(value) == 0) {
        return returnType.cast(floatValue);
      } else {
        throw new IllegalArgumentException();
      }
    } else {
      try {
        if (returnType.isAssignableFrom(BigInteger.class)) {
          return returnType.cast(value.toBigIntegerExact());
        } else if (returnType.isAssignableFrom(Long.class)) {
          return returnType.cast(value.longValueExact());
        } else if (returnType.isAssignableFrom(Integer.class)) {
          return returnType.cast(value.intValueExact());
        } else if (returnType.isAssignableFrom(Short.class)) {
          return returnType.cast(value.shortValueExact());
        } else if (returnType.isAssignableFrom(Byte.class)) {
          return returnType.cast(value.byteValueExact());
        } else {
          throw new ClassCastException("unsupported return type " + returnType.getSimpleName());
        }
      } catch (final ArithmeticException e) {
        throw new IllegalArgumentException(e);
      }
    }
  }