Skip to content

Commit 6bc4ecc

Browse files
blackspherefollowerqdot
authored andcommitted
Adding MessageVersion support
This updates the JSON schema and C# bindings to match. The JSON parser has been updated too handle message downgrades too.
1 parent 9c1273a commit 6bc4ecc

3 files changed

Lines changed: 380 additions & 9 deletions

File tree

Buttplug.Core/ButtplugJsonMessageParser.cs

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ public ButtplugJsonMessageParser(IButtplugLogManager aLogManager = null)
6363
_schema = JsonSchema4.FromJsonAsync(result).GetAwaiter().GetResult();
6464
}
6565
}
66+
catch (Exception e)
67+
{
68+
_bpLogger.LogException(e);
69+
throw e;
70+
}
6671
finally
6772
{
6873
stream?.Dispose();
@@ -152,25 +157,75 @@ public ButtplugMessage[] Deserialize(string aJsonMsg)
152157
return res.ToArray();
153158
}
154159

155-
public string Serialize([NotNull] ButtplugMessage aMsg)
160+
public string Serialize([NotNull] ButtplugMessage aMsg, uint clientSchemaVersion)
156161
{
157162
// Warning: Any log messages in this function must be localOnly. They will possibly recurse.
158-
var o = new JObject(new JProperty(aMsg.GetType().Name, JObject.FromObject(aMsg)));
163+
164+
// Support downgrading messages
165+
var tmp = aMsg;
166+
while (tmp.MessageVersioningVersion > clientSchemaVersion)
167+
{
168+
if (tmp.MessageVersioningPrevious == null)
169+
{
170+
if (tmp.Id == ButtplugConsts.SystemMsgId)
171+
{
172+
// There's no previous version of this system message
173+
_bpLogger?.Warn($"No messages serialized!");
174+
return null;
175+
}
176+
177+
tmp = new Error($"No backwards compatible version for message #{tmp.GetType().Name}!",
178+
ErrorClass.ERROR_MSG, tmp.Id);
179+
continue;
180+
}
181+
182+
tmp = (ButtplugMessage)aMsg.MessageVersioningPrevious.GetConstructor(
183+
new Type[] { tmp.GetType() }).Invoke(new object[] { tmp });
184+
}
185+
186+
var o = new JObject(new JProperty(aMsg.GetType().Name, JObject.FromObject(tmp)));
159187
var a = new JArray(o);
160188
_bpLogger?.Trace($"Message serialized to: {a.ToString(Formatting.None)}", true);
161189
return a.ToString(Formatting.None);
162190
}
163191

164-
public string Serialize([NotNull] IEnumerable<ButtplugMessage> aMsgs)
192+
public string Serialize([NotNull] IEnumerable<ButtplugMessage> aMsgs, uint clientSchemaVersion)
165193
{
166194
// Warning: Any log messages in this function must be localOnly. They will possibly recurse.
167195
var a = new JArray();
168196
foreach (var msg in aMsgs)
169197
{
170-
var o = new JObject(new JProperty(msg.GetType().Name, JObject.FromObject(msg)));
198+
// Support downgrading messages
199+
var tmp = msg;
200+
while (tmp.MessageVersioningVersion > clientSchemaVersion)
201+
{
202+
if (tmp.MessageVersioningPrevious == null)
203+
{
204+
if (tmp.Id == ButtplugConsts.SystemMsgId)
205+
{
206+
// There's no previous version of this system message
207+
continue;
208+
}
209+
210+
tmp = new Error($"No backwards compatible version for message #{tmp.GetType().Name}!",
211+
ErrorClass.ERROR_MSG, tmp.Id);
212+
continue;
213+
}
214+
215+
tmp = (ButtplugMessage)tmp.MessageVersioningPrevious.GetConstructor(
216+
new Type[] { tmp.GetType() }).Invoke(new object[] { tmp });
217+
}
218+
219+
var o = new JObject(new JProperty(msg.GetType().Name, JObject.FromObject(tmp)));
171220
a.Add(o);
172221
}
173222

223+
if (!a.Any())
224+
{
225+
_bpLogger?.Warn($"No messages serialized!");
226+
return null;
227+
}
228+
174229
_bpLogger?.Trace($"Message serialized to: {a.ToString(Formatting.None)}", true);
175230
return a.ToString(Formatting.None);
176231
}

Buttplug.Core/ButtplugMessage.cs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,65 @@
1-
using Newtonsoft.Json;
1+
using System;
2+
using Newtonsoft.Json;
23

34
namespace Buttplug.Core
45
{
56
public class ButtplugMessage
67
{
8+
/*
9+
* Message versions
10+
*
11+
* These are here for backwards compatibility support, but
12+
* this also serves as a changelog of sorts.
13+
*
14+
* Version 0 - Originally Schema 0.1.0
15+
* First release with no backwards compatibility
16+
*
17+
* Version 1 - Introduction of MessageVersioning
18+
* Addition of generic commands VibrateCmd/RotateCmd/LinearCmd
19+
* Addition of message attributes
20+
*/
21+
[JsonIgnore]
22+
public const uint CurrentMessageVersion = 1;
23+
724
[JsonProperty(Required = Required.Always)]
825
public uint Id { get; set; }
926

27+
[JsonIgnore]
28+
public uint MessageVersioningVersion
29+
{
30+
get
31+
{
32+
return _messageVersioningVersion;
33+
}
34+
35+
protected set
36+
{
37+
_messageVersioningVersion = value;
38+
}
39+
}
40+
41+
[JsonIgnore]
42+
public Type MessageVersioningPrevious
43+
{
44+
get
45+
{
46+
return _messageVersioningPrevious;
47+
}
48+
49+
protected set
50+
{
51+
_messageVersioningPrevious = value;
52+
}
53+
}
54+
55+
// Base class starts at version 0
56+
[JsonIgnore]
57+
private uint _messageVersioningVersion = 0;
58+
59+
// No previous version for base classes
60+
[JsonIgnore]
61+
private Type _messageVersioningPrevious = null;
62+
1063
public ButtplugMessage(uint aId)
1164
{
1265
Id = aId;

0 commit comments

Comments
 (0)