/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * 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 "EnumType.h"

#include <hidl-util/Formatter.h>
#include <inttypes.h>
#include <iostream>
#include <unordered_map>

#include "Annotation.h"
#include "Location.h"
#include "ScalarType.h"

namespace android {

EnumType::EnumType(const char* localName, const FQName& fullName, const Location& location,
                   const Reference<Type>& storageType, Scope* parent)
    : Scope(localName, fullName, location, parent), mValues(), mStorageType(storageType) {}

const Type *EnumType::storageType() const {
    return mStorageType.get();
}

const std::vector<EnumValue *> &EnumType::values() const {
    return mValues;
}

void EnumType::forEachValueFromRoot(const std::function<void(EnumValue*)> f) const {
    std::vector<const EnumType*> chain = typeChain();
    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
        const auto& type = *it;
        for (EnumValue* v : type->values()) {
            f(v);
        }
    }
}

void EnumType::addValue(EnumValue* value) {
    CHECK(value != nullptr);
    mValues.push_back(value);
}

status_t EnumType::resolveInheritance() {
    const EnumType* prevType = nullptr;
    EnumValue* prevValue = nullptr;

    for (const auto* type : superTypeChain()) {
        if (!type->values().empty()) {
            prevType = type;
            prevValue = type->values().back();
            break;
        }
    }

    for (auto* value : mValues) {
        value->autofill(prevType, prevValue, mStorageType->resolveToScalarType());
        prevType = this;
        prevValue = value;
    }

    return Scope::resolveInheritance();
}

std::vector<const Reference<Type>*> EnumType::getReferences() const {
    return {&mStorageType};
}

std::vector<const ConstantExpression*> EnumType::getConstantExpressions() const {
    std::vector<const ConstantExpression*> ret;
    for (const auto* value : mValues) {
        ret.push_back(value->constExpr());
    }
    return ret;
}

status_t EnumType::validate() const {
    CHECK(getSubTypes().empty());

    if (!isElidableType() || !mStorageType->isValidEnumStorageType()) {
        std::cerr << "ERROR: Invalid enum storage type (" << (mStorageType)->typeName()
                  << ") specified at " << mStorageType.location() << "\n";
        return UNKNOWN_ERROR;
    }

    status_t err = validateUniqueNames();
    if (err != OK) return err;

    return Scope::validate();
}

status_t EnumType::validateUniqueNames() const {
    std::unordered_map<std::string, const EnumType*> registeredValueNames;
    for (const auto* type : superTypeChain()) {
        for (const auto* enumValue : type->mValues) {
            // No need to check super value uniqueness
            registeredValueNames[enumValue->name()] = type;
        }
    }

    for (const auto* value : mValues) {
        auto registered = registeredValueNames.find(value->name());

        if (registered != registeredValueNames.end()) {
            const EnumType* definedInType = registered->second;

            if (definedInType == this) {
                // Defined in this enum
                std::cerr << "ERROR: Redefinition of value '" << value->name() << "'";
            } else {
                // Defined in super enum
                std::cerr << "ERROR: Redefinition of value '" << value->name()
                          << "' defined in enum '" << definedInType->fullName() << "'";
            }
            std::cerr << " at " << value->location() << "\n";
            return UNKNOWN_ERROR;
        }

        registeredValueNames[value->name()] = this;
    }

    return OK;
}

bool EnumType::isElidableType() const {
    return mStorageType->isElidableType();
}

const ScalarType *EnumType::resolveToScalarType() const {
    return mStorageType->resolveToScalarType();
}

std::string EnumType::typeName() const {
    return "enum " + localName();
}

bool EnumType::isEnum() const {
    return true;
}

bool EnumType::deepCanCheckEquality(std::unordered_set<const Type*>* /* visited */) const {
    return true;
}

std::string EnumType::getCppType(StorageMode,
                                 bool /* specifyNamespaces */) const {
    return fullName();
}

std::string EnumType::getJavaType(bool forInitializer) const {
    return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
}

std::string EnumType::getJavaSuffix() const {
    return mStorageType->resolveToScalarType()->getJavaSuffix();
}

std::string EnumType::getJavaWrapperType() const {
    return mStorageType->resolveToScalarType()->getJavaWrapperType();
}

std::string EnumType::getVtsType() const {
    return "TYPE_ENUM";
}

