diff --git a/src/Addax.Formats.Tabular.Analyzers.CSharp.UnitTests/Assets/TypeMemberHasSupportedType.cs b/src/Addax.Formats.Tabular.Analyzers.CSharp.UnitTests/Assets/TypeMemberHasSupportedType.cs index 53acb3c..d9f7f83 100644 --- a/src/Addax.Formats.Tabular.Analyzers.CSharp.UnitTests/Assets/TypeMemberHasSupportedType.cs +++ b/src/Addax.Formats.Tabular.Analyzers.CSharp.UnitTests/Assets/TypeMemberHasSupportedType.cs @@ -1,5 +1,6 @@ using System; using System.Numerics; +using System.Text; using Addax.Formats.Tabular; namespace MyNamespace; @@ -81,4 +82,7 @@ public struct MyType [TabularFieldOrder(24)] public Uri? MyValue24; + + [TabularFieldOrder(25)] + public Rune MyValue25; } diff --git a/src/Addax.Formats.Tabular.Analyzers.CSharp.UnitTests/Assets/TypeMemberHasSupportedTypeAsNullableT.cs b/src/Addax.Formats.Tabular.Analyzers.CSharp.UnitTests/Assets/TypeMemberHasSupportedTypeAsNullableT.cs index bfbb93c..6608dd9 100644 --- a/src/Addax.Formats.Tabular.Analyzers.CSharp.UnitTests/Assets/TypeMemberHasSupportedTypeAsNullableT.cs +++ b/src/Addax.Formats.Tabular.Analyzers.CSharp.UnitTests/Assets/TypeMemberHasSupportedTypeAsNullableT.cs @@ -1,5 +1,6 @@ using System; using System.Numerics; +using System.Text; using Addax.Formats.Tabular; namespace MyNamespace; @@ -81,4 +82,7 @@ public struct MyType [TabularFieldOrder(24)] public Uri? MyValue24; + + [TabularFieldOrder(25)] + public Rune? MyValue25; } diff --git a/src/Addax.Formats.Tabular.Analyzers.CSharp/TabularHandlerEmitter.cs b/src/Addax.Formats.Tabular.Analyzers.CSharp/TabularHandlerEmitter.cs index 1db72c2..1e55120 100644 --- a/src/Addax.Formats.Tabular.Analyzers.CSharp/TabularHandlerEmitter.cs +++ b/src/Addax.Formats.Tabular.Analyzers.CSharp/TabularHandlerEmitter.cs @@ -223,6 +223,10 @@ private static string GetValueTypeCode(string valueTypeName) { return "BigInteger"; } + case "global::System.Text.Rune": + { + return "Rune"; + } default: { throw new NotSupportedException(); diff --git a/src/Addax.Formats.Tabular.Analyzers.CSharp/TabularHandlerParser.cs b/src/Addax.Formats.Tabular.Analyzers.CSharp/TabularHandlerParser.cs index dde406d..8b062ab 100644 --- a/src/Addax.Formats.Tabular.Analyzers.CSharp/TabularHandlerParser.cs +++ b/src/Addax.Formats.Tabular.Analyzers.CSharp/TabularHandlerParser.cs @@ -415,7 +415,8 @@ private static (ITypeSymbol Type, string Name, bool IsSupported, bool IsNullable (valueTypeName == "global::System.TimeSpan") || (valueTypeName == "global::System.UInt128") || (valueTypeName == "global::System.Uri") || - (valueTypeName == "global::System.Numerics.BigInteger"); + (valueTypeName == "global::System.Numerics.BigInteger") || + (valueTypeName == "global::System.Text.Rune"); } break; } diff --git a/src/Addax.Formats.Tabular.UnitTests/TabularReaderTests.T.cs b/src/Addax.Formats.Tabular.UnitTests/TabularReaderTests.T.cs index 345a1ea..7d177bd 100644 --- a/src/Addax.Formats.Tabular.UnitTests/TabularReaderTests.T.cs +++ b/src/Addax.Formats.Tabular.UnitTests/TabularReaderTests.T.cs @@ -13,10 +13,9 @@ public partial class TabularReaderTests private static void TryGet(Func> selector, string content, T? expected) { var dialect = new TabularDialect("\u000a", '\u000b', '\u000c', '\u000d'); - var options = new TabularOptions { Encoding = Encoding.ASCII }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); - using var reader = new TabularReader(stream, dialect, options); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); + using var reader = new TabularReader(stream, dialect); var method = selector.Invoke(reader); @@ -37,10 +36,9 @@ private static void TryGet(Func> selector, strin private static void Get(Func> selector, string content, T? expected) { var dialect = new TabularDialect("\u000a", '\u000b', '\u000c', '\u000d'); - var options = new TabularOptions { Encoding = Encoding.ASCII }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); - using var reader = new TabularReader(stream, dialect, options); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); + using var reader = new TabularReader(stream, dialect); var method = selector.Invoke(reader); @@ -336,6 +334,14 @@ public void TryGetBase64Binary(string content, string expected) TryGet(x => x.TryGetBase64Binary, content, Convert.FromBase64String(expected)); } + [TestMethod] + [DataRow("v", "v")] + [DataRow("\ud83d\udd2e", "\ud83d\udd2e")] + public void TryGetRune(string content, string expected) + { + TryGet(x => x.TryGetRune, content, Rune.GetRuneAt(expected, 0)); + } + [TestMethod] [DataRow("", "")] [DataRow(" v ", " v ")] @@ -613,4 +619,12 @@ public void GetBase64Binary(string content, string expected) { Get(x => x.GetBase64Binary, content, Convert.FromBase64String(expected)); } + + [TestMethod] + [DataRow("v", "v")] + [DataRow("\ud83d\udd2e", "\ud83d\udd2e")] + public void GetRune(string content, string expected) + { + Get(x => x.GetRune, content, Rune.GetRuneAt(expected, 0)); + } } diff --git a/src/Addax.Formats.Tabular.UnitTests/TabularReaderTests.cs b/src/Addax.Formats.Tabular.UnitTests/TabularReaderTests.cs index 49466b5..fcc0bb1 100644 --- a/src/Addax.Formats.Tabular.UnitTests/TabularReaderTests.cs +++ b/src/Addax.Formats.Tabular.UnitTests/TabularReaderTests.cs @@ -126,9 +126,9 @@ public sealed partial class TabularReaderTests public void ConsumePositive(string dialectScript, string content, string structureScript) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); var structureBuilder = new StringBuilder(); @@ -227,9 +227,9 @@ public void ConsumePositive(string dialectScript, string content, string structu public void ConsumeNegative(string dialectScript, string content) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); Assert.ThrowsException(() => ReadStream(reader)); @@ -253,9 +253,9 @@ static void ReadStream(TabularReader reader) public void TryPickRecordIfStreamStart(string dialectScript, string content, bool expected) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); Assert.AreEqual(expected, reader.TryPickRecord()); @@ -269,9 +269,9 @@ public void TryPickRecordIfStreamStart(string dialectScript, string content, boo public void TryPickRecordIfRecordStart(string dialectScript, string content, bool expected) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); reader.TryPickRecord(); @@ -287,9 +287,9 @@ public void TryPickRecordIfRecordStart(string dialectScript, string content, boo public void TryPickRecordIfDelimiter(string dialectScript, string content, bool expected) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); reader.TryReadField(); @@ -305,9 +305,9 @@ public void TryPickRecordIfDelimiter(string dialectScript, string content, bool public void TryPickRecordIfRecordEnd(string dialectScript, string content, bool expected) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); reader.TryReadField(); @@ -323,9 +323,9 @@ public void TryPickRecordIfRecordEnd(string dialectScript, string content, bool public void TryPickRecordIfStreamEnd(string dialectScript, string content, bool expected) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); reader.TryReadField(); @@ -341,9 +341,9 @@ public void TryPickRecordIfStreamEnd(string dialectScript, string content, bool public void TryReadFieldIfStreamStart(string dialectScript, string content, bool expected) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); Assert.AreEqual(expected, reader.TryReadField()); @@ -357,9 +357,9 @@ public void TryReadFieldIfStreamStart(string dialectScript, string content, bool public void TryReadFieldIfRecordStart(string dialectScript, string content, bool expected) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); reader.TryPickRecord(); @@ -375,9 +375,9 @@ public void TryReadFieldIfRecordStart(string dialectScript, string content, bool public void TryReadFieldIfDelimiter(string dialectScript, string content, bool expected) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); reader.TryReadField(); @@ -393,9 +393,9 @@ public void TryReadFieldIfDelimiter(string dialectScript, string content, bool e public void TryReadFieldIfRecordEnd(string dialectScript, string content, bool expected) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); reader.TryReadField(); @@ -411,9 +411,9 @@ public void TryReadFieldIfRecordEnd(string dialectScript, string content, bool e public void TryReadFieldIfStreamEnd(string dialectScript, string content, bool expected) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); reader.TryReadField(); @@ -429,9 +429,9 @@ public void TryReadFieldIfStreamEnd(string dialectScript, string content, bool e public void TrySkipFieldIfStreamStart(string dialectScript, string content, bool expected) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); Assert.AreEqual(expected, reader.TrySkipField()); @@ -445,9 +445,9 @@ public void TrySkipFieldIfStreamStart(string dialectScript, string content, bool public void TrySkipFieldIfRecordStart(string dialectScript, string content, bool expected) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); reader.TryPickRecord(); @@ -463,9 +463,9 @@ public void TrySkipFieldIfRecordStart(string dialectScript, string content, bool public void TrySkipFieldIfDelimiter(string dialectScript, string content, bool expected) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); reader.TryReadField(); @@ -481,9 +481,9 @@ public void TrySkipFieldIfDelimiter(string dialectScript, string content, bool e public void TrySkipFieldIfRecordEnd(string dialectScript, string content, bool expected) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); reader.TryReadField(); @@ -499,9 +499,9 @@ public void TrySkipFieldIfRecordEnd(string dialectScript, string content, bool e public void TrySkipFieldIfStreamEnd(string dialectScript, string content, bool expected) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); reader.TryReadField(); @@ -521,9 +521,9 @@ public void TrySkipFieldIfStreamEnd(string dialectScript, string content, bool e public void TryReadRecord(string dialectScript, string content) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(content)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); using var reader = new TabularReader(stream, dialect, options); Assert.IsTrue(reader.TrySkipRecord()); diff --git a/src/Addax.Formats.Tabular.UnitTests/TabularWriterTests.T.cs b/src/Addax.Formats.Tabular.UnitTests/TabularWriterTests.T.cs index bddbf5e..6536872 100644 --- a/src/Addax.Formats.Tabular.UnitTests/TabularWriterTests.T.cs +++ b/src/Addax.Formats.Tabular.UnitTests/TabularWriterTests.T.cs @@ -12,17 +12,16 @@ public partial class TabularWriterTests private static void Write(Func> selector, T value, string expected) { var dialect = new TabularDialect("\u000a", '\u000b', '\u000c', '\u000d'); - var options = new TabularOptions { Encoding = Encoding.ASCII }; using var stream = new MemoryStream(); - using var writer = new TabularWriter(stream, dialect, options); + using var writer = new TabularWriter(stream, dialect); var method = selector.Invoke(writer); method.Invoke(value); writer.Flush(); - Assert.AreEqual(expected, Encoding.ASCII.GetString(stream.ToArray())); + Assert.AreEqual(expected, Encoding.UTF8.GetString(stream.ToArray())); } [TestMethod] @@ -265,6 +264,14 @@ public void WriteGuid(string value, string expected) Write(x => x.WriteGuid, Guid.Parse(value, CultureInfo.InvariantCulture), expected); } + [TestMethod] + [DataRow("urn:com.example", "urn:com.example")] + [DataRow("https://example.com/", "https://example.com/")] + public void WriteUri(string value, string expected) + { + Write(x => x.WriteUri, new Uri(value, UriKind.RelativeOrAbsolute), expected); + } + [TestMethod] [DataRow("", "")] [DataRow("123e4567e89b12d3a456426614174000", "123e4567e89b12d3a456426614174000")] @@ -282,10 +289,10 @@ public void WriteBase64Binary(string value, string expected) } [TestMethod] - [DataRow("urn:com.example", "urn:com.example")] - [DataRow("https://example.com/", "https://example.com/")] - public void WriteUri(string value, string expected) + [DataRow("v", "v")] + [DataRow("\ud83d\udd2e", "\ud83d\udd2e")] + public void WriteRune(string value, string expected) { - Write(x => x.WriteUri, new Uri(value, UriKind.RelativeOrAbsolute), expected); + Write(x => x.WriteRune, Rune.GetRuneAt(value, 0), expected); } } diff --git a/src/Addax.Formats.Tabular.UnitTests/TabularWriterTests.cs b/src/Addax.Formats.Tabular.UnitTests/TabularWriterTests.cs index 35b08c2..ce55910 100644 --- a/src/Addax.Formats.Tabular.UnitTests/TabularWriterTests.cs +++ b/src/Addax.Formats.Tabular.UnitTests/TabularWriterTests.cs @@ -142,7 +142,7 @@ public sealed partial class TabularWriterTests public void CommitStringPositive(string dialectScript, string structureScript, string content) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; using var stream = new MemoryStream(); using var writer = new TabularWriter(stream, dialect, options); @@ -159,7 +159,7 @@ public void CommitStringPositive(string dialectScript, string structureScript, s writer.Flush(); - Assert.AreEqual(content, Encoding.ASCII.GetString(stream.ToArray())); + Assert.AreEqual(content, Encoding.UTF8.GetString(stream.ToArray())); } [TestMethod] @@ -186,7 +186,7 @@ public void CommitStringPositive(string dialectScript, string structureScript, s public void CommitAnnotationPositive(string dialectScript, string structureScript, string content) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; using var stream = new MemoryStream(); using var writer = new TabularWriter(stream, dialect, options); @@ -210,7 +210,7 @@ public void CommitAnnotationPositive(string dialectScript, string structureScrip writer.Flush(); - Assert.AreEqual(content, Encoding.ASCII.GetString(stream.ToArray())); + Assert.AreEqual(content, Encoding.UTF8.GetString(stream.ToArray())); } [TestMethod] @@ -225,7 +225,7 @@ public void CommitAnnotationPositive(string dialectScript, string structureScrip public void CommitAnnotationNegative(string dialectScript, string structureScript) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; using var stream = new MemoryStream(); using var writer = new TabularWriter(stream, dialect, options); @@ -270,7 +270,7 @@ static void WriteStream(TabularWriter writer, string structureScript) public void WriteEmpty(string dialectScript, string content) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; using var stream = new MemoryStream(); using var writer = new TabularWriter(stream, dialect, options); @@ -278,7 +278,7 @@ public void WriteEmpty(string dialectScript, string content) writer.WriteEmpty(); writer.Flush(); - Assert.AreEqual(content, Encoding.ASCII.GetString(stream.ToArray())); + Assert.AreEqual(content, Encoding.UTF8.GetString(stream.ToArray())); } [TestMethod] @@ -293,7 +293,7 @@ public void WriteEmpty(string dialectScript, string content) public void WriteRecord(string dialectScript, string structureScript, string content) { var dialect = CreateDialect(dialectScript); - var options = new TabularOptions { Encoding = Encoding.ASCII, BufferSize = 1 }; + var options = new TabularOptions { BufferSize = 1 }; using var stream = new MemoryStream(); using var writer = new TabularWriter(stream, dialect, options); @@ -305,7 +305,7 @@ public void WriteRecord(string dialectScript, string structureScript, string con writer.Flush(); - Assert.AreEqual(content, Encoding.ASCII.GetString(stream.ToArray())); + Assert.AreEqual(content, Encoding.UTF8.GetString(stream.ToArray())); } private static TabularDialect CreateDialect(string script) diff --git a/src/Addax.Formats.Tabular/Converters/TabularRuneConverter.cs b/src/Addax.Formats.Tabular/Converters/TabularRuneConverter.cs new file mode 100644 index 0000000..00ca0f8 --- /dev/null +++ b/src/Addax.Formats.Tabular/Converters/TabularRuneConverter.cs @@ -0,0 +1,39 @@ +// (c) Oleksandr Kozlenko. Licensed under the MIT license. + +using System.Text; + +namespace Addax.Formats.Tabular.Converters; + +/// Converts a value from or to a character sequence. +public class TabularRuneConverter : TabularConverter +{ + internal static readonly TabularRuneConverter Instance = new(); + + /// Initializes a new instance of the class. + public TabularRuneConverter() + { + } + + /// + public override bool TryFormat(Rune value, Span destination, IFormatProvider? provider, out int charsWritten) + { + return value.TryEncodeToUtf16(destination, out charsWritten); + } + + /// + public override bool TryParse(ReadOnlySpan source, IFormatProvider? provider, out Rune value) + { + if (source.Length == 2) + { + return Rune.TryCreate(source[0], source[1], out value); + } + else if (source.Length == 1) + { + return Rune.TryCreate(source[0], out value); + } + + value = default; + + return false; + } +} diff --git a/src/Addax.Formats.Tabular/TabularReader.T.cs b/src/Addax.Formats.Tabular/TabularReader.T.cs index 3dcb94f..56368e1 100644 --- a/src/Addax.Formats.Tabular/TabularReader.T.cs +++ b/src/Addax.Formats.Tabular/TabularReader.T.cs @@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis; using System.Numerics; +using System.Text; using Addax.Formats.Tabular.Converters; namespace Addax.Formats.Tabular; @@ -247,6 +248,15 @@ public bool TryGetBase64Binary([NotNullWhen(true)] out byte[]? value) return TryGet(_currentField.AsSpan(), TabularBase64ArrayConverter.Instance, out value); } + /// Tries to parse the current field as and returns a value that indicates whether the operation succeeded. + /// When this method returns, contains a value that represents the current field, or an undefined value on failure. This parameter is treated as uninitialized. + /// if the field was successfully parsed; otherwise, . + /// The value should be represented as one UTF-16 code unit. + public bool TryGetRune(out Rune value) + { + return TryGet(_currentField.AsSpan(), TabularRuneConverter.Instance, out value); + } + /// Parses the current field as . /// A value. /// The current field cannot be parsed as a value. @@ -615,4 +625,18 @@ public byte[] GetBase64Binary() return result; } + + /// Parses the current field as . + /// A value. + /// The current field cannot be parsed as a value. + /// The field must be represented as one UTF-16 code unit. + public Rune GetRune() + { + if (!TryGetRune(out var result)) + { + ThrowFieldFormatException(); + } + + return result; + } } diff --git a/src/Addax.Formats.Tabular/TabularRegistry.T.cs b/src/Addax.Formats.Tabular/TabularRegistry.T.cs index da5db87..9ff8e4e 100644 --- a/src/Addax.Formats.Tabular/TabularRegistry.T.cs +++ b/src/Addax.Formats.Tabular/TabularRegistry.T.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Numerics; +using System.Text; using Addax.Formats.Tabular.Converters; using Addax.Formats.Tabular.Handlers; @@ -61,6 +62,8 @@ private static ConcurrentDictionary CreateHandlers() [typeof(ulong[])] = new TabularArrayHandler(TabularUInt64Converter.Instance), [typeof(ulong?[])] = new TabularSparseArrayHandler(TabularUInt64Converter.Instance), [typeof(Uri?[])] = new TabularArrayHandler(TabularUriConverter.Instance), + [typeof(Rune[])] = new TabularArrayHandler(TabularRuneConverter.Instance), + [typeof(Rune?[])] = new TabularSparseArrayHandler(TabularRuneConverter.Instance), }; } } diff --git a/src/Addax.Formats.Tabular/TabularWriter.T.cs b/src/Addax.Formats.Tabular/TabularWriter.T.cs index bc1bd8c..a3d2ac2 100644 --- a/src/Addax.Formats.Tabular/TabularWriter.T.cs +++ b/src/Addax.Formats.Tabular/TabularWriter.T.cs @@ -1,6 +1,7 @@ // (c) Oleksandr Kozlenko. Licensed under the MIT license. using System.Numerics; +using System.Text; using Addax.Formats.Tabular.Converters; namespace Addax.Formats.Tabular; @@ -259,6 +260,15 @@ public void WriteBase64Binary(byte[]? value) WriteValueCore(value, TabularBase64ArrayConverter.Instance); } + /// Writes a value as the next value field of the current record. + /// A value to write. + public void WriteRune(Rune value) + { + ObjectDisposedException.ThrowIf(_isDisposed, this); + + WriteValueCore(value, TabularRuneConverter.Instance); + } + /// Asynchronously writes a value as the next value field of the current record. /// A value to write. /// The token to monitor for cancellation requests. @@ -588,4 +598,16 @@ public ValueTask WriteBase64BinaryAsync(byte[]? value, CancellationToken cancell return WriteValueCoreAsync(value, TabularBase64ArrayConverter.Instance, cancellationToken); } + + /// Asynchronously writes a value as the next value field of the current record. + /// A value to write. + /// The token to monitor for cancellation requests. + /// A task object. + /// The cancellation token was canceled. This exception is stored into the returned task. + public ValueTask WriteRuneAsync(Rune value, CancellationToken cancellationToken = default) + { + ObjectDisposedException.ThrowIf(_isDisposed, this); + + return WriteValueCoreAsync(value, TabularRuneConverter.Instance, cancellationToken); + } }