diff --git a/Ical.Net.Tests/EncodingProviderTests.cs b/Ical.Net.Tests/EncodingProviderTests.cs new file mode 100644 index 00000000..f25312c9 --- /dev/null +++ b/Ical.Net.Tests/EncodingProviderTests.cs @@ -0,0 +1,89 @@ +// +// Copyright ical.net project maintainers and contributors. +// Licensed under the MIT license. +// + +#nullable enable +using System; +using Ical.Net.Serialization; +using NUnit.Framework; +using EncodingProvider = Ical.Net.Serialization.EncodingProvider; + +namespace Ical.Net.Tests; + +[TestFixture] +public class EncodingProviderTests +{ + private EncodingProvider GetEncodingProvider() => new EncodingProvider(new SerializationContext()); + + [Test] + public void Encode_ShouldReturnEncodedString_WhenValidEncodingIsProvided() + { + const string encoding = "8BIT"; + var data = "Hello"u8.ToArray(); + + var result = GetEncodingProvider().Encode(encoding, data); + + Assert.That(result, Is.EqualTo("Hello")); + } + + [Test] + public void Encode_ShouldBeNull_WhenInvalidEncodingIsProvided() + { + const string encoding = "Invalid-Encoding"; + var data = "Hello"u8.ToArray(); + + Assert.That(GetEncodingProvider().Encode(encoding, data), Is.Null); + } + + [Test] + public void Decode_ShouldReturnDecodedByteArray_WhenValidEncodingIsProvided() + { + const string encoding = "8BIT"; + const string data = "Hello"; + + var result = GetEncodingProvider().DecodeString(encoding, data); + + Assert.That(result, Is.EqualTo("Hello"u8.ToArray())); + } + + [Test] + public void Decode_ShouldBeNull_WhenInvalidEncodingIsProvided() + { + const string encoding = "Invalid-Encoding"; + const string data = "Hello"; + + Assert.That(GetEncodingProvider().DecodeString(encoding, data), Is.Null); + } + + [Test] + public void Encode_ShouldReturnEncodedString_WithBase64Encoding() + { + const string encoding = "BASE64"; + var data = "Hello"u8.ToArray(); + + var result = GetEncodingProvider().Encode(encoding, data); + + Assert.That(result, Is.EqualTo("SGVsbG8=")); // "Hello" in Base64 + } + + [Test] + public void Decode_ShouldReturnDecodedByteArray_WithBase64Encoding() + { + const string encoding = "BASE64"; + const string data = "SGVsbG8="; // "Hello" in Base64 + + var result = GetEncodingProvider().DecodeString(encoding, data); + + Assert.That(result, Is.EqualTo("Hello"u8.ToArray())); + } + + [Test] + public void Decode_ShouldThrow_WithInvalidBase64String() + { + const string encoding = "BASE64"; + const string data = "InvalidBase64==="; // Invalid Base64 string + + Assert.Throws(() => GetEncodingProvider().DecodeString(encoding, data)); + } +} diff --git a/Ical.Net/Serialization/EncodingProvider.cs b/Ical.Net/Serialization/EncodingProvider.cs index 481940ea..67ab601a 100644 --- a/Ical.Net/Serialization/EncodingProvider.cs +++ b/Ical.Net/Serialization/EncodingProvider.cs @@ -3,179 +3,147 @@ // Licensed under the MIT license. // +#nullable enable using System; using System.Text; namespace Ical.Net.Serialization; +/// +/// Provides encoding and decoding services for byte arrays and strings. +/// internal class EncodingProvider : IEncodingProvider { - public delegate string EncoderDelegate(byte[] data); + private readonly SerializationContext _mSerializationContext; - public delegate byte[] DecoderDelegate(string value); + /// + /// Represents a method that encodes a byte array into a string. + /// + public delegate string? EncoderDelegate(byte[] data); - private readonly SerializationContext _mSerializationContext; + /// + /// Represents a method that decodes a string into a byte array. + /// + public delegate byte[] DecoderDelegate(string value); + /// + /// Creates a new instance of the class. + /// + /// public EncodingProvider(SerializationContext ctx) { _mSerializationContext = ctx; } - protected byte[] Decode7Bit(string value) - { - try - { - var utf7 = new UTF7Encoding(); - return utf7.GetBytes(value); - } - catch - { - return null; - } - } - + /// + /// Decodes an 8-bit string into a byte array. + /// + /// + /// A byte array of the decoded string. protected byte[] Decode8Bit(string value) { - try - { - var utf8 = new UTF8Encoding(); - return utf8.GetBytes(value); - } - catch - { - return null; - } + var utf8 = new UTF8Encoding(); + return utf8.GetBytes(value); } + /// + /// Decodes a base-64 encoded string into a byte array. + /// + /// + /// A byte array of the decoded string. protected byte[] DecodeBase64(string value) { - try - { - return Convert.FromBase64String(value); - } - catch - { - return null; - } + return Convert.FromBase64String(value); } - protected virtual DecoderDelegate GetDecoderFor(string encoding) + /// + /// Gets a decoder for the specified encoding. + /// + /// + /// + protected virtual DecoderDelegate? GetDecoderFor(string encoding) { - if (encoding == null) + return encoding.ToUpper() switch { - return null; - } - - switch (encoding.ToUpper()) - { - case "7BIT": - return Decode7Bit; - case "8BIT": - return Decode8Bit; - case "BASE64": - return DecodeBase64; - default: - return null; - } - } - - protected string Encode7Bit(byte[] data) - { - try - { - var utf7 = new UTF7Encoding(); - return utf7.GetString(data); - } - catch - { - return null; - } + "8BIT" => Decode8Bit, + "BASE64" => DecodeBase64, + _ => null, + }; } + /// + /// Encodes a byte array into an 8-bit string. + /// + /// + /// An 8-bit string, if encoding is successful, else protected string Encode8Bit(byte[] data) { - try - { - var utf8 = new UTF8Encoding(); - return utf8.GetString(data); - } - catch - { - return null; - } + var utf8 = new UTF8Encoding(); + return utf8.GetString(data); } + /// + /// Encodes a byte array into a base-64 encoded string. + /// + /// + /// A base-64 encoded string. protected string EncodeBase64(byte[] data) { - try - { - return Convert.ToBase64String(data); - } - catch - { - return null; - } + return Convert.ToBase64String(data); } - protected virtual EncoderDelegate GetEncoderFor(string encoding) + /// + /// Gets an encoder for the specified encoding. + /// + /// + /// + protected virtual EncoderDelegate? GetEncoderFor(string encoding) { - if (encoding == null) - { - return null; - } - - switch (encoding.ToUpper()) + return encoding.ToUpper() switch { - case "7BIT": - return Encode7Bit; - case "8BIT": - return Encode8Bit; - case "BASE64": - return EncodeBase64; - default: - return null; - } + "8BIT" => Encode8Bit, + "BASE64" => EncodeBase64, + _ => null + }; } - public string Encode(string encoding, byte[] data) + /// + /// Encodes a byte array into a string. + /// + /// + /// + /// A string representation of using the specified , or if encoding fails. + public string? Encode(string encoding, byte[] data) { - if (encoding == null || data == null) - { - return null; - } - var encoder = GetEncoderFor(encoding); - //var wrapped = TextUtil.FoldLines(encoder?.Invoke(data)); - //return wrapped; return encoder?.Invoke(data); } - public string DecodeString(string encoding, string value) + /// + /// Encodes a string into an encoded string by using the service. + /// + /// + /// + /// A string representation of using the specified . + /// Base64 string is invalid. + public string? DecodeString(string encoding, string value) { - if (encoding == null || value == null) - { - return null; - } - var data = DecodeData(encoding, value); - if (data == null) - { - return null; - } // Decode the string into the current encoding var encodingStack = _mSerializationContext.GetService(typeof(EncodingStack)) as EncodingStack; - return encodingStack.Current.GetString(data); + return data != null ? encodingStack?.Current.GetString(data) : null; } - public byte[] DecodeData(string encoding, string value) + /// + /// Decodes an encoded string into a byte array. + /// + /// + /// + /// A string representation of using the specified , or when decoding fails. + public byte[]? DecodeData(string encoding, string value) { - if (encoding == null || value == null) - { - return null; - } - var decoder = GetDecoderFor(encoding); return decoder?.Invoke(value); } -} \ No newline at end of file +}