/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * 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.
 */

#include "ani_parse_utils.h"

#include <arpa/inet.h>
#include <memory>
#include <sys/mman.h>
#include <unistd.h>
#include <regex>

#include "nweb_helper.h"
#include "nweb_log.h"
#include "ohos_adapter_helper.h"
#include "securec.h"
#include "nweb_cache_options_impl.h"

#define MAX_FLOWBUF_DATA_SIZE 52428800 /* 50 MB */

namespace OHOS {
namespace NWeb {
bool AniParseUtils::ParseString(ani_env *env, ani_ref ref, std::string& outValue)
{
    ani_string str = static_cast<ani_string>(ref);
    ani_size strSize;
    auto status = env->String_GetUTF8Size(str, &strSize);
    if (status != ANI_OK) {
        WVLOG_E("AniUtils_ParseString String_GetUTF8Size failed, status: %{public}d", status);
        return false;
    }
    std::vector<char> buffer(strSize + 1);
    char* utfBuffer = buffer.data();
    ani_size bytes_written = 0;
    status = env->String_GetUTF8(str, utfBuffer, strSize + 1, &bytes_written);
    if (status != ANI_OK) {
        WVLOG_E("AniUtils_ParseString String_GetUTF8 failed, status: %{public}d", status);
        return false;
    }
    utfBuffer[bytes_written] = '\0';
    outValue = std::string(utfBuffer, strSize);
    return true;
}

bool AniParseUtils::IsString(ani_env *env, const ani_object& object)
{
    ani_class stringCls;
    ani_status status = env->FindClass("std.core.String", &stringCls);
    if (status != ANI_OK) {
        WVLOG_E("AniUtils_IsString FindClass status: %{public}d", status);
        return false;
    }
    ani_boolean isString = false;
    env->Object_InstanceOf(object, stringCls, &isString);
    return isString;
}

bool AniParseUtils::IsResource(ani_env *env, const ani_object& object)
{
    ani_class resourceCls;
    ani_status status =
        env->FindClass("global.resource.Resource", &resourceCls);
    if (status != ANI_OK) {
        WVLOG_E("AniUtils_IsResource FindClass status: %{public}d", status);
        return false;
    }
    ani_boolean isResource = false;
    env->Object_InstanceOf(object, resourceCls, &isResource);
    return isResource;
}

void* AniParseUtils::Unwrap(ani_env *env, const ani_object& object)
{
    ani_long thisVar;
    ani_status status = env->Object_GetFieldByName_Long(object, "nativePtr", &thisVar);
    if (status != ANI_OK) {
        WVLOG_E("AniUtils_Unwrap Object_GetFieldByName_Long status: %{public}d", status);
        return nullptr;
    }
    return reinterpret_cast<void *>(thisVar);
}

bool AniParseUtils::Wrap(ani_env *env, const ani_object& object, const char *className, const ani_long& thisVar)
{
    ani_status status;
    ani_class cls;
    if ((status = env->FindClass(className, &cls)) != ANI_OK) {
        WVLOG_E("AniUtils_Wrap FindClass status: %{public}d", status);
        return false;
    }
    ani_method innerWrapMethod;
    if ((status = env->Class_FindMethod(cls, "bindNativePtr", "l:", &innerWrapMethod)) != ANI_OK) {
        WVLOG_E("AniUtils_Wrap Class_FindMethod status: %{public}d", status);
        return false;
    }
    if ((status = env->Object_CallMethod_Void(object, innerWrapMethod, thisVar)) != ANI_OK) {
        WVLOG_E("AniUtils_Wrap Object_CallMethod_Void status: %{public}d", status);
        return false;
    }
    return true;
}

bool AniParseUtils::ParseDouble_t(ani_env* env, ani_ref ref, double& outValue)
{
    ani_class doubleClass;
    if (env->FindClass("std.core.Double", &doubleClass) != ANI_OK) {
        WVLOG_E("ParseDouble failed - invalid FindClass type");
        return false;
    }
    ani_boolean isDouble;
    if (env->Object_InstanceOf(static_cast<ani_object>(ref), doubleClass, &isDouble) != ANI_OK ||
        isDouble != ANI_TRUE) {
        WVLOG_E("ParseDouble failed - invalid double type");
        return false;
    }

    ani_double value = 0;
    if (env->Object_CallMethodByName_Double(static_cast<ani_object>(ref), "toDouble", ":d", &value) != ANI_OK) {
        WVLOG_E("ParseDouble failed");
        return false;
    }
    outValue = value;
    return true;
}

bool AniParseUtils::ParseBoolean_t(ani_env* env, ani_ref ref, bool& outValue)
{
    ani_class boolClass;
    if (env->FindClass("std.core.Boolean", &boolClass) != ANI_OK) {
        WVLOG_E("ParseBoolean failed - invalid FindClass type");
        return false;
    }
    ani_boolean isBool;
    if (env->Object_InstanceOf(static_cast<ani_object>(ref), boolClass, &isBool) != ANI_OK || isBool != ANI_TRUE) {
        WVLOG_E("ParseBoolean failed - invalid boolean type");
        return false;
    }

    ani_boolean boolValue = false;
    if (env->Object_CallMethodByName_Boolean(static_cast<ani_object>(ref), "toBoolean", ":z", &boolValue) != ANI_OK) {
        WVLOG_E("ParseBoolean failed");
        return false;
    }
    outValue = boolValue ? true : false;
    return true;
}

bool AniParseUtils::CreateObjectVoid(ani_env *env, const char *className, ani_object& object)
{
    ani_class cls;
    ani_status status = env->FindClass(className, &cls);
    if (status != ANI_OK) {
        WVLOG_E("find %{public}s class failed, status: %{public}d", className, status);
        return false;
    }
    ani_method ctor;
    if ((status = env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) != ANI_OK) {
        WVLOG_E("get %{public}s ctor method failed, status: %{public}d", className, status);
        return false;
    }
    if ((status = env->Object_New(cls, ctor, &object)) != ANI_OK) {
        WVLOG_E("new %{public}s failed, status: %{public}d", className, status);
        return false;
    }
    return true;
}

bool AniParseUtils::GetEnumItemByIndex(ani_env *env, const char* enumName, int32_t typeIndex, ani_enum_item& eType)
{
    ani_enum enumType;
    ani_status status = env->FindEnum(enumName, &enumType);
    if (status != ANI_OK) {
        WVLOG_E("find %{public}s enum failed, status: %{public}d", enumName, status);
        return false;
    }
    if ((status = env->Enum_GetEnumItemByIndex(enumType, typeIndex, &eType)) != ANI_OK) {
        WVLOG_E("get %{public}s item by index failed, status: %{public}d", enumName, status);
        return false;
    }
    return true;
}

ani_status AniParseUtils::SetPropertyByName_String(ani_env *env, ani_object aniCls,
                                                   const char *keyName, std::string keyValue)
{
    ani_status status;
    ani_ref string_ref;
    status = env->Object_GetPropertyByName_Ref(aniCls, keyName, &string_ref);
    if (status != ANI_OK) {
        WVLOG_E("Object_GetPropertyByName_Ref failed, key=%{public}s, name=%{public}s, status=%{public}d",
                keyName, keyValue.c_str(), status);
        return status;
    }

    ani_string aniResult{};
    status = env->String_NewUTF8(keyValue.c_str(), keyValue.size(), &aniResult);
    if (status != ANI_OK) {
        WVLOG_E("String_GetUTF8 failed, key=%{public}s, name=%{public}s, status=%{public}d",
                keyName, keyValue.c_str(), status);
        return status;
    }

    status = env->Object_SetPropertyByName_Ref(aniCls, keyName, static_cast<ani_ref>(aniResult));
    return status;
}

std::shared_ptr<CacheOptions> AniParseUtils::ParseCacheOptions(ani_env *env, ani_object cacheOptions)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return nullptr;
    }
    std::map<std::string, std::string> responseHeaders;
    auto defaultCacheOptions = std::make_shared<NWebCacheOptionsImpl>(responseHeaders);

