all repos — mgba @ 03c17cdc5637d3609b08caaa2c2c416fee9f9cbc

mGBA Game Boy Advance Emulator

src/third-party/discord-rpc/src/serialization.cpp (view raw)

  1#include "serialization.h"
  2#include "connection.h"
  3#include "discord_rpc.h"
  4
  5template <typename T>
  6void NumberToString(char* dest, T number)
  7{
  8    if (!number) {
  9        *dest++ = '0';
 10        *dest++ = 0;
 11        return;
 12    }
 13    if (number < 0) {
 14        *dest++ = '-';
 15        number = -number;
 16    }
 17    char temp[32];
 18    int place = 0;
 19    while (number) {
 20        auto digit = number % 10;
 21        number = number / 10;
 22        temp[place++] = '0' + (char)digit;
 23    }
 24    for (--place; place >= 0; --place) {
 25        *dest++ = temp[place];
 26    }
 27    *dest = 0;
 28}
 29
 30// it's ever so slightly faster to not have to strlen the key
 31template <typename T>
 32void WriteKey(JsonWriter& w, T& k)
 33{
 34    w.Key(k, sizeof(T) - 1);
 35}
 36
 37struct WriteObject {
 38    JsonWriter& writer;
 39    WriteObject(JsonWriter& w)
 40      : writer(w)
 41    {
 42        writer.StartObject();
 43    }
 44    template <typename T>
 45    WriteObject(JsonWriter& w, T& name)
 46      : writer(w)
 47    {
 48        WriteKey(writer, name);
 49        writer.StartObject();
 50    }
 51    ~WriteObject() { writer.EndObject(); }
 52};
 53
 54struct WriteArray {
 55    JsonWriter& writer;
 56    template <typename T>
 57    WriteArray(JsonWriter& w, T& name)
 58      : writer(w)
 59    {
 60        WriteKey(writer, name);
 61        writer.StartArray();
 62    }
 63    ~WriteArray() { writer.EndArray(); }
 64};
 65
 66template <typename T>
 67void WriteOptionalString(JsonWriter& w, T& k, const char* value)
 68{
 69    if (value && value[0]) {
 70        w.Key(k, sizeof(T) - 1);
 71        w.String(value);
 72    }
 73}
 74
 75static void JsonWriteNonce(JsonWriter& writer, int nonce)
 76{
 77    WriteKey(writer, "nonce");
 78    char nonceBuffer[32];
 79    NumberToString(nonceBuffer, nonce);
 80    writer.String(nonceBuffer);
 81}
 82
 83size_t JsonWriteRichPresenceObj(char* dest,
 84                                size_t maxLen,
 85                                int nonce,
 86                                int pid,
 87                                const DiscordRichPresence* presence)
 88{
 89    JsonWriter writer(dest, maxLen);
 90
 91    {
 92        WriteObject top(writer);
 93
 94        JsonWriteNonce(writer, nonce);
 95
 96        WriteKey(writer, "cmd");
 97        writer.String("SET_ACTIVITY");
 98
 99        {
100            WriteObject args(writer, "args");
101
102            WriteKey(writer, "pid");
103            writer.Int(pid);
104
105            if (presence != nullptr) {
106                WriteObject activity(writer, "activity");
107
108                WriteOptionalString(writer, "state", presence->state);
109                WriteOptionalString(writer, "details", presence->details);
110
111                if (presence->startTimestamp || presence->endTimestamp) {
112                    WriteObject timestamps(writer, "timestamps");
113
114                    if (presence->startTimestamp) {
115                        WriteKey(writer, "start");
116                        writer.Int64(presence->startTimestamp);
117                    }
118
119                    if (presence->endTimestamp) {
120                        WriteKey(writer, "end");
121                        writer.Int64(presence->endTimestamp);
122                    }
123                }
124
125                if ((presence->largeImageKey && presence->largeImageKey[0]) ||
126                    (presence->largeImageText && presence->largeImageText[0]) ||
127                    (presence->smallImageKey && presence->smallImageKey[0]) ||
128                    (presence->smallImageText && presence->smallImageText[0])) {
129                    WriteObject assets(writer, "assets");
130                    WriteOptionalString(writer, "large_image", presence->largeImageKey);
131                    WriteOptionalString(writer, "large_text", presence->largeImageText);
132                    WriteOptionalString(writer, "small_image", presence->smallImageKey);
133                    WriteOptionalString(writer, "small_text", presence->smallImageText);
134                }
135
136                if ((presence->partyId && presence->partyId[0]) || presence->partySize ||
137                    presence->partyMax) {
138                    WriteObject party(writer, "party");
139                    WriteOptionalString(writer, "id", presence->partyId);
140                    if (presence->partySize && presence->partyMax) {
141                        WriteArray size(writer, "size");
142                        writer.Int(presence->partySize);
143                        writer.Int(presence->partyMax);
144                    }
145                }
146
147                if ((presence->matchSecret && presence->matchSecret[0]) ||
148                    (presence->joinSecret && presence->joinSecret[0]) ||
149                    (presence->spectateSecret && presence->spectateSecret[0])) {
150                    WriteObject secrets(writer, "secrets");
151                    WriteOptionalString(writer, "match", presence->matchSecret);
152                    WriteOptionalString(writer, "join", presence->joinSecret);
153                    WriteOptionalString(writer, "spectate", presence->spectateSecret);
154                }
155
156                writer.Key("instance");
157                writer.Bool(presence->instance != 0);
158            }
159        }
160    }
161
162    return writer.Size();
163}
164
165size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId)
166{
167    JsonWriter writer(dest, maxLen);
168
169    {
170        WriteObject obj(writer);
171        WriteKey(writer, "v");
172        writer.Int(version);
173        WriteKey(writer, "client_id");
174        writer.String(applicationId);
175    }
176
177    return writer.Size();
178}
179
180size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
181{
182    JsonWriter writer(dest, maxLen);
183
184    {
185        WriteObject obj(writer);
186
187        JsonWriteNonce(writer, nonce);
188
189        WriteKey(writer, "cmd");
190        writer.String("SUBSCRIBE");
191
192        WriteKey(writer, "evt");
193        writer.String(evtName);
194    }
195
196    return writer.Size();
197}
198
199size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
200{
201    JsonWriter writer(dest, maxLen);
202
203    {
204        WriteObject obj(writer);
205
206        JsonWriteNonce(writer, nonce);
207
208        WriteKey(writer, "cmd");
209        writer.String("UNSUBSCRIBE");
210
211        WriteKey(writer, "evt");
212        writer.String(evtName);
213    }
214
215    return writer.Size();
216}
217
218size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce)
219{
220    JsonWriter writer(dest, maxLen);
221
222    {
223        WriteObject obj(writer);
224
225        WriteKey(writer, "cmd");
226        if (reply == DISCORD_REPLY_YES) {
227            writer.String("SEND_ACTIVITY_JOIN_INVITE");
228        }
229        else {
230            writer.String("CLOSE_ACTIVITY_JOIN_REQUEST");
231        }
232
233        WriteKey(writer, "args");
234        {
235            WriteObject args(writer);
236
237            WriteKey(writer, "user_id");
238            writer.String(userId);
239        }
240
241        JsonWriteNonce(writer, nonce);
242    }
243
244    return writer.Size();
245}