std::string EnumType::getBitfieldCppType(StorageMode /* mode */, bool specifyNamespaces) const {
    const std::string space = specifyNamespaces ? "::android::hardware::" : "";
    return space + "hidl_bitfield<" + (specifyNamespaces ? fullName() : localName()) + ">";
}

std::string EnumType::getBitfieldJavaType(bool forInitializer) const {
    return resolveToScalarType()->getJavaType(forInitializer);
}

std::string EnumType::getBitfieldJavaWrapperType() const {
    return resolveToScalarType()->getJavaWrapperType();
}

LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
    std::vector<const EnumType*> chain = typeChain();
    for (auto it = chain.begin(); it != chain.end(); ++it) {
        const auto &type = *it;
        for(EnumValue *v : type->values()) {
            if(v->name() == name) {
                return v;
            }
        }
    }
    return nullptr;
}

void EnumType::emitReaderWriter(
        Formatter &out,
        const std::string &name,
        const std::string &parcelObj,
        bool parcelObjIsPointer,
        bool isReader,
        ErrorMode mode) const {
    const ScalarType *scalarType = mStorageType->resolveToScalarType();
    CHECK(scalarType != NULL);

    scalarType->emitReaderWriterWithCast(
            out,
            name,
            parcelObj,
            parcelObjIsPointer,
            isReader,
            mode,
            true /* needsCast */);
}

void EnumType::emitJavaFieldReaderWriter(
        Formatter &out,
        size_t depth,
        const std::string &parcelName,
        const std::string &blobName,
        const std::string &fieldName,
        const std::string &offset,
        bool isReader) const {
    return mStorageType->emitJavaFieldReaderWriter(
            out, depth, parcelName, blobName, fieldName, offset, isReader);
}

void EnumType::emitTypeDeclarations(Formatter& out) const {
    const ScalarType *scalarType = mStorageType->resolveToScalarType();
    CHECK(scalarType != nullptr);

    const std::string storageType = scalarType->getCppStackType();

    out << "enum class "
        << localName()
        << " : "
        << storageType
        << " {\n";

    out.indent();

    std::vector<const EnumType*> chain = typeChain();

    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
        const auto &type = *it;

        for (const auto &entry : type->values()) {
            entry->emitDocComment(out);

            out << entry->name();

            std::string value = entry->cppValue(scalarType->getKind());
            CHECK(!value.empty()); // use autofilled values for c++.
            out << " = " << value;

            out << ",";

            std::string comment = entry->comment();
            if (!comment.empty()) {
                out << " // " << comment;
            }

            out << "\n";
        }
    }

    out.unindent();
    out << "};\n\n";
}

void EnumType::emitTypeForwardDeclaration(Formatter& out) const {
    const ScalarType* scalarType = mStorageType->resolveToScalarType();
    const std::string storageType = scalarType->getCppStackType();

    out << "enum class " << localName() << " : " << storageType << ";\n";
}

void EnumType::emitIteratorDeclaration(Formatter& out) const {
    size_t elementCount = 0;
    for (const auto* type : typeChain()) {
        elementCount += type->mValues.size();
    }

    out << "template<> struct hidl_enum_iterator<" << getCppStackType() << ">\n";
    out.block([&] {
        out << "const " << getCppStackType() << "* begin() { return static_begin(); }\n";
        out << "const " << getCppStackType() << "* end() { return begin() + " << elementCount
            << "; }\n";
        out << "private:\n";
        out << "static const " << getCppStackType() << "* static_begin() ";
        out.block([&] {
            out << "static const " << getCppStackType() << " kVals[" << elementCount << "] ";
            out.block([&] {
                auto enumerators = typeChain();
                std::reverse(enumerators.begin(), enumerators.end());
                for (const auto* type : enumerators) {
                    for (const auto* enumValue : type->mValues) {
                        out << fullName() << "::" << enumValue->name() << ",\n";
                    }
                }
            }) << ";\n";
            out << "return &kVals[0];\n";
        });
    }) << ";\n\n";
}