    ani_ref cacheOptionsArray = nullptr;
    if (env->Object_GetPropertyByName_Ref(cacheOptions, "responseHeaders", &cacheOptionsArray) != ANI_OK) {
        WVLOG_E("PrecompileJavaScript defaultCacheOptions");
        return defaultCacheOptions;
    }

    if (!ParseStringArrayMap(env, static_cast<ani_object>(cacheOptionsArray), responseHeaders)) {
        WVLOG_E("PrecompileJavaScript defaultCacheOptions");
        return defaultCacheOptions;
    }
    return std::make_shared<NWebCacheOptionsImpl>(responseHeaders);
}

bool AniParseUtils::ParseStringArray(ani_env* env, ani_object argv, std::vector<std::string>& outValue)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return false;
    }
    ani_class cls;
    ani_boolean isArray = ANI_FALSE;
    ani_int arrayLength;
    ani_array arrayRef;
    if (env->FindClass("std.core.Array", &cls) != ANI_OK) {
        WVLOG_E("find array class failed");
        return false;
    }
    env->Object_InstanceOf(argv, cls, &isArray);
    if (!isArray) {
        WVLOG_E("argv must be array");
        return false;
    }

    arrayRef = static_cast<ani_array>(argv);
    ani_status status;
    if ((status = env->Object_GetPropertyByName_Int(argv, "length", &arrayLength)) != ANI_OK) {
        WVLOG_E("string array get length error status = %{public}d", status);
        return false;
    }
    WVLOG_I("stringArray size = %{public}d", static_cast<int>(arrayLength));
    for (ani_int i = 0; i < arrayLength; i++) {
        ani_ref arrayItem = nullptr;
        env->Array_Get(arrayRef, i, &arrayItem);
        std::string str;
        if (ParseString(env, arrayItem, str)) {
            outValue.push_back(str);
        }
    }
    return true;
}

bool AniParseUtils::ParseStringArrayMap(ani_env* env, ani_object argv, std::map<std::string, std::string>& outValue)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return false;
    }
    ani_class cls;
    ani_boolean isArray = ANI_FALSE;
    ani_array arrayRef;
    ani_int arrayLength;
    if (env->FindClass("std.core.Array", &cls) != ANI_OK) {
        WVLOG_E("find array class failed");
        return false;
    }
    env->Object_InstanceOf(argv, cls, &isArray);
    if (!isArray) {
        WVLOG_E("argv must be array");
        return false;
    }

    arrayRef = static_cast<ani_array>(argv);
    if (env->Object_GetPropertyByName_Int(argv, "length", &arrayLength) != ANI_OK) {
        WVLOG_E("get array length failed");
        return false;
    }
    for (ani_int i = 0; i < arrayLength; i++) {
        ani_ref arrayItem = nullptr;
        env->Array_Get(arrayRef, i, &arrayItem);
        ani_ref keyObj = nullptr;
        ani_ref valueObj = nullptr;
        env->Object_GetPropertyByName_Ref(static_cast<ani_object>(arrayItem), "headerKey", &keyObj);
        env->Object_GetPropertyByName_Ref(static_cast<ani_object>(arrayItem), "headerValue", &valueObj);

        std::string keyString;
        std::string valueString;
        if (!AniParseUtils::ParseString(env, keyObj, keyString)) {
            WVLOG_E("Parse keyString failed.");
            return false;
        }
        if (!AniParseUtils::ParseString(env, valueObj, valueString)) {
            WVLOG_E("Parse valueString failed.");
            return false;
        }
        outValue[keyString] = valueString;
    }

    return true;
}

bool AniParseUtils::EnumParseInt32_t(ani_env* env, ani_enum_item enum_item, int32_t& outValue)
{
    if (env == nullptr) {
        WVLOG_E("null env");
        return false;
    }

    ani_class doubleObject;
    if (env->FindClass("std.core.Object", &doubleObject) != ANI_OK) {
        WVLOG_E("EnumParseInt32 failed - invalid FindClass type");
        return false;
    }
    ani_boolean isObject = ANI_FALSE;
    if (env->Object_InstanceOf(static_cast<ani_object>(enum_item), doubleObject, &isObject) != ANI_OK ||
        isObject != ANI_TRUE) {
        WVLOG_E("EnumParseInt32 failed - invalid int type");
        return false;
    }
    ani_int number = 0;
    ani_status status = env->EnumItem_GetValue_Int(enum_item, &number);
    if (status != ANI_OK) {
        WVLOG_E("EnumParseInt32 failed - EnumItem_GetValue_Int failed");
        return false;
    }
    outValue = static_cast<int32_t>(number);
    return true;
}

