summaryrefslogtreecommitdiff
path: root/include/SSVOpenHexagon/Utils/LuaMetadataProxy.hpp
blob: 792541aebd0e4b5054f821d6c41f293ff29e2b35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright (c) 2013-2020 Vittorio Romeo
// License: Academic Free License ("AFL") v. 3.0
// AFL License page: https://opensource.org/licenses/AFL-3.0

#pragma once

#include "SSVOpenHexagon/Utils/ArgExtractor.hpp"
#include "SSVOpenHexagon/Utils/TypeWrapper.hpp"

#include <string>
#include <vector>
#include <utility>
#include <type_traits>
#include <tuple>
#include <cstddef>

namespace hg::Utils {

class LuaMetadata;

class LuaMetadataProxy
{
private:
    LuaMetadata& luaMetadata;
    std::string name;
    std::string (*erasedRet)(LuaMetadataProxy*);
    std::string (*erasedArgs)(LuaMetadataProxy*);
    std::string docs;
    std::vector<std::string> argNames;

    template <typename T>
    [[nodiscard]] static const char* typeToStr(TypeWrapper<T>) noexcept;

    template <typename... Ts>
    [[nodiscard]] static std::string typeToStr(TypeWrapper<std::tuple<Ts...>>);

    template <typename FOp>
    [[nodiscard]] static std::string makeArgsString(LuaMetadataProxy* self)
    {
        using AE = Utils::ArgExtractor<FOp>;

        if constexpr(AE::numArgs == 0)
        {
            return "";
        }
        else if constexpr(AE::numArgs == 1)
        {
            std::string res;

            res += typeToStr(
                TypeWrapper<std::decay_t<typename AE::template NthArg<0>>>{});

            res += ' ';
            res += self->argNames.at(0);

            return res;
        }
        else
        {
            std::string res;

            [&]<std::size_t... Is>(std::index_sequence<Is...>)
            {
                (( //
                     res += typeToStr(TypeWrapper<
                         std::decay_t<typename AE::template NthArg<Is>>>{}), //
                     res += ' ',                                             //
                     res += self->argNames.at(Is),                           //
                     res += ", "),
                    ...);
            }
            (std::make_index_sequence<AE::numArgs>{});

            res.pop_back();
            res.pop_back();

            return res;
        }
    }

    [[nodiscard]] std::string resolveArgNames(const std::string& docs);

    template <typename Ret>
    [[nodiscard]] static std::string makeErasedRet(LuaMetadataProxy*)
    {
        return typeToStr(TypeWrapper<std::decay_t<Ret>>{});
    }

public:
    template <typename F, typename FOp = decltype(&std::decay_t<F>::operator())>
    explicit LuaMetadataProxy(
        TypeWrapper<F>, LuaMetadata& mLuaMetadata, const std::string& mName)
        : luaMetadata{mLuaMetadata},
          name{mName},
          erasedRet{&makeErasedRet<typename Utils::ArgExtractor<FOp>::Return>},
          erasedArgs{&makeArgsString<FOp>}
    {}

    ~LuaMetadataProxy();

    LuaMetadataProxy& arg(const std::string& mArgName);
    LuaMetadataProxy& doc(const std::string& mDocs);
};

} // namespace hg::Utils