@SuppressWarnings({ "rawtypes", "unchecked" })
    public static <T> T cast(Object obj, Class<T> targetClass, ObjectReaderProvider provider) {
        if (obj == null) {
            return null;
        }

        if (targetClass.isInstance(obj)) {
            return (T) obj;
        }

        if (targetClass == Date.class) {
            return (T) toDate(obj);
        }

        if (targetClass == Instant.class) {
            return (T) toInstant(obj);
        }

        if (targetClass == String.class) {
            if (obj instanceof Character) {
                return (T) obj.toString();
            }

            return (T) JSON.toJSONString(obj);
        }

        if (targetClass == AtomicInteger.class) {
            return (T) new AtomicInteger(toIntValue(obj));
        }

        if (targetClass == AtomicLong.class) {
            return (T) new AtomicLong(toLongValue(obj));
        }

        if (targetClass == AtomicBoolean.class) {
            return (T) new AtomicBoolean((Boolean) obj);
        }

        if (obj instanceof Map) {
            ObjectReader objectReader = provider.getObjectReader(targetClass);
            return (T) objectReader.createInstance((Map) obj, 0L);
        }

        Function typeConvert = provider.getTypeConvert(obj.getClass(), targetClass);
        if (typeConvert != null) {
            return (T) typeConvert.apply(obj);
        }

        if (targetClass.isEnum()) {
            ObjectReader objectReader = JSONFactory.getDefaultObjectReaderProvider().getObjectReader(targetClass);
            if (objectReader instanceof ObjectReaderImplEnum) {
                if (obj instanceof Integer) {
                    int intValue = (Integer) obj;
                    return (T) ((ObjectReaderImplEnum) objectReader).of(intValue);
                }
            } else {
                JSONReader jsonReader = JSONReader.of(JSON.toJSONString(obj));
                return (T) objectReader.readObject(jsonReader, targetClass, null, 0);
            }
        }

        if (obj instanceof String) {
            String json = (String) obj;
            if (json.isEmpty() || "null".equals(json)) {
                return null;
            }

            JSONReader jsonReader;
            char first = json.trim().charAt(0);
            if (first == '"' || first == '{' || first == '[') {
                jsonReader = JSONReader.of(json);
            } else {
                jsonReader = JSONReader.of(
                        JSON.toJSONString(json));
            }

            ObjectReader objectReader = JSONFactory
                    .getDefaultObjectReaderProvider()
                    .getObjectReader(targetClass);
            return (T) objectReader.readObject(jsonReader, targetClass, null, 0);
        }

        if (obj instanceof Collection) {
            return (T) provider.getObjectReader(targetClass)
                    .createInstance((Collection) obj);
        }

        String className = targetClass.getName();
        if (obj instanceof Integer || obj instanceof Long) {
            long millis = ((Number) obj).longValue();
            switch (className) {
                case "java.sql.Date":
                    return (T) JdbcSupport.createDate(millis);
                case "java.sql.Timestamp":
                    return (T) JdbcSupport.createTimestamp(millis);
                case "java.sql.Time":
                    return (T) JdbcSupport.createTime(millis);
                case "java.time.LocalDateTime":
                    return (T) LocalDateTime.ofInstant(
                            Instant.ofEpochMilli(millis),
                            DateUtils.DEFAULT_ZONE_ID);
                default:
                    break;
            }
        }
        // fix org.bson.types.Decimal128 to Double
        String objClassName = obj.getClass().getName();
        if (objClassName.equals("org.bson.types.Decimal128") && targetClass == Double.class) {
            ObjectWriter objectWriter = JSONFactory
                    .getDefaultObjectWriterProvider()
                    .getObjectWriter(obj.getClass());
            if (objectWriter instanceof ObjectWriterPrimitiveImpl) {
                Function function = ((ObjectWriterPrimitiveImpl<?>) objectWriter).getFunction();
                if (function != null) {
                    Object apply = function.apply(obj);
                    Function DecimalTypeConvert = provider.getTypeConvert(apply.getClass(), targetClass);
                    if (DecimalTypeConvert != null) {
                        return (T) DecimalTypeConvert.apply(obj);
                    }
                }
            }
        }

        ObjectWriter objectWriter = JSONFactory
                .getDefaultObjectWriterProvider()
                .getObjectWriter(obj.getClass());
        if (objectWriter instanceof ObjectWriterPrimitiveImpl) {
            Function function = ((ObjectWriterPrimitiveImpl<?>) objectWriter).getFunction();
            if (function != null) {
                Object apply = function.apply(obj);
                if (targetClass.isInstance(apply)) {
                    return (T) apply;
                }
            }
        }

        throw new JSONException("can not cast to " + className + ", from " + obj.getClass());
    }
All the positive powers of 10 that can be
represented exactly in double/float.
core/src/main/java/com/alibaba/fastjson2/util/TypeUtils.java