bool AniParseUtils::GetStringList(ani_env *env, ani_object array, std::vector<std::string>& outValue)
{
    ani_int arrayLength;
    if (env->Object_GetPropertyByName_Int(array, "length", &arrayLength) != ANI_OK) {
        WVLOG_E("Param check failed, unable to get array length.");
        return false;
    }
    for (int32_t i = 0; i < static_cast<int32_t>(arrayLength); ++i) {
        ani_ref elementRef;
        if (env->Object_CallMethodByName_Ref(array, "$_get", "i:Y", &elementRef,
            static_cast<ani_int>(i)) != ANI_OK) {
            WVLOG_E("Failed to get element at index %d", i);
            return false;
        }
        std::string strValue;
        if (!AniParseUtils::ParseString(env, elementRef, strValue)) {
            WVLOG_W("Failed to parse string at index %d", i);
            continue;
        }
        outValue.push_back(strValue);
    }
    return true;
}

bool AniParseUtils::ParseIP(ani_env *env, ani_object urlObj, std::string& ip)
{
    if (AniParseUtils::ParseString(env, urlObj, ip)) {
        if (ip == "") {
            WVLOG_E("The IP is null");
            return false;
        }

        unsigned char buf[sizeof(struct in6_addr)];
        if ((inet_pton(AF_INET, ip.c_str(), buf) == 1) || (inet_pton(AF_INET6, ip.c_str(), buf) == 1)) {
            return true;
        }
        WVLOG_E("IP error.");
        return false;
    }

    WVLOG_E("Unable to parse type from ip object.");
    return false;
}

bool IsFormatStringOfLength(const std::string& str)
{
    std::regex pattern("^\\d+(px|vp|%)?$");
    return std::regex_match(str, pattern);
}

bool IsNumberOfLength(const std::string& value)
{
    if (value.empty()) {
        WVLOG_E("value is empty");
        return false;
    }
    return std::all_of(value.begin(), value.end(), [](char i) { return isdigit(i); });
}

bool TransStringToInt(const std::string& str, int32_t& value)
{
    if (str.empty()) {
        WVLOG_E("str is empty");
        return false;
    }
    char* endPtr = nullptr;
    errno = 0;
    int64_t tempValue = std::strtoll(str.c_str(), &endPtr, 10);
    if (endPtr == str || errno == ERANGE || *endPtr != '\0') {
        return false;
    }
    if (tempValue < std::numeric_limits<int32_t>::min() || tempValue > std::numeric_limits<int32_t>::max()) {
        WVLOG_E("input trans failed: out of range");
        value = 0;
        return false;
    }
    value = static_cast<int32_t>(tempValue);
    return true;
}

bool AniParseUtils::ParseJsLengthStringToInt(const std::string& input, PixelUnit& type, int32_t& value)
{
        if (input.empty() || input.size() > MAX_STRING_TO_INT32_LENGTH) {
            WVLOG_E("invalid input");
            return false;
        }
        if (!IsFormatStringOfLength(input)) {
            WVLOG_E("IsFormatStringOfLength failed");
            return false;
        }
        if (IsNumberOfLength(input)) {
            if (TransStringToInt(input, value)) {
                type = PixelUnit::VP;
                return true;
            }
            return false;
        }
        if (input.back() == '%') {
            std::string trans = input.substr(0, input.length() - 1);
            if (IsNumberOfLength(trans)) {
                if (TransStringToInt(trans, value)) {
                    type = PixelUnit::PERCENTAGE;
                    return true;
                }
            }
            return false;
        }
        if (input.length() < PARSE_THREE) {
            WVLOG_E("input.leng below PARSE_THREE");
            return false;
        }
        std::string lastTwo = input.substr(input.length() - PARSE_TWO);
        std::string trans = input.substr(0, input.length() - PARSE_TWO);
        if (!IsNumberOfLength(trans)) {
            WVLOG_E("IsNumberOfLength failed");
            return false;
        }
        if (lastTwo == "px") {
            if (TransStringToInt(trans, value)) {
                type = PixelUnit::PX;
                return true;
            }
        } else if (lastTwo == "vp") {
            if (TransStringToInt(trans, value)) {
                type = PixelUnit::VP;
                return true;
            }
        }
        WVLOG_E("invaild lastTwo");
        return false;
}

bool AniParseUtils::ParseInt32(ani_env* env, ani_ref ref, int32_t& outValue)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return false;
    }
    ani_class intClass;
    if (env->FindClass("std.core.Int", &intClass) != ANI_OK) {
        WVLOG_E("ParseInt32 failed - invalid FindClass type");
        return false;
    }
    ani_boolean isInt;
    if (env->Object_InstanceOf(static_cast<ani_object>(ref), intClass, &isInt) != ANI_OK || isInt != ANI_TRUE) {
        WVLOG_E("ParseInt32 failed - invalid int type");
        return false;
    }

    ani_int value = 0;
    if (env->Object_CallMethodByName_Int(static_cast<ani_object>(ref), "toInt", ":i", &value) != ANI_OK) {
        WVLOG_E("ParseInt32 failed");
        return false;
    }
    outValue = static_cast<int32_t>(value);
    return true;
}

bool AniParseUtils::IsFunction(ani_env* env, const ani_object& object)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return false;
    }
    ani_class functionCls;
    ani_status status = env->FindClass("std.core.Function", &functionCls);
    if (status != ANI_OK) {
        WVLOG_E("AniUtils_IsFunction FindClass status: %{public}d", status);
        return false;
    }
    ani_boolean isFunction = false;
    auto statusInstanceOf = env->Object_InstanceOf(object, functionCls, &isFunction);
    if (statusInstanceOf != ANI_OK) {
        WVLOG_E("IsFunction failed - Object_InstanceOf error: %d", statusInstanceOf);
        return false;
    }
    return isFunction;
}

bool AniParseUtils::IsDouble(ani_env* env, const ani_object& object)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return false;
    }
    ani_class doubleCls;
    ani_status status = env->FindClass("std.core.Double", &doubleCls);
    if (status != ANI_OK) {
        WVLOG_E("AniUtils_IsDouble FindClass status: %{public}d", status);
        return false;
    }
    ani_boolean isDouble = false;
    auto statusInstanceOf = env->Object_InstanceOf(object, doubleCls, &isDouble);
    if (statusInstanceOf != ANI_OK) {
        WVLOG_E("IsDouble failed - Object_InstanceOf error: %d", statusInstanceOf);
        return false;
    }
    return isDouble;
}

