From 182679c7dfa47e2489c4c8aa0ab2fcc31d8d9676 Mon Sep 17 00:00:00 2001 From: ITR Date: Wed, 26 Feb 2025 14:08:24 +0100 Subject: [PATCH 1/4] Moved model classes for tests into TestModelClasses --- Tomlet.Tests/TestModelClasses/Name.cs | 7 ------- Tomlet.Tests/TestModelClasses/Subname.cs | 6 ++++++ .../{ => TestModelClasses}/TomlTestClassWithEnum.cs | 0 Tomlet.Tests/{ => TestModelClasses}/TomlTestEnum.cs | 0 4 files changed, 6 insertions(+), 7 deletions(-) delete mode 100644 Tomlet.Tests/TestModelClasses/Name.cs create mode 100644 Tomlet.Tests/TestModelClasses/Subname.cs rename Tomlet.Tests/{ => TestModelClasses}/TomlTestClassWithEnum.cs (100%) rename Tomlet.Tests/{ => TestModelClasses}/TomlTestEnum.cs (100%) diff --git a/Tomlet.Tests/TestModelClasses/Name.cs b/Tomlet.Tests/TestModelClasses/Name.cs deleted file mode 100644 index 255a1a1..0000000 --- a/Tomlet.Tests/TestModelClasses/Name.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Tomlet.Tests.TestModelClasses; - -public class Subname -{ - public string a; - public string b; -} \ No newline at end of file diff --git a/Tomlet.Tests/TestModelClasses/Subname.cs b/Tomlet.Tests/TestModelClasses/Subname.cs new file mode 100644 index 0000000..1d84ef3 --- /dev/null +++ b/Tomlet.Tests/TestModelClasses/Subname.cs @@ -0,0 +1,6 @@ +namespace Tomlet.Tests.TestModelClasses; + +public class Subname +{ + public string a; + public string b; } diff --git a/Tomlet.Tests/TomlTestClassWithEnum.cs b/Tomlet.Tests/TestModelClasses/TomlTestClassWithEnum.cs similarity index 100% rename from Tomlet.Tests/TomlTestClassWithEnum.cs rename to Tomlet.Tests/TestModelClasses/TomlTestClassWithEnum.cs diff --git a/Tomlet.Tests/TomlTestEnum.cs b/Tomlet.Tests/TestModelClasses/TomlTestEnum.cs similarity index 100% rename from Tomlet.Tests/TomlTestEnum.cs rename to Tomlet.Tests/TestModelClasses/TomlTestEnum.cs From 790a3dc1dd150558fe3b734e7315cbc4f651c853 Mon Sep 17 00:00:00 2001 From: ITR Date: Wed, 26 Feb 2025 14:08:46 +0100 Subject: [PATCH 2/4] Added more tests for serialization/deserialization of enums. --- Tomlet.Tests/EnumSerializationTests.cs | 22 ---- Tomlet.Tests/EnumTests.cs | 102 ++++++++++++++++++ Tomlet.Tests/TestModelClasses/Subname.cs | 33 ++++-- .../TomlTestClassWithEnumDict.cs | 9 ++ 4 files changed, 138 insertions(+), 28 deletions(-) delete mode 100644 Tomlet.Tests/EnumSerializationTests.cs create mode 100644 Tomlet.Tests/EnumTests.cs create mode 100644 Tomlet.Tests/TestModelClasses/TomlTestClassWithEnumDict.cs diff --git a/Tomlet.Tests/EnumSerializationTests.cs b/Tomlet.Tests/EnumSerializationTests.cs deleted file mode 100644 index c04631d..0000000 --- a/Tomlet.Tests/EnumSerializationTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using Tomlet.Tests.TestModelClasses; -using Xunit; - -namespace Tomlet.Tests; - -public class EnumSerializationTests -{ - [Fact] - public void CanSerializeEnum() - { - var toml = TomletMain.TomlStringFrom(new {EnumValue = TestEnum.Value1}).Trim(); - Assert.Equal("EnumValue = \"Value1\"", toml); - } - - [Fact] - public void SerializingAnUndefinedEnumValueThrows() - { - var testObj = new { EnumValue = (TestEnum)4 }; - Assert.Throws(() => TomletMain.TomlStringFrom(testObj)); - } -} \ No newline at end of file diff --git a/Tomlet.Tests/EnumTests.cs b/Tomlet.Tests/EnumTests.cs new file mode 100644 index 0000000..c8166f7 --- /dev/null +++ b/Tomlet.Tests/EnumTests.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Tomlet.Tests.TestModelClasses; +using Xunit; +using Xunit.Abstractions; + +namespace Tomlet.Tests; + +public class EnumTests +{ + private readonly ITestOutputHelper _testOutputHelper; + + public EnumTests(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper; + } + + [Fact] + public void CanSerializeEnum() + { + var toml = TomletMain.TomlStringFrom(new {EnumValue = TestEnum.Value1}).Trim(); + Assert.Equal("EnumValue = \"Value1\"", toml); + } + + [Fact] + public void SerializingAnUndefinedEnumValueThrows() + { + var testObj = new {EnumValue = (TestEnum)4}; + Assert.Throws(() => TomletMain.TomlStringFrom(testObj)); + } + + [Fact] + public void CanSerializeDictWithEnumValues() + { + var testObj = new Dictionary {{TestEnum.Value1, 1}, {TestEnum.Value2, 2}, {TestEnum.Value3, 3}}; + var toml = TomletMain.TomlStringFrom(testObj); + Assert.Equal("Value1 = 1\nValue2 = 2\nValue3 = 3\n", toml); + } + + [Fact] + public void CanSerializeNonInlinedClass() + { + var testObj = new Dictionary + { + { + TestEnum.Value1, new ClassWithDoNotInlineMembers + { + ShouldNotBeInlinedField = new Dictionary {{"Key", "Value1"}} + } + }, + }; + var toml = TomletMain.TomlStringFrom(testObj); + var expected = "[Value1]\nShouldBeInlined = { }\n[Value1.ShouldNotBeInlinedField]\nKey = \"Value1\"\n\n[Value1.ShouldNotBeInlinedProp]\n\n\n"; + Assert.Equal(expected, toml); + } + + [Fact] + public void CanDeserializeEnumDictionary() + { + var toml = "Value1 = 1\nValue2 = 2\nValue3 = 3\n"; + var result = TomletMain.To>(toml); + var expected = new Dictionary {{TestEnum.Value1, 1}, {TestEnum.Value2, 2}, {TestEnum.Value3, 3}}; + Assert.Equal(expected, result); + } + + [Fact] + public void CanDeserializeEnumDictionaryWithFields() + { + var toml = @" +[Value1] +a = 'A' +b = 'B' +"; + var result = TomletMain.To>(toml); + var expected = new Dictionary + { + {TestEnum.Value1, new Subname {a = "A", b = "B"}}, + }; + + Assert.Equal(expected, result); + } + + [Fact] + public void CanDeserializeEnumDictionaryInClass() + { + var toml = @" +[Subnames] +[Subnames.Value1] +a = 'A' +b = 'B' +"; + var result = TomletMain.To(toml); + var expected = new TomlTestClassWithEnumDict + { + Subnames = new Dictionary {{TestEnum.Value1, new Subname {a = "A", b = "B"}}}, + }; + + Assert.Equal(expected.Subnames, result.Subnames); + } +} \ No newline at end of file diff --git a/Tomlet.Tests/TestModelClasses/Subname.cs b/Tomlet.Tests/TestModelClasses/Subname.cs index 1d84ef3..3d34d78 100644 --- a/Tomlet.Tests/TestModelClasses/Subname.cs +++ b/Tomlet.Tests/TestModelClasses/Subname.cs @@ -1,6 +1,27 @@ -namespace Tomlet.Tests.TestModelClasses; - -public class Subname -{ - public string a; - public string b; } +using System; + +namespace Tomlet.Tests.TestModelClasses; + +public class Subname +{ + public string a; + public string b; + + protected bool Equals(Subname other) + { + return a == other.a && b == other.b; + } + + public override bool Equals(object obj) + { + if (obj is null) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((Subname)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(a, b); + } +} \ No newline at end of file diff --git a/Tomlet.Tests/TestModelClasses/TomlTestClassWithEnumDict.cs b/Tomlet.Tests/TestModelClasses/TomlTestClassWithEnumDict.cs new file mode 100644 index 0000000..c05785b --- /dev/null +++ b/Tomlet.Tests/TestModelClasses/TomlTestClassWithEnumDict.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; +using Tomlet.Tests.TestModelClasses; + +namespace Tomlet.Tests; + +public class TomlTestClassWithEnumDict +{ + public Dictionary Subnames; +} \ No newline at end of file From 8d82855fc4d6be12c59f5512054555ea2b14776a Mon Sep 17 00:00:00 2001 From: ITR Date: Wed, 26 Feb 2025 14:08:57 +0100 Subject: [PATCH 3/4] Fixed PrimitiveKeyedDictionaryDeserializerFor throwing an exception when enums were used as keys. --- Tomlet/TomlSerializationMethods.cs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Tomlet/TomlSerializationMethods.cs b/Tomlet/TomlSerializationMethods.cs index 792d17b..6523856 100644 --- a/Tomlet/TomlSerializationMethods.cs +++ b/Tomlet/TomlSerializationMethods.cs @@ -382,14 +382,32 @@ private static Deserialize> PrimitiveKeyedDictionaryDes #endif { var valueDeserializer = GetDeserializer(typeof(TValue), options); - + var type = typeof(TKey); return value => { if (value is not TomlTable table) throw new TomlTypeMismatchException(typeof(TomlTable), value.GetType(), typeof(Dictionary)); return table.Entries.ToDictionary( - entry => (TKey)(entry.Key as IConvertible).ToType(typeof(TKey), CultureInfo.InvariantCulture), + entry => + { + if (!type.IsEnum) + { + return (TKey)(entry.Key as IConvertible).ToType(typeof(TKey), CultureInfo.InvariantCulture); + } + + try + { + return (TKey)Enum.Parse(type, entry.Key); + } + catch (ArgumentException) + { + if (options.IgnoreInvalidEnumValues) + return (TKey)Enum.GetValues(type).GetValue(0)!; + + throw new TomlEnumParseException(entry.Key, typeof(TKey)); + } + }, entry => (TValue)valueDeserializer(entry.Value) ); }; From a7d9f87859baf6b0cbfe6c7e592a9fe55ce80042 Mon Sep 17 00:00:00 2001 From: ITR Date: Wed, 26 Feb 2025 14:17:24 +0100 Subject: [PATCH 4/4] Made enum parsing ignore capitilization. --- Tomlet/TomlSerializationMethods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tomlet/TomlSerializationMethods.cs b/Tomlet/TomlSerializationMethods.cs index 6523856..d3ac220 100644 --- a/Tomlet/TomlSerializationMethods.cs +++ b/Tomlet/TomlSerializationMethods.cs @@ -398,7 +398,7 @@ private static Deserialize> PrimitiveKeyedDictionaryDes try { - return (TKey)Enum.Parse(type, entry.Key); + return (TKey)Enum.Parse(type, entry.Key, true); } catch (ArgumentException) {