From 950313cc6e1f7adc45a3b8e098e39d52629bd9dd Mon Sep 17 00:00:00 2001 From: NRG-Drink Date: Mon, 19 May 2025 08:30:44 +0200 Subject: [PATCH 1/3] feat: serialize multiple categories to oneline --- Ical.Net.Tests/SymmetricSerializationTests.cs | 2 +- Ical.Net/Serialization/PropertySerializer.cs | 26 ++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Ical.Net.Tests/SymmetricSerializationTests.cs b/Ical.Net.Tests/SymmetricSerializationTests.cs index 9c22082c..45f1aa65 100644 --- a/Ical.Net.Tests/SymmetricSerializationTests.cs +++ b/Ical.Net.Tests/SymmetricSerializationTests.cs @@ -238,7 +238,7 @@ public static IEnumerable UriAttachment_TestCases() yield return new TestCaseData("\\\\uncPath\\to\\resource.txt", new Uri("\\\\uncPath\\to\\resource.txt")).SetName("UNC path URL"); } - [Test, Ignore("TODO: Fix CATEGORIES multiple serializations")] + [Test] public void CategoriesTest() { var vEvent = GetSimpleEvent(); diff --git a/Ical.Net/Serialization/PropertySerializer.cs b/Ical.Net/Serialization/PropertySerializer.cs index 40e5051a..16259b5a 100644 --- a/Ical.Net/Serialization/PropertySerializer.cs +++ b/Ical.Net/Serialization/PropertySerializer.cs @@ -36,15 +36,35 @@ public PropertySerializer(SerializationContext ctx) : base(ctx) { } // the property and parameter values var sf = GetService(); + // TODO: Exhaust this list with all properties which can be displayed in one line. + var stringBuilder = prop.Name switch + { + "CATEGORIES" => ToOneLine(prop, sf), + _ => ToMultipleLines(prop, sf), + }; + + // Pop the object off the serialization context. + SerializationContext.Pop(); + return stringBuilder.ToString(); + } + + private StringBuilder ToOneLine(ICalendarProperty prop, ISerializerFactory sf) + { + var result = new StringBuilder(); + SerializeValue(result, prop, prop.Values.Where(e => e is not null), sf); + + return result; + } + + private StringBuilder ToMultipleLines(ICalendarProperty prop, ISerializerFactory sf) + { var result = new StringBuilder(); foreach (var v in prop.Values.Where(value => value != null)) { SerializeValue(result, prop, v!, sf); } - // Pop the object off the serialization context. - SerializationContext.Pop(); - return result.ToString(); + return result; } private void SerializeValue(StringBuilder result, ICalendarProperty prop, object value, ISerializerFactory sf) From 89ba53b0082049beb4c3811b823235eec60ec5ef Mon Sep 17 00:00:00 2001 From: NRG-Drink Date: Mon, 19 May 2025 10:33:52 +0200 Subject: [PATCH 2/3] test: extend categories test --- Ical.Net.Tests/SymmetricSerializationTests.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Ical.Net.Tests/SymmetricSerializationTests.cs b/Ical.Net.Tests/SymmetricSerializationTests.cs index 45f1aa65..b4ea2b72 100644 --- a/Ical.Net.Tests/SymmetricSerializationTests.cs +++ b/Ical.Net.Tests/SymmetricSerializationTests.cs @@ -238,17 +238,19 @@ public static IEnumerable UriAttachment_TestCases() yield return new TestCaseData("\\\\uncPath\\to\\resource.txt", new Uri("\\\\uncPath\\to\\resource.txt")).SetName("UNC path URL"); } - [Test] - public void CategoriesTest() + [TestCase("Foo", "Bar", "Baz")] + [TestCase("Hello", "World", null)] + public void CategoriesTest(string cat1, string cat2, string cat3) { var vEvent = GetSimpleEvent(); - vEvent.Categories = new List { "Foo", "Bar", "Baz" }; + vEvent.Categories = [cat1, cat2, cat3]; var c = new Calendar(); c.Events.Add(vEvent); var serialized = SerializeToString(c); var categoriesCount = Regex.Matches(serialized, "CATEGORIES").Count; Assert.That(categoriesCount, Is.EqualTo(1)); + Assert.That(serialized, Does.Contain($"CATEGORIES:{string.Join(",", vEvent.Categories)}")); var deserialized = UnserializeCalendar(serialized); Assert.That(deserialized, Is.EqualTo(c)); From e81400df7df6331b325541d821691e624da9f1d6 Mon Sep 17 00:00:00 2001 From: NRG-Drink Date: Mon, 19 May 2025 10:43:13 +0200 Subject: [PATCH 3/3] chore: add serialize RESOURCES to oneline --- Ical.Net.Tests/SymmetricSerializationTests.cs | 18 ++++++++++++++++++ Ical.Net/Serialization/PropertySerializer.cs | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Ical.Net.Tests/SymmetricSerializationTests.cs b/Ical.Net.Tests/SymmetricSerializationTests.cs index b4ea2b72..2a6d2c4f 100644 --- a/Ical.Net.Tests/SymmetricSerializationTests.cs +++ b/Ical.Net.Tests/SymmetricSerializationTests.cs @@ -255,4 +255,22 @@ public void CategoriesTest(string cat1, string cat2, string cat3) var deserialized = UnserializeCalendar(serialized); Assert.That(deserialized, Is.EqualTo(c)); } + + [TestCase("Foo", "Bar", "Baz")] + [TestCase("Hello", "World", null)] + public void ResourceTest(string cat1, string cat2, string cat3) + { + var vEvent = GetSimpleEvent(); + vEvent.Resources = [cat1, cat2, cat3]; + var c = new Calendar(); + c.Events.Add(vEvent); + + var serialized = SerializeToString(c); + var categoriesCount = Regex.Matches(serialized, "RESOURCES").Count; + Assert.That(categoriesCount, Is.EqualTo(1)); + Assert.That(serialized, Does.Contain($"RESOURCES:{string.Join(",", vEvent.Categories)}")); + + var deserialized = UnserializeCalendar(serialized); + Assert.That(deserialized, Is.EqualTo(c)); + } } diff --git a/Ical.Net/Serialization/PropertySerializer.cs b/Ical.Net/Serialization/PropertySerializer.cs index 16259b5a..a085d83d 100644 --- a/Ical.Net/Serialization/PropertySerializer.cs +++ b/Ical.Net/Serialization/PropertySerializer.cs @@ -39,7 +39,7 @@ public PropertySerializer(SerializationContext ctx) : base(ctx) { } // TODO: Exhaust this list with all properties which can be displayed in one line. var stringBuilder = prop.Name switch { - "CATEGORIES" => ToOneLine(prop, sf), + "CATEGORIES" or "RESOURCES" => ToOneLine(prop, sf), _ => ToMultipleLines(prop, sf), };