bool AniParseUtils::IsObject(ani_env* env, const ani_object& object)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return false;
    }
    ani_class objectCls;
    ani_status status = env->FindClass("std.core.Object", &objectCls);
    if (status != ANI_OK) {
        WVLOG_E("AniUtils_IsObject FindClass status: %{public}d", status);
        return false;
    }
    ani_boolean isObject = false;
    auto statusInstanceOf = env->Object_InstanceOf(object, objectCls, &isObject);
    if (statusInstanceOf != ANI_OK) {
        WVLOG_E("IsObject failed - Object_InstanceOf error: %d", statusInstanceOf);
        return false;
    }
    return isObject;
}

bool AniParseUtils::CreateBoolean(ani_env *env, bool src, ani_object& aniObj)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return false;
    }
    static const char *className = "std.core.Boolean";
    ani_class cls;
    ani_status status = env->FindClass(className, &cls);
    if (status != ANI_OK) {
        WVLOG_E("find %{public}s class failed, status: %{public}d", className, status);
        return false;
    }
    ani_method ctor;
    status = env->Class_FindMethod(cls, "<ctor>", "z:", &ctor);
    if (status != ANI_OK) {
        WVLOG_E("get %{public}s ctor method failed, status: %{public}d", className, status);
        return false;
    }
    ani_boolean aniBool = src ? ANI_TRUE : ANI_FALSE;
    status = env->Object_New(cls, ctor, &aniObj, aniBool);
    if (status != ANI_OK) {
        WVLOG_E("new %{public}s failed, status: %{public}d", className, status);
        return false;
    }
    return true;
}

ani_object AniParseUtils::CreateDouble(ani_env* env, ani_double val)
{
    if (!env) {
        WVLOG_E("env is null");
        return nullptr;
    }
    static constexpr const char* className = "std.core.Double";
    ani_class doubleCls {};
    if (env->FindClass(className, &doubleCls) != ANI_OK) {
        WVLOG_E("find double class failed");
        return nullptr;
    }
    ani_method ctor {};
    if (env->Class_FindMethod(doubleCls, "<ctor>", "d:", &ctor) != ANI_OK) {
        WVLOG_E("find double ctor failed");
        return nullptr;
    }
    ani_object obj {};
    if (env->Object_New(doubleCls, ctor, &obj, static_cast<ani_double>(val)) != ANI_OK) {
        WVLOG_E("CreateDouble Failed");
        ani_ref undefinedRef;
        env->GetUndefined(&undefinedRef);
        return static_cast<ani_object>(undefinedRef);
    }
    return obj;
}

ani_object AniParseUtils::CreateInt(ani_env *env, ani_int val)
{
    static constexpr const char* className = "std.core.Int";
    ani_class intCls {};
    if (env->FindClass(className, &intCls) != ANI_OK) {
        WVLOG_E("find int class failed");
        return nullptr;
    }
    ani_method ctor {};
    if (env->Class_FindMethod(intCls, "<ctor>", "i:", &ctor) != ANI_OK) {
        WVLOG_E("find int ctor failed");
        return nullptr;
    }
    ani_object obj {};
    if (env->Object_New(intCls, ctor, &obj, static_cast<ani_int>(val)) != ANI_OK) {
        WVLOG_E("CreateInt Failed");
        ani_ref undefinedRef;
        env->GetUndefined(&undefinedRef);
        return static_cast<ani_object>(undefinedRef);
    }
    return obj;
}

ani_string AniParseUtils::StringToAniStr(ani_env* env, const std::string& str)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return nullptr;
    }
    ani_string result {};
    if (ANI_OK != env->String_NewUTF8(str.c_str(), str.size(), &result)) {
        return nullptr;
    }
    return result;
}

ani_ref AniParseUtils::CreateAniStringArray(ani_env* env, const std::vector<std::string>& paths)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return nullptr;
    }

    ani_ref undefinedRef = nullptr;
    if (ANI_OK != env->GetUndefined(&undefinedRef)) {
        WVLOG_E("GetUndefined Failed.");
        return nullptr;
    }
    ani_array array;
    if (ANI_OK != env->Array_New(paths.size(), undefinedRef, &array)) {
        WVLOG_E("new array ref error.");
        return nullptr;
    }
    for (size_t i = 0; i < paths.size(); ++i) {
        auto item = AniParseUtils::StringToAniStr(env, paths[i]);
        if (ANI_OK != env->Array_Set(array, i, item)) {
            return nullptr;
        }
    }
    return array;
}

bool AniParseUtils::ParseBoolean(ani_env* env, ani_ref ref, bool& outValue)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return false;
    }
    ani_class booleanClass;
    if (env->FindClass("std.core.Boolean", &booleanClass) != ANI_OK) {
        WVLOG_E("ParseBoolean failed - invalid FindClass type");
        return false;
    }
    ani_boolean isBoolean;
    if (env->Object_InstanceOf(static_cast<ani_object>(ref), booleanClass, &isBoolean) != ANI_OK ||
        isBoolean != ANI_TRUE) {
        WVLOG_E("ParseBoolean failed - invalid boolean type");
        return false;
    }

    ani_boolean boolValue;
    if (env->Object_CallMethodByName_Boolean(static_cast<ani_object>(ref), "toBoolean", ":z", &boolValue) != ANI_OK) {
        WVLOG_E("get bool value failed");
        return false;
    }
    outValue = static_cast<bool>(boolValue);
    return true;
}

bool AniParseUtils::ParseInt64(ani_env* env, ani_ref ref, int64_t& outValue)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return false;
    }
    ani_class longClass;
    if (env->FindClass("std.core.Long", &longClass) != ANI_OK) {
        WVLOG_E("ParseInt64 failed - invalid FindClass type");
        return false;
    }
    ani_boolean isLong;
    if (env->Object_InstanceOf(static_cast<ani_object>(ref), longClass, &isLong) != ANI_OK || isLong != ANI_TRUE) {
        WVLOG_E("ParseInt64 failed - invalid long type");
        return false;
    }

    ani_long value;
    if (env->Object_CallMethodByName_Long(static_cast<ani_object>(ref), "toLong", ":l", &value) != ANI_OK) {
        WVLOG_E("get long value failed");
        return false;
    }
    outValue = static_cast<int64_t>(value);
    return true;
}

