1/**
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef ES2PANDA_DYNAMIC_LANGUAGE_H
17#define ES2PANDA_DYNAMIC_LANGUAGE_H
18
19#include <algorithm>
20#include <array>
21#include <optional>
22#include <string_view>
23#include <tuple>
24
25#include "libpandabase/macros.h"
26
27namespace ark::es2panda {
28
29class Language {
30public:
31    enum class Id {
32        AS,
33        JS,
34        TS,
35        ETS,
36        COUNT,
37    };
38
39    constexpr explicit Language(Id id) : id_(id) {}
40
41    constexpr std::string_view ToString() const
42    {
43        for (auto [id, name, _] : ID_TABLE) {
44            if (id_ == id) {
45                return name;
46            }
47        }
48
49        UNREACHABLE();
50    }
51
52    static std::optional<Language> FromString(std::string_view str)
53    {
54        for (auto [id, name, _] : ID_TABLE) {
55            if (str == name) {
56                return Language(id);
57            }
58        }
59
60        return std::nullopt;
61    }
62
63    Id GetId() const
64    {
65        return id_;
66    }
67
68    bool IsDynamic() const
69    {
70        for (auto [id, _, isDynamic] : ID_TABLE) {
71            if (id_ == id) {
72                return isDynamic;
73            }
74        }
75
76        UNREACHABLE();
77    }
78
79    bool operator==(const Language &l) const
80    {
81        return id_ == l.id_;
82    }
83
84    bool operator!=(const Language &l) const
85    {
86        return id_ != l.id_;
87    }
88
89private:
90    static constexpr auto COUNT = static_cast<size_t>(Id::COUNT);
91    static constexpr auto ID_TABLE = {
92        std::tuple {Id::AS, "as", false},
93        {Id::JS, "js", true},
94        {Id::TS, "ts", true},
95        {Id::ETS, "sts", false},
96    };
97
98public:
99    static std::array<Language, COUNT> All()
100    {
101        static_assert(std::size(ID_TABLE) == COUNT);
102
103        std::array<Id, COUNT> arr = {};
104        std::transform(ID_TABLE.begin(), ID_TABLE.end(), arr.begin(), [](const auto &tpl) { return std::get<0>(tpl); });
105
106        return std::apply([](auto... id) { return std::array<Language, COUNT> {Language(id)...}; }, arr);
107    }
108
109private:
110    Id id_;
111};
112
113}  // namespace ark::es2panda
114
115// NOLINTNEXTLINE(cert-dcl58-cpp)
116namespace std {
117
118template <>
119// NOLINTNEXTLINE(altera-struct-pack-align)
120struct hash<ark::es2panda::Language> {
121    std::size_t operator()(ark::es2panda::Language lang) const
122    {
123        return std::hash<ark::es2panda::Language::Id> {}(lang.GetId());
124    }
125};
126
127}  // namespace std
128
129#endif  // ES2PANDA_DYNAMIC_LANGUAGE_H
130