void EnumType::emitEnumBitwiseOperator(
        Formatter &out,
        bool lhsIsEnum,
        bool rhsIsEnum,
        const std::string &op) const {
    const ScalarType *scalarType = mStorageType->resolveToScalarType();
    CHECK(scalarType != nullptr);

    const std::string storageType = scalarType->getCppStackType();

    out << "constexpr "
        << storageType
        << " operator"
        << op
        << "(const "
        << (lhsIsEnum ? fullName() : storageType)
        << " lhs, const "
        << (rhsIsEnum ? fullName() : storageType)
        << " rhs) {\n";

    out.indent([&] {
        out << "return static_cast<"
            << storageType
            << ">(";

        if (lhsIsEnum) {
            out << "static_cast<"
                << storageType
                << ">(lhs)";
        } else {
            out << "lhs";
        }
        out << " " << op << " ";
        if (rhsIsEnum) {
            out << "static_cast<"
                << storageType
                << ">(rhs)";
        } else {
            out << "rhs";
        }
        out << ");\n";
    });

    out << "}\n\n";
}

void EnumType::emitBitFieldBitwiseAssignmentOperator(
        Formatter &out,
        const std::string &op) const {
    const ScalarType *scalarType = mStorageType->resolveToScalarType();
    CHECK(scalarType != nullptr);

    const std::string storageType = scalarType->getCppStackType();

    out << "constexpr " << storageType << " &operator" << op << "=("
        << storageType << "& v, const " << fullName() << " e) {\n";

    out.indent([&] {
        out << "v " << op << "= static_cast<" << storageType << ">(e);\n";
        out << "return v;\n";
    });

    out << "}\n\n";
}

void EnumType::emitGlobalTypeDeclarations(Formatter& out) const {
    out << "namespace android {\n";
    out << "namespace hardware {\n";

    emitIteratorDeclaration(out);

    out << "}  // namespace hardware\n";
    out << "}  // namespace android\n";
}

void EnumType::emitPackageTypeDeclarations(Formatter& out) const {
    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
    emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "|");
    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
    emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "&");

    emitBitFieldBitwiseAssignmentOperator(out, "|");
    emitBitFieldBitwiseAssignmentOperator(out, "&");

    const ScalarType *scalarType = mStorageType->resolveToScalarType();
    CHECK(scalarType != NULL);

    out << "template<typename>\n"
        << "static inline std::string toString(" << resolveToScalarType()->getCppArgumentType()
        << " o);\n";
    out << "template<>\n"
        << "inline std::string toString<" << getCppStackType() << ">("
        << scalarType->getCppArgumentType() << " o) ";
    out.block([&] {
        // include toHexString for scalar types
        out << "using ::android::hardware::details::toHexString;\n"
            << "std::string os;\n"
            << getBitfieldCppType(StorageMode_Stack) << " flipped = 0;\n"
            << "bool first = true;\n";
        forEachValueFromRoot([&](EnumValue* value) {
            std::string valueName = fullName() + "::" + value->name();
            out.sIf("(o & " + valueName + ")" +
                    " == static_cast<" + scalarType->getCppStackType() +
                    ">(" + valueName + ")", [&] {
                out << "os += (first ? \"\" : \" | \");\n"
                    << "os += \"" << value->name() << "\";\n"
                    << "first = false;\n"
                    << "flipped |= " << valueName << ";\n";
            }).endl();
        });
        // put remaining bits
        out.sIf("o != flipped", [&] {
            out << "os += (first ? \"\" : \" | \");\n";
            scalarType->emitHexDump(out, "os", "o & (~flipped)");
        });
        out << "os += \" (\";\n";
        scalarType->emitHexDump(out, "os", "o");
        out << "os += \")\";\n";

        out << "return os;\n";
    }).endl().endl();

    out << "static inline std::string toString(" << getCppArgumentType() << " o) ";

    out.block([&] {
        out << "using ::android::hardware::details::toHexString;\n";
        forEachValueFromRoot([&](EnumValue* value) {
            out.sIf("o == " + fullName() + "::" + value->name(), [&] {
                out << "return \"" << value->name() << "\";\n";
            }).endl();
        });
        out << "std::string os;\n";
        scalarType->emitHexDump(out, "os",
            "static_cast<" + scalarType->getCppStackType() + ">(o)");
        out << "return os;\n";
    }).endl().endl();
}