bool AniParseUtils::ParseDouble(ani_env* env, ani_ref ref, double& outValue)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return false;
    }
    ani_class doubleClass;
    if (env->FindClass("std.core.Double", &doubleClass) != ANI_OK) {
        WVLOG_E("ParseDouble failed - invalid FindClass type");
        return false;
    }
    ani_boolean isDouble;
    if (env->Object_InstanceOf(static_cast<ani_object>(ref), doubleClass, &isDouble) != ANI_OK ||
        isDouble != ANI_TRUE) {
        WVLOG_E("ParseDouble failed - invalid double type");
        return false;
    }

    ani_double value;
    if (env->Object_CallMethodByName_Double(static_cast<ani_object>(ref), "toDouble", ":d", &value) != ANI_OK) {
        WVLOG_E("get double value failed");
        return false;
    }
    outValue = static_cast<double>(value);
    return true;
}

bool AniParseUtils::IsBoolean(ani_env* env, const ani_object& object)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return false;
    }
    ani_class booleanCls;
    ani_status status = env->FindClass("std.core.Boolean", &booleanCls);
    if (status != ANI_OK) {
        WVLOG_E("AniUtils_IsBoolean FindClass status: %{public}d", status);
        return false;
    }
    ani_boolean isBoolean = false;
    auto statusInstanceOf = env->Object_InstanceOf(object, booleanCls, &isBoolean);
    if (statusInstanceOf != ANI_OK) {
        WVLOG_E("AniUtils_IsBoolean failed - Object_InstanceOf error: %d", statusInstanceOf);
        return false;
    }
    return isBoolean;
}

bool AniParseUtils::IsInteger(ani_env* env, const ani_object& object)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return false;
    }
    ani_class longCls;
    ani_status status = env->FindClass("std.core.Long", &longCls);
    if (status != ANI_OK) {
        WVLOG_E("AniUtils_IsINTEGER FindClass status: %{public}d", status);
        return false;
    }
    ani_boolean isLong = false;
    auto statusInstanceOf = env->Object_InstanceOf(object, longCls, &isLong);
    if (statusInstanceOf != ANI_OK) {
        WVLOG_E("AniUtils_IsINTEGER failed - Object_InstanceOf error: %d", statusInstanceOf);
        return false;
    }
    return isLong;
}

bool AniParseUtils::ParseInt64Array(ani_env* env, ani_object argv, std::vector<int64_t>& outValue)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return false;
    }
    ani_class cls;
    ani_boolean isArray = ANI_FALSE;
    ani_int arrayLength;
    ani_array arrayRef;
    env->FindClass("std.core.Array", &cls);
    env->Object_InstanceOf(argv, cls, &isArray);
    if (!isArray) {
        WVLOG_E("argv must be array");
        return false;
    }

    arrayRef = static_cast<ani_array>(argv);
    env->Object_GetPropertyByName_Int(argv, "length", &arrayLength);
    for (ani_int i = 0; i < arrayLength; i++) {
        ani_ref arrayItem = nullptr;
        env->Array_Get(arrayRef, i, &arrayItem);
        int64_t value;
        if (ParseInt64(env, arrayItem, value)) {
            outValue.push_back(value);
        }
    }
    return true;
}

bool AniParseUtils::ParseBooleanArray(ani_env* env, ani_object argv, std::vector<bool>& outValue)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return false;
    }
    ani_class cls;
    ani_boolean isArray = ANI_FALSE;
    ani_int arrayLength;
    ani_array arrayRef;
    if (env->FindClass("std.core.Array", &cls) != ANI_OK) {
        WVLOG_E("find array class failed");
        return false;
    }
    env->Object_InstanceOf(argv, cls, &isArray);
    if (!isArray) {
        WVLOG_E("argv must be array");
        return false;
    }

    arrayRef = static_cast<ani_array>(argv);
    if (env->Object_GetPropertyByName_Int(argv, "length", &arrayLength) != ANI_OK) {
        WVLOG_E("get array length failed");
        return false;
    }
    for (ani_int i = 0; i < arrayLength; i++) {
        ani_ref arrayItem = nullptr;
        env->Array_Get(arrayRef, i, &arrayItem);
        bool value;
        if (ParseBoolean(env, arrayItem, value)) {
            outValue.push_back(value);
        }
    }
    return true;
}

bool AniParseUtils::ParseDoubleArray(ani_env* env, ani_object argv, std::vector<double>& outValue)
{
    if (env == nullptr) {
        WVLOG_E("env is nullptr");
        return false;
    }
    ani_class cls;
    ani_boolean isArray = ANI_FALSE;
    ani_int arrayLength;
    ani_array arrayRef;
    env->FindClass("std.core.Array", &cls);
    env->Object_InstanceOf(argv, cls, &isArray);
    if (!isArray) {
        WVLOG_E("argv must be array");
        return false;
    }

    arrayRef = static_cast<ani_array>(argv);
    if (env->Object_GetPropertyByName_Int(argv, "length", &arrayLength) != ANI_OK) {
        WVLOG_E("get array length failed");
        return false;
    }
    for (ani_int i = 0; i < arrayLength; i++) {
        ani_ref arrayItem = nullptr;
        if (env->Array_Get(arrayRef, i, &arrayItem) != ANI_OK) {
            WVLOG_E("get array value failed");
            return false;
        }
        double value;
        if (env->Object_CallMethodByName_Double(static_cast<ani_object>(arrayItem), "toDouble", ":d", &value) ==
            ANI_OK) {
            outValue.push_back(value);
        }
    }
    return true;
}

ErrCode AniParseUtils::ConstructStringFlowbuf(ani_env *env, const std::string script, int& fd, size_t& scriptLength)
{
    if (!env) {
        WVLOG_E("env is nullptr");
        return NWebError::PARAM_CHECK_ERROR;
    }

    ani_string str = nullptr;
    if (env->String_NewUTF8(script.c_str(), script.size(), &str) != ANI_OK) {
        WVLOG_E("create ani_string failed");
        return NWebError::NEW_OOM;
    }
    if (env->String_GetUTF8Size(str, &scriptLength) != ANI_OK) {
        WVLOG_E("GetUTF8Size error");
        return NWebError::NEW_OOM;
    }
    if (scriptLength + 1 > MAX_FLOWBUF_DATA_SIZE) {
        WVLOG_E("String length is too long");
        return NWebError::PARAM_CHECK_ERROR;
    }

    auto flowbufferAdapter = OhosAdapterHelper::GetInstance().CreateFlowbufferAdapter();
    if (!flowbufferAdapter) {
        WVLOG_E("Create flowbuffer adapter failed");
        return NWebError::NEW_OOM;
    }

    auto ashmem = flowbufferAdapter->CreateAshmem(scriptLength + 1, PROT_READ | PROT_WRITE, fd);
    if (!ashmem) {
        return NWebError::NEW_OOM;
    }

    // write to ashmem
    if (memcpy_s(ashmem, scriptLength + 1, script.c_str(), scriptLength) != EOK) {
        WVLOG_E("ConstructArrayBufFlowbuf, memory copy failed");
        return NWebError::NEW_OOM;
    }
    static_cast<char*>(ashmem)[scriptLength] = '\0';
    WVLOG_D("ConstructStringFlowbuf successful");
    return NWebError::NO_ERROR;
}

