1/*
2 * Copyright (c) 2021 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 ECMASCRIPT_TOOLING_DISPATCHER_H
17#define ECMASCRIPT_TOOLING_DISPATCHER_H
18
19#include <map>
20#include <memory>
21
22#include "tooling/base/pt_returns.h"
23
24#include "ecmascript/debugger/js_debugger_interface.h"
25#include "ecmascript/napi/include/jsnapi.h"
26#include "libpandabase/macros.h"
27
28namespace panda::ecmascript::tooling {
29class ProtocolChannel;
30class PtBaseReturns;
31class PtBaseEvents;
32
33enum class RequestCode : uint8_t {
34    OK = 0,
35    NOK,
36
37    // Json parse errors
38    JSON_PARSE_ERROR,
39    PARSE_ID_ERROR,
40    ID_FORMAT_ERROR,
41    PARSE_METHOD_ERROR,
42    METHOD_FORMAT_ERROR,
43    PARSE_PARAMS_ERROR,
44    PARAMS_FORMAT_ERROR
45};
46
47enum class ResponseCode : uint8_t { OK, NOK };
48
49class DispatchRequest {
50public:
51    explicit DispatchRequest(const std::string &message);
52    ~DispatchRequest();
53
54    bool IsValid() const
55    {
56        return code_ == RequestCode::OK;
57    }
58    int32_t GetCallId() const
59    {
60        return callId_;
61    }
62    const PtJson &GetParams() const
63    {
64        return *params_;
65    }
66    const std::string &GetDomain() const
67    {
68        return domain_;
69    }
70    const std::string &GetMethod() const
71    {
72        return method_;
73    }
74
75private:
76    int32_t callId_ = -1;
77    std::string domain_ {};
78    std::string method_ {};
79    std::unique_ptr<PtJson> params_ = std::make_unique<PtJson>();
80    RequestCode code_ {RequestCode::OK};
81    std::string errorMsg_ {};
82    void JsonParseError()
83    {
84        code_ = RequestCode::JSON_PARSE_ERROR;
85        LOG_DEBUGGER(ERROR) << "json parse error";
86    }
87    void JsonFormatError(std::unique_ptr<PtJson>& json)
88    {
89        code_ = RequestCode::PARAMS_FORMAT_ERROR;
90        LOG_DEBUGGER(ERROR) << "json parse format error";
91        json->ReleaseRoot();
92    }
93};
94
95class DispatchResponse {
96public:
97    bool IsOk() const
98    {
99        return code_ == ResponseCode::OK;
100    }
101
102    ResponseCode GetError() const
103    {
104        return code_;
105    }
106
107    const std::string &GetMessage() const
108    {
109        return errorMsg_;
110    }
111
112    static DispatchResponse Create(ResponseCode code, const std::string &msg = "");
113    static DispatchResponse Create(std::optional<std::string> error);
114    static DispatchResponse Ok();
115    static DispatchResponse Fail(const std::string &message);
116
117    ~DispatchResponse() = default;
118
119private:
120    DispatchResponse() = default;
121
122    ResponseCode code_ {ResponseCode::OK};
123    std::string errorMsg_ {};
124};
125
126class DispatcherBase {
127public:
128    explicit DispatcherBase(ProtocolChannel *channel) : channel_(channel) {}
129    virtual ~DispatcherBase()
130    {
131        channel_ = nullptr;
132    };
133    virtual void Dispatch(const DispatchRequest &request) = 0;
134
135protected:
136    void SendResponse(const DispatchRequest &request, const DispatchResponse &response,
137                      const PtBaseReturns &result = PtBaseReturns());
138
139private:
140    ProtocolChannel *channel_ {nullptr};
141
142    NO_COPY_SEMANTIC(DispatcherBase);
143    NO_MOVE_SEMANTIC(DispatcherBase);
144};
145
146class Dispatcher {
147public:
148    explicit Dispatcher(const EcmaVM *vm, ProtocolChannel *channel);
149    ~Dispatcher() = default;
150    void Dispatch(const DispatchRequest &request);
151
152private:
153    std::unordered_map<std::string, std::unique_ptr<DispatcherBase>> dispatchers_ {};
154
155    NO_COPY_SEMANTIC(Dispatcher);
156    NO_MOVE_SEMANTIC(Dispatcher);
157};
158}  // namespace panda::ecmascript::tooling
159#endif
160