void EnumType::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const {
    const ScalarType *scalarType = mStorageType->resolveToScalarType();
    CHECK(scalarType != NULL);

    out << "public "
        << (atTopLevel ? "" : "static ")
        << "final class "
        << localName()
        << " {\n";

    out.indent();

    const std::string typeName =
        scalarType->getJavaType(false /* forInitializer */);

    std::vector<const EnumType*> chain = typeChain();

    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
        const auto &type = *it;

        for (const auto &entry : type->values()) {
            entry->emitDocComment(out);

            out << "public static final "
                << typeName
                << " "
                << entry->name()
                << " = ";

            // javaValue will make the number signed.
            std::string value = entry->javaValue(scalarType->getKind());
            CHECK(!value.empty()); // use autofilled values for java.
            out << value;

            out << ";";

            std::string comment = entry->comment();
            if (!comment.empty()) {
                out << " // " << comment;
            }

            out << "\n";
        }
    }

    out << "public static final String toString("
        << typeName << " o) ";
    out.block([&] {
        forEachValueFromRoot([&](EnumValue* value) {
            out.sIf("o == " + value->name(), [&] {
                out << "return \"" << value->name() << "\";\n";
            }).endl();
        });
        out << "return \"0x\" + ";
        scalarType->emitConvertToJavaHexString(out, "o");
        out << ";\n";
    }).endl();

    auto bitfieldType = getBitfieldJavaType(false /* forInitializer */);
    auto bitfieldWrapperType = getBitfieldJavaWrapperType();
    out << "\n"
        << "public static final String dumpBitfield("
        << bitfieldType << " o) ";
    out.block([&] {
        out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n";
        out << bitfieldType << " flipped = 0;\n";
        forEachValueFromRoot([&](EnumValue* value) {
            if (value->constExpr()->castSizeT() == 0) {
                out << "list.add(\"" << value->name() << "\"); // " << value->name() << " == 0\n";
                return;  // continue to next value
            }
            out.sIf("(o & " + value->name() + ") == " + value->name(), [&] {
                out << "list.add(\"" << value->name() << "\");\n";
                out << "flipped |= " << value->name() << ";\n";
            }).endl();
        });
        // put remaining bits
        out.sIf("o != flipped", [&] {
            out << "list.add(\"0x\" + ";
            scalarType->emitConvertToJavaHexString(out, "o & (~flipped)");
            out << ");\n";
        }).endl();
        out << "return String.join(\" | \", list);\n";
    }).endl().endl();

    out.unindent();
    out << "};\n\n";
}

void EnumType::emitVtsTypeDeclarations(Formatter& out) const {
    const ScalarType *scalarType = mStorageType->resolveToScalarType();

    out << "name: \"" << fullName() << "\"\n";
    out << "type: " << getVtsType() << "\n";
    out << "enum_value: {\n";
    out.indent();

    out << "scalar_type: \""
        << scalarType->getVtsScalarType()
        << "\"\n\n";
    std::vector<const EnumType*> chain = typeChain();

    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
        const auto &type = *it;

        for (const auto &entry : type->values()) {
            out << "enumerator: \"" << entry->name() << "\"\n";
            out << "scalar_value: {\n";
            out.indent();
            // use autofilled values for vts.
            std::string value = entry->value(scalarType->getKind());
            CHECK(!value.empty());
            out << mStorageType->resolveToScalarType()->getVtsScalarType()
                << ": "
                << value
                << "\n";
            out.unindent();
            out << "}\n";
        }
    }

    out.unindent();
    out << "}\n";
}

void EnumType::emitVtsAttributeType(Formatter& out) const {
    out << "type: " << getVtsType() << "\n";
    out << "predefined_type: \"" << fullName() << "\"\n";
}

void EnumType::emitJavaDump(
        Formatter &out,
        const std::string &streamName,
        const std::string &name) const {
    out << streamName << ".append(" << fqName().javaName() << ".toString("
        << name << "));\n";
}

std::vector<const EnumType*> EnumType::typeChain() const {
    std::vector<const EnumType*> types;
    for (const EnumType* type = this; type != nullptr;) {
        types.push_back(type);

        const Type* superType = type->storageType();
        if (superType != nullptr && superType->isEnum()) {
            type = static_cast<const EnumType*>(superType);
        } else {
            type = nullptr;
        }
    }

    return types;
}

std::vector<const EnumType*> EnumType::superTypeChain() const {
    const Type* superType = storageType();
    if (superType == nullptr || !superType->isEnum()) {
        return {};
    }
    return static_cast<const EnumType*>(superType)->typeChain();
}

void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
    mStorageType->getAlignmentAndSize(align, size);
}