ErrCode AniParseUtils::ConstructArrayBufFlowbuf(ani_env* env, const ani_object script, int& fd, size_t& scriptLength)
{
    if (!env) {
        WVLOG_E("env is nullptr");
        return NWebError::PARAM_CHECK_ERROR;
    }
    ani_boolean isArrayBuffer = false;
    ani_class arrayBufferClass;
    ani_status status;
    if ((status = env->FindClass("std.core.ArrayBuffer", &arrayBufferClass)) != ANI_OK) {
        WVLOG_E("find buffer class error status : %{public}d", status);
        return NWebError::PARAM_CHECK_ERROR;
    }
    if ((env->Object_InstanceOf(script, arrayBufferClass, &isArrayBuffer) != ANI_OK) || !isArrayBuffer) {
        WVLOG_E("Object_InstanceOf error status : %{public}d", status);
        return NWebError::PARAM_CHECK_ERROR;
    }

    char* arrBuf = nullptr;
    if ((status = env->ArrayBuffer_GetInfo(
        static_cast<ani_arraybuffer>(script), reinterpret_cast<void**>(&arrBuf), &scriptLength)) != ANI_OK) {
        WVLOG_E("ArrayBuffer_GetInfo error status : %{public}d", status);
        return NWebError::PARAM_CHECK_ERROR;
    }

    // get ashmem
    auto flowbufferAdapter = OhosAdapterHelper::GetInstance().CreateFlowbufferAdapter();
    if (!flowbufferAdapter) {
        WVLOG_E("Create flowbuffer adapter failed");
        return NWebError::NEW_OOM;
    }
    auto ashmem = flowbufferAdapter->CreateAshmem(scriptLength + 1, PROT_READ | PROT_WRITE, fd);
    if (!ashmem) {
        return NWebError::NEW_OOM;
    }

    // write to ashmem
    if (memcpy_s(ashmem, scriptLength + 1, arrBuf, scriptLength) != EOK) {
        WVLOG_E("ConstructArrayBufFlowbuf, memory copy failed");
        return NWebError::NEW_OOM;
    }
    static_cast<char*>(ashmem)[scriptLength] = '\0';
    return NWebError::NO_ERROR;
}

ani_ref ConvertToAniHandlerOfString(ani_env* env, std::shared_ptr<NWebMessage> src)
{
    WVLOG_I("enter ConvertToNapiHandlerOfString");
    if (!env || !src) {
        WVLOG_E("env is nullptr");
        return nullptr;
    }
    std::string msgStr = src->GetString();
    ani_string dstTemp;
    if (env->String_NewUTF8(msgStr.c_str(), msgStr.size(), &dstTemp) != ANI_OK) {
        WVLOG_E("create object failed");
        return nullptr;
    }
    return static_cast<ani_ref>(dstTemp);
}

ani_ref ConvertToAniHandlerOfBinary(ani_env* env, std::shared_ptr<NWebMessage> src)
{
    WVLOG_I("enter ConvertToNapiHandlerOfBinary");
    if (!env || !src) {
        WVLOG_E("env is nullptr");
        return nullptr;
    }
    std::vector<uint8_t> msgArr = src->GetBinary();
    void* arrayData = nullptr;
    ani_arraybuffer arraybuffer;
    ani_status status = env->CreateArrayBuffer(msgArr.size(), &arrayData, &arraybuffer);
    if (status != ANI_OK) {
        WVLOG_E("Create arraybuffer failed status : %{public}d", status);
        return nullptr;
    }
    for (size_t i = 0; i < msgArr.size(); ++i) {
        *(uint8_t*)((uint8_t*)arrayData + i) = msgArr[i];
    }
    WVLOG_I("ConvertToNapiHandlerOfBinary successful!");
    return static_cast<ani_ref>(arraybuffer);
}

ani_ref ConvertToAniHandlerOfBoolean(ani_env* env, std::shared_ptr<NWebMessage> src)
{
    WVLOG_I("enter ConvertToAniHandlerOfBoolean");
    if (!env || !src) {
        WVLOG_E("env is nullptr");
        return nullptr;
    }

    ani_class bool_cls;
    ani_status status;
    if ((status = env->FindClass("std.core.Boolean", &bool_cls)) != ANI_OK) {
        WVLOG_E("error in FindClass status : %{public}d", status);
        return nullptr;
    }

    ani_method boolInfoCtor;
    if ((status = env->Class_FindMethod(bool_cls, "<ctor>", "z:", &boolInfoCtor)) != ANI_OK) {
        WVLOG_E("error in FindMethod status : %{public}d", status);
        return nullptr;
    }

    ani_object boolInfoObj;
    if (env->Object_New(bool_cls, boolInfoCtor, &boolInfoObj, static_cast<ani_boolean>(src->GetBoolean())) != ANI_OK) {
        WVLOG_E("create bool object failed");
        return nullptr;
    }
    return static_cast<ani_ref>(boolInfoObj);
}

ani_ref ConvertToAniHandlerOfInteger(ani_env* env, std::shared_ptr<NWebMessage> src)
{
    WVLOG_I("enter ConvertToAniHandlerOfInteger");
    if (!env || !src) {
        WVLOG_E("env is nullptr");
        return nullptr;
    }

    ani_class integer_cls;
    ani_status status;
    if ((status = env->FindClass("std.core.Long", &integer_cls)) != ANI_OK) {
        WVLOG_E("error in FindClass status : %{public}d", status);
        return nullptr;
    }

    ani_method integerInfoCtor;
    if ((status = env->Class_FindMethod(integer_cls, "<ctor>", "l:", &integerInfoCtor)) != ANI_OK) {
        WVLOG_E("error in FindMethod status : %{public}d", status);
        return nullptr;
    }

    ani_object integerInfoObj;
    if (env->Object_New(integer_cls, integerInfoCtor, &integerInfoObj, static_cast<ani_long>(src->GetInt64()))
        != ANI_OK) {
        WVLOG_E("create object failed");
        return nullptr;
    }
    return static_cast<ani_ref>(integerInfoObj);
}

