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 }