const Annotation *EnumType::findExportAnnotation() const {
    for (const auto &annotation : annotations()) {
        if (annotation->name() == "export") {
            return annotation;
        }
    }

    return nullptr;
}

void EnumType::appendToExportedTypesVector(
        std::vector<const Type *> *exportedTypes) const {
    if (findExportAnnotation() != nullptr) {
        exportedTypes->push_back(this);
    }
}

void EnumType::emitExportedHeader(Formatter& out, bool forJava) const {
    const Annotation *annotation = findExportAnnotation();
    CHECK(annotation != nullptr);

    std::string name = localName();

    const AnnotationParam *nameParam = annotation->getParam("name");
    if (nameParam != nullptr) {
        name = nameParam->getSingleString();
    }

    bool exportParent = true;
    const AnnotationParam *exportParentParam = annotation->getParam("export_parent");
    if (exportParentParam != nullptr) {
        exportParent = exportParentParam->getSingleBool();
    }

    std::string valuePrefix;
    const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
    if (prefixParam != nullptr) {
        valuePrefix = prefixParam->getSingleString();
    }

    std::string valueSuffix;
    const AnnotationParam *suffixParam = annotation->getParam("value_suffix");
    if (suffixParam != nullptr) {
        valueSuffix = suffixParam->getSingleString();
    }

    const ScalarType *scalarType = mStorageType->resolveToScalarType();
    CHECK(scalarType != nullptr);

    std::vector<const EnumType *> chain;
    if (exportParent) {
        chain = typeChain();
    } else {
        chain = { this };
    }

    if (forJava) {
        if (!name.empty()) {
            out << "public final class "
                << name
                << " {\n";

            out.indent();
        } else {
            out << "// Values declared in " << localName() << " follow.\n";
        }

        const std::string typeName =
            scalarType->getJavaType(false /* forInitializer */);

        for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
            const auto &type = *it;

            for (const auto &entry : type->values()) {
                out << "public static final "
                    << typeName
                    << " "
                    << valuePrefix
                    << entry->name()
                    << valueSuffix
                    << " = ";

                // javaValue will make the number signed.
                std::string value = entry->javaValue(scalarType->getKind());
                CHECK(!value.empty()); // use autofilled values for java.
                out << value;

                out << ";";

                std::string comment = entry->comment();
                if (!comment.empty()) {
                    out << " // " << comment;
                }

                out << "\n";
            }
        }

        if (!name.empty()) {
            out.unindent();
            out << "};\n";
        }
        out << "\n";

        return;
    }

    if (!name.empty()) {
        out << "typedef ";
    }

    out << "enum {\n";

    out.indent();

    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
        const auto &type = *it;

        for (const auto &entry : type->values()) {
            out << valuePrefix << entry->name() << valueSuffix;

            std::string value = entry->cppValue(scalarType->getKind());
            CHECK(!value.empty()); // use autofilled values for c++.
            out << " = " << value;

            out << ",";

            std::string comment = entry->comment();
            if (!comment.empty()) {
                out << " // " << comment;
            }

            out << "\n";
        }
    }

    out.unindent();
    out << "}";

    if (!name.empty()) {
        out << " " << name;
    }

    out << ";\n\n";
}

////////////////////////////////////////////////////////////////////////////////

EnumValue::EnumValue(const char* name, ConstantExpression* value, const Location& location)
    : mName(name), mValue(value), mLocation(location), mIsAutoFill(false) {}

std::string EnumValue::name() const {
    return mName;
}

std::string EnumValue::value(ScalarType::Kind castKind) const {
    CHECK(mValue != nullptr);
    return mValue->value(castKind);
}

std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
    CHECK(mValue != nullptr);
    return mValue->cppValue(castKind);
}
std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
    CHECK(mValue != nullptr);
    return mValue->javaValue(castKind);
}

std::string EnumValue::comment() const {
    CHECK(mValue != nullptr);
    if (mValue->descriptionIsTrivial()) return "";
    return mValue->description();
}

ConstantExpression *EnumValue::constExpr() const {
    CHECK(mValue != nullptr);
    return mValue;
}