ani_ref ConvertToAniHandlerOfDouble(ani_env* env, std::shared_ptr<NWebMessage> src)
{
    WVLOG_I("enter ConvertToAniHandlerOfDouble");
    if (!env || !src) {
        WVLOG_E("env is nullptr");
        return nullptr;
    }

    ani_class double_cls;
    ani_status status;
    if ((status = env->FindClass("std.core.Double", &double_cls)) != ANI_OK) {
        WVLOG_E("error in FindClass status : %{public}d", status);
        return nullptr;
    }

    ani_method doubleInfoCtor;
    if ((status = env->Class_FindMethod(double_cls, "<ctor>", "d:", &doubleInfoCtor)) != ANI_OK) {
        WVLOG_E("error in FindMethod status : %{public}d", status);
        return nullptr;
    }

    ani_object doubleInfoObj;
    if (env->Object_New(double_cls, doubleInfoCtor, &doubleInfoObj, static_cast<ani_long>(src->GetDouble()))
        != ANI_OK) {
        WVLOG_E("create double object failed");
        return nullptr;
    }
    return static_cast<ani_ref>(doubleInfoObj);
}

ani_ref ConvertToAniHandlerOfError(ani_env* env, std::shared_ptr<NWebMessage> src)
{
    WVLOG_I("enter ConvertToAniHandlerOfError");
    if (!env || !src) {
        WVLOG_E("env is nullptr");
        return nullptr;
    }
    std::string errorMsg = src->GetErrName() + ": " + src->GetErrMsg();
    ani_string message = nullptr;
    if (env->String_NewUTF8(errorMsg.c_str(), errorMsg.length(), &message) != ANI_OK) {
        WVLOG_E("error create ani_string object");
        return nullptr;
    }

    ani_class errCls;
    ani_status status;
    if ((status = env->FindClass("std.core.NullPointerError", &errCls)) != ANI_OK) {
        WVLOG_E("error in FindClass status : %{public}d", status);
        return nullptr;
    }

    ani_method errInfoCtor;
    if ((status = env->Class_FindMethod(errCls, "<ctor>",
        "C{std.core.String}C{std.core.ErrorOptions}:", &errInfoCtor)) != ANI_OK) {
        WVLOG_E("error in FindMethod status : %{public}d", status);
        return nullptr;
    }

    ani_ref undefinedArgument;
    if (ANI_OK != env->GetUndefined(&undefinedArgument)) {
        WVLOG_E("Failed to get undefined");
        return nullptr;
    }

    ani_object errObj;
    if (env->Object_New(errCls, errInfoCtor, &errObj, message, undefinedArgument) != ANI_OK) {
        WVLOG_E("create error object failed");
        return nullptr;
    }
    return static_cast<ani_ref>(errObj);
}

ani_ref ConvertToAniHandlerOfStringArr(ani_env* env, std::shared_ptr<NWebMessage> src)
{
    WVLOG_I("enter ConvertToAniHandlerOfStringArray");
    if (!env || !src) {
        WVLOG_E("env is nullptr");
        return nullptr;
    }
    std::vector<std::string> values = src->GetStringArray();

    ani_ref undefinedRef = nullptr;
    if (ANI_OK != env->GetUndefined(&undefinedRef)) {
        WVLOG_E("WebMessageExt GetUndefined Failed.");
        return nullptr;
    }

    ani_array array = nullptr;
    if (ANI_OK != env->Array_New(values.size(), undefinedRef, &array)) {
        WVLOG_E("WebMessageExt new array ref error.");
        return array;
    }

    for (size_t i = 0; i < values.size(); ++i) {
        ani_string result {};
        if (ANI_OK != env->String_NewUTF8(values[i].c_str(), values[i].size(), &result)) {
            continue;
        }
        if (ANI_OK != env->Array_Set(array, i, result)) {
            return array;
        }
    }
    return static_cast<ani_ref>(array);
}

ani_ref ConvertToAniHandlerOfBooleanArr(ani_env* env, std::shared_ptr<NWebMessage> src)
{
    WVLOG_I("enter ConvertToAniHandlerOfBooleanArr");
    if (!env || !src) {
        WVLOG_E("env is nullptr");
        return nullptr;
    }
    std::vector<bool> values = src->GetBooleanArray();
    size_t valueSize = values.size();

    ani_ref undefinedRef = nullptr;
    if (ANI_OK != env->GetUndefined(&undefinedRef)) {
        WVLOG_E("WebMessageExt GetUndefined Failed.");
        return nullptr;
    }

    ani_array array = nullptr;
    if (ANI_OK != env->Array_New(values.size(), undefinedRef, &array)) {
        WVLOG_E("WebMessageExt new array ref error.");
        return array;
    }

    ani_class booleanCls {};
    if (ANI_OK != env->FindClass("std.core.Boolean", &booleanCls)) {
        return nullptr;
    }
    ani_method ctor {};
    if (ANI_OK != env->Class_FindMethod(booleanCls, "<ctor>", "z:", &ctor)) {
        return nullptr;
    }

    for (size_t i = 0; i < valueSize; i++) {
        ani_boolean item = static_cast<ani_boolean>(values[i]);
        ani_object obj {};
        if (env->Object_New(booleanCls, ctor, &obj, item) != ANI_OK) {
            return nullptr;
        }
        if (ANI_OK != env->Array_Set(array, i, obj)) {
            return array;
        }
    }
    return static_cast<ani_ref>(array);
}

