/ src / serialization.cpp
serialization.cpp
  1  #include "serialization.h"
  2  #include "connection.h"
  3  #include "discord_rpc.h"
  4  
  5  template <typename T>
  6  void 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
 31  template <typename T>
 32  void WriteKey(JsonWriter& w, T& k)
 33  {
 34      w.Key(k, sizeof(T) - 1);
 35  }
 36  
 37  struct 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  
 54  struct 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  
 66  template <typename T>
 67  void 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  
 75  static 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  
 83  size_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 || presence->partyPrivacy) {
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                      if (presence->partyPrivacy) {
147                          WriteKey(writer, "privacy");
148                          writer.Int(presence->partyPrivacy);
149                      }
150                  }
151  
152                  if ((presence->matchSecret && presence->matchSecret[0]) ||
153                      (presence->joinSecret && presence->joinSecret[0]) ||
154                      (presence->spectateSecret && presence->spectateSecret[0])) {
155                      WriteObject secrets(writer, "secrets");
156                      WriteOptionalString(writer, "match", presence->matchSecret);
157                      WriteOptionalString(writer, "join", presence->joinSecret);
158                      WriteOptionalString(writer, "spectate", presence->spectateSecret);
159                  }
160  
161                  writer.Key("instance");
162                  writer.Bool(presence->instance != 0);
163              }
164          }
165      }
166  
167      return writer.Size();
168  }
169  
170  size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId)
171  {
172      JsonWriter writer(dest, maxLen);
173  
174      {
175          WriteObject obj(writer);
176          WriteKey(writer, "v");
177          writer.Int(version);
178          WriteKey(writer, "client_id");
179          writer.String(applicationId);
180      }
181  
182      return writer.Size();
183  }
184  
185  size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
186  {
187      JsonWriter writer(dest, maxLen);
188  
189      {
190          WriteObject obj(writer);
191  
192          JsonWriteNonce(writer, nonce);
193  
194          WriteKey(writer, "cmd");
195          writer.String("SUBSCRIBE");
196  
197          WriteKey(writer, "evt");
198          writer.String(evtName);
199      }
200  
201      return writer.Size();
202  }
203  
204  size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
205  {
206      JsonWriter writer(dest, maxLen);
207  
208      {
209          WriteObject obj(writer);
210  
211          JsonWriteNonce(writer, nonce);
212  
213          WriteKey(writer, "cmd");
214          writer.String("UNSUBSCRIBE");
215  
216          WriteKey(writer, "evt");
217          writer.String(evtName);
218      }
219  
220      return writer.Size();
221  }
222  
223  size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce)
224  {
225      JsonWriter writer(dest, maxLen);
226  
227      {
228          WriteObject obj(writer);
229  
230          WriteKey(writer, "cmd");
231          if (reply == DISCORD_REPLY_YES) {
232              writer.String("SEND_ACTIVITY_JOIN_INVITE");
233          }
234          else {
235              writer.String("CLOSE_ACTIVITY_JOIN_REQUEST");
236          }
237  
238          WriteKey(writer, "args");
239          {
240              WriteObject args(writer);
241  
242              WriteKey(writer, "user_id");
243              writer.String(userId);
244          }
245  
246          JsonWriteNonce(writer, nonce);
247      }
248  
249      return writer.Size();
250  }