void EnumValue::autofill(const EnumType* prevType, EnumValue* prevValue, const ScalarType* type) {
    // Value is defined explicitly
    if (mValue != nullptr) return;

    CHECK((prevType == nullptr) == (prevValue == nullptr));

    mIsAutoFill = true;
    if (prevValue == nullptr) {
        mValue = ConstantExpression::Zero(type->getKind()).release();
    } else {
        std::string description = prevType->fullName() + "." + prevValue->name() + " implicitly";
        auto* prevReference = new ReferenceConstantExpression(
            Reference<LocalIdentifier>(prevValue, mLocation), description);
        mValue = prevReference->addOne(type->getKind()).release();
    }
}

bool EnumValue::isAutoFill() const {
    return mIsAutoFill;
}

bool EnumValue::isEnumValue() const {
    return true;
}

const Location& EnumValue::location() const {
    return mLocation;
}

////////////////////////////////////////////////////////////////////////////////

BitFieldType::BitFieldType(Scope* parent) : TemplatedType(parent) {}

bool BitFieldType::isBitField() const {
    return true;
}

const EnumType* BitFieldType::getElementEnumType() const {
    CHECK(mElementType.get() != nullptr && mElementType->isEnum());
    return static_cast<const EnumType*>(mElementType.get());
}

std::string BitFieldType::templatedTypeName() const {
    return "mask";
}

bool BitFieldType::isCompatibleElementType(const Type* elementType) const {
    return elementType->isEnum();
}

const ScalarType *BitFieldType::resolveToScalarType() const {
    return mElementType->resolveToScalarType();
}

std::string BitFieldType::getCppType(StorageMode mode,
                                 bool specifyNamespaces) const {
    return getElementEnumType()->getBitfieldCppType(mode, specifyNamespaces);
}

std::string BitFieldType::getJavaType(bool forInitializer) const {
    return getElementEnumType()->getBitfieldJavaType(forInitializer);
}

std::string BitFieldType::getJavaSuffix() const {
    return resolveToScalarType()->getJavaSuffix();
}

std::string BitFieldType::getJavaWrapperType() const {
    return getElementEnumType()->getBitfieldJavaWrapperType();
}

std::string BitFieldType::getVtsType() const {
    return "TYPE_MASK";
}

bool BitFieldType::isElidableType() const {
    return resolveToScalarType()->isElidableType();
}

bool BitFieldType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const {
    return resolveToScalarType()->canCheckEquality(visited);
}

void BitFieldType::emitVtsAttributeType(Formatter& out) const {
    out << "type: " << getVtsType() << "\n";
    out << "scalar_type: \""
        << mElementType->resolveToScalarType()->getVtsScalarType()
        << "\"\n";
    out << "predefined_type: \"" << static_cast<const NamedType*>(mElementType.get())->fullName()
        << "\"\n";
}

void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const {
    resolveToScalarType()->getAlignmentAndSize(align, size);
}

void BitFieldType::emitReaderWriter(
        Formatter &out,
        const std::string &name,
        const std::string &parcelObj,
        bool parcelObjIsPointer,
        bool isReader,
        ErrorMode mode) const {
    resolveToScalarType()->emitReaderWriterWithCast(
            out,
            name,
            parcelObj,
            parcelObjIsPointer,
            isReader,
            mode,
            true /* needsCast */);
}

const EnumType* BitFieldType::getEnumType() const {
    CHECK(mElementType->isEnum());
    return static_cast<const EnumType*>(mElementType.get());
}

// a bitfield maps to the underlying scalar type in C++, so operator<< is
// already defined. We can still emit useful information if the bitfield is
// in a struct / union by overriding emitDump as below.
void BitFieldType::emitDump(
        Formatter &out,
        const std::string &streamName,
        const std::string &name) const {
    out << streamName << " += "<< getEnumType()->fqName().cppNamespace()
        << "::toString<" << getEnumType()->getCppStackType()
        << ">(" << name << ");\n";
}

void BitFieldType::emitJavaDump(
        Formatter &out,
        const std::string &streamName,
        const std::string &name) const {
    out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield("
        << name << "));\n";
}

void BitFieldType::emitJavaFieldReaderWriter(
        Formatter &out,
        size_t depth,
        const std::string &parcelName,
        const std::string &blobName,
        const std::string &fieldName,
        const std::string &offset,
        bool isReader) const {
    return resolveToScalarType()->emitJavaFieldReaderWriter(
            out, depth, parcelName, blobName, fieldName, offset, isReader);
}

}  // namespace android