ani_ref ConvertToAniHandlerOfDoubleArr(ani_env* env, std::shared_ptr<NWebMessage> src)
{
    WVLOG_I("enter ConvertToAniHandlerOfDoubleArr");
    if (!env || !src) {
        WVLOG_E("env is nullptr");
        return nullptr;
    }
    std::vector<double> values = src->GetDoubleArray();
    size_t valueSize = values.size();

    ani_ref undefinedRef = nullptr;
    if (ANI_OK != env->GetUndefined(&undefinedRef)) {
        WVLOG_E("WebMessageExt GetUndefined Failed.");
        return nullptr;
    }

    ani_array array = nullptr;
    if (ANI_OK != env->Array_New(values.size(), undefinedRef, &array)) {
        WVLOG_E("WebMessageExt new array ref error.");
        return array;
    }

    ani_class cls {};
    if (ANI_OK != env->FindClass("std.core.Double", &cls)) {
        WVLOG_E("find double class failed");
        return nullptr;
    }
    ani_method ctor {};
    if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", "d:", &ctor)) {
        return nullptr;
    }

    for (size_t i = 0; i < valueSize; i++) {
        ani_double item = static_cast<ani_double>(values[i]);
        ani_object obj {};
        if (env->Object_New(cls, ctor, &obj, item) != ANI_OK) {
            return nullptr;
        }
        if (ANI_OK != env->Array_Set(array, i, obj)) {
            return array;
        }
    }
    return static_cast<ani_ref>(array);
}

ani_ref ConvertToAniHandlerOfInt64Arr(ani_env* env, std::shared_ptr<NWebMessage> src)
{
    WVLOG_I("enter ConvertToAniHandlerOfInt64Arr");
    if (!env || !src) {
        WVLOG_E("env is nullptr");
        return nullptr;
    }
    std::vector<int64_t> values = src->GetInt64Array();
    size_t valueSize = values.size();

    ani_ref undefinedRef = nullptr;
    if (ANI_OK != env->GetUndefined(&undefinedRef)) {
        WVLOG_E("WebMessageExt GetUndefined Failed.");
        return nullptr;
    }

    ani_array array = nullptr;
    if (ANI_OK != env->Array_New(values.size(), undefinedRef, &array)) {
        WVLOG_E("WebMessageExt new array ref error.");
        return array;
    }

    ani_class cls {};
    if (ANI_OK != env->FindClass("std.core.Long", &cls)) {
        return nullptr;
    }
    ani_method ctor {};
    if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", "l:", &ctor)) {
        return nullptr;
    }

    for (size_t i = 0; i < valueSize; i++) {
        ani_long item = static_cast<ani_long>(values[i]);
        ani_object obj {};
        if (env->Object_New(cls, ctor, &obj, item) != ANI_OK) {
            return nullptr;
        }
        if (ANI_OK != env->Array_Set(array, i, obj)) {
            return array;
        }
    }
    return static_cast<ani_ref>(array);
}

ani_ref AniParseUtils::ConvertNWebToAniValue(ani_env* env, std::shared_ptr<NWebMessage> src)
{
    WVLOG_I("enter ConvertNWebToNapiValue");
    if (!src || !env) {
        WVLOG_E("src of env is nullptr");
        return nullptr;
    }
    NWebValue::Type type = src->GetType();
    using ConvertNWebToAniValueHandler = std::function<ani_ref(ani_env*, std::shared_ptr<NWebMessage>)>;
    static const std::unordered_map<NWebValue::Type, ConvertNWebToAniValueHandler> functionMap = {
        { NWebValue::Type::STRING, ConvertToAniHandlerOfString },
        { NWebValue::Type::BINARY, ConvertToAniHandlerOfBinary },
        { NWebValue::Type::BOOLEAN, ConvertToAniHandlerOfBoolean },
        { NWebValue::Type::INTEGER, ConvertToAniHandlerOfInteger },
        { NWebValue::Type::DOUBLE, ConvertToAniHandlerOfDouble },
        { NWebValue::Type::ERROR, ConvertToAniHandlerOfError },
        { NWebValue::Type::STRINGARRAY, ConvertToAniHandlerOfStringArr },
        { NWebValue::Type::BOOLEANARRAY, ConvertToAniHandlerOfBooleanArr },
        { NWebValue::Type::DOUBLEARRAY, ConvertToAniHandlerOfDoubleArr },
        { NWebValue::Type::INT64ARRAY, ConvertToAniHandlerOfInt64Arr }
    };
    auto it = functionMap.find(type);
    if (it == functionMap.end()) {
        WVLOG_E("This type not support");
        std::string msgStr = "This type not support";
        ani_string dstTemp;
        if (env->String_NewUTF8(msgStr.c_str(), msgStr.size(), &dstTemp) != ANI_OK) {
            WVLOG_E("create object failed");
            return nullptr;
        }
        return static_cast<ani_ref>(dstTemp);
    }
    return it->second(env, src);
}

bool AniParseUtils::ParseArrayBuffer(ani_env* env, ani_object script, std::string& outValue)
{
    if (!env) {
        WVLOG_E("env is nullptr");
        return false;
    }
    ani_boolean isArrayBuffer = false;
    ani_class arrayBufferClass;
    ani_status status;
    if ((status = env->FindClass("std.core.ArrayBuffer", &arrayBufferClass)) != ANI_OK) {
        WVLOG_E("find buffer class error status : %{public}d", status);
        return false;
    }
    if ((env->Object_InstanceOf(script, arrayBufferClass, &isArrayBuffer) != ANI_OK) || !isArrayBuffer) {
        WVLOG_E("Object_InstanceOf error status : %{public}d", status);
        return false;
    }

    char* arrBuf = nullptr;
    size_t byteLength = 0;
    if ((status = env->ArrayBuffer_GetInfo(
        static_cast<ani_arraybuffer>(script), reinterpret_cast<void**>(&arrBuf), &byteLength)) != ANI_OK) {
        WVLOG_E("ArrayBuffer_GetInfo error status : %{public}d", status);
        return false;
    }

    outValue = std::string(arrBuf, byteLength);
    return true;
}

bool AniParseUtils::GetRefProperty(ani_env* env, ani_object param, const char* name, ani_ref& value)
{
    if (env == nullptr) {
        WVLOG_E("null env");
        return false;
    }

    ani_status status;
    ani_boolean isUndefined = true;

    if ((status = env->Object_GetPropertyByName_Ref(param, name, &value)) != ANI_OK) {
        WVLOG_E("status: %{public}d, name : %{public}s", status, name);
        return false;
    }
    if ((status = env->Reference_IsUndefined(value, &isUndefined)) != ANI_OK) {
        WVLOG_E("status: %{public}d, name : %{public}s", status, name);
        return false;
    }
    if (isUndefined) {
        return false;
    }
    return true;
}
}
}