Fix SeString serialization/deserialization (#840)

* chore: add SeString JSON conversion test

* fix: SeString JSON serialization

* chore: add SeString JSON deserialization test

* chore: rename tests to abstract format away

* chore: fix typos

* fix: deserializable SeStrings

* chore: add comment to test

* chore: use DeserializeConfig in Load
This commit is contained in:
karashiiro 2022-05-13 13:07:51 -07:00 committed by GitHub
parent 6dcddb1f29
commit 387a820392
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 104 additions and 14 deletions

View file

@ -0,0 +1,68 @@
using System;
using Dalamud.Configuration;
using Dalamud.Game.Text.SeStringHandling;
using Xunit;
namespace Dalamud.Test.Game.Text.SeStringHandling
{
public class SeStringTests
{
private class MockConfig : IPluginConfiguration, IEquatable<MockConfig>
{
public int Version { get; set; }
public SeString Text { get; init; }
public bool Equals(MockConfig other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Version == other.Version && Equals(Text.TextValue, other.Text.TextValue);
}
public override bool Equals(object obj)
{
return Equals(obj as MockConfig);
}
public override int GetHashCode()
{
return HashCode.Combine(Text);
}
public static bool operator ==(MockConfig left, MockConfig right)
{
return Equals(left, right);
}
public static bool operator !=(MockConfig left, MockConfig right)
{
return !Equals(left, right);
}
}
// Dalamud#779
[Fact]
public void TestConfigSerializable()
{
var builder = new SeStringBuilder();
var seString = builder.AddText("Some text").Build();
var config = new MockConfig { Text = seString };
PluginConfigurations.SerializeConfig(config);
}
[Fact]
public void TestConfigDeserializable()
{
var builder = new SeStringBuilder();
var seString = builder.AddText("Some text").Build();
var config = new MockConfig { Text = seString };
// This relies on the type information being maintained, which is why we're using these
// static methods instead of default serialization/deserialization.
var configSerialized = PluginConfigurations.SerializeConfig(config);
var configDeserialized = (MockConfig)PluginConfigurations.DeserializeConfig(configSerialized);
Assert.Equal(config, configDeserialized);
}
}
}

View file

@ -21,6 +21,36 @@ namespace Dalamud.Configuration
this.configDirectory.Create();
}
/// <summary>
/// Serializes a plugin configuration object.
/// </summary>
/// <param name="config">The configuration object.</param>
/// <returns>A string representing the serialized configuration object.</returns>
internal static string SerializeConfig(object? config)
{
return JsonConvert.SerializeObject(config, Formatting.Indented, new JsonSerializerSettings
{
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
TypeNameHandling = TypeNameHandling.Objects,
});
}
/// <summary>
/// Deserializes a plugin configuration from a string.
/// </summary>
/// <param name="data">The serialized configuration.</param>
/// <returns>The configuration object, or null.</returns>
internal static IPluginConfiguration? DeserializeConfig(string data)
{
return JsonConvert.DeserializeObject<IPluginConfiguration>(
data,
new JsonSerializerSettings
{
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
TypeNameHandling = TypeNameHandling.Objects,
});
}
/// <summary>
/// Save/Load plugin configuration.
/// NOTE: Save/Load are still using Type information for now,
@ -32,11 +62,7 @@ namespace Dalamud.Configuration
/// <param name="pluginName">Plugin name.</param>
public void Save(IPluginConfiguration config, string pluginName)
{
File.WriteAllText(this.GetConfigFile(pluginName).FullName, JsonConvert.SerializeObject(config, Formatting.Indented, new JsonSerializerSettings
{
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
TypeNameHandling = TypeNameHandling.Objects,
}));
File.WriteAllText(this.GetConfigFile(pluginName).FullName, SerializeConfig(config));
}
/// <summary>
@ -51,13 +77,7 @@ namespace Dalamud.Configuration
if (!path.Exists)
return null;
return JsonConvert.DeserializeObject<IPluginConfiguration>(
File.ReadAllText(path.FullName),
new JsonSerializerSettings
{
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
TypeNameHandling = TypeNameHandling.Objects,
});
return DeserializeConfig(File.ReadAllText(path.FullName));
}
/// <summary>

View file

@ -5,6 +5,7 @@ using System.IO;
using Dalamud.Data;
using Dalamud.Game.Text.SeStringHandling.Payloads;
using Newtonsoft.Json;
using Serilog;
// TODOs:
@ -29,6 +30,7 @@ namespace Dalamud.Game.Text.SeStringHandling
/// <summary>
/// Gets the Lumina instance to use for any necessary data lookups.
/// </summary>
[JsonIgnore]
public DataManager DataResolver => Service<DataManager>.Get();
/// <summary>
@ -231,13 +233,13 @@ namespace Dalamud.Game.Text.SeStringHandling
/// <summary>
/// The start byte of a payload.
/// </summary>
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "This is prefered.")]
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "This is preferred.")]
protected const byte START_BYTE = 0x02;
/// <summary>
/// The end byte of a payload.
/// </summary>
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "This is prefered.")]
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "This is preferred.")]
protected const byte END_BYTE = 0x03;
/// <summary>