Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/aspnet/MessagePack-CSharp.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Arnott <andrew.arnott@microsoft.com>2022-05-24 05:47:44 +0300
committerAndrew Arnott <andrewarnott@live.com>2022-05-24 19:08:29 +0300
commitc7ef724b09e12284062fb5534d74c78164685fbc (patch)
treee63c48aa3fd02b6ce7ab72fd04f296259cf862c6
parent50b549fe1ffa6346675a55e5bb914c0a8def3c37 (diff)
Add built-in support for .NET 6 `DateOnly` and `TimeOnly` types
`DateOnly` requires 5 bytes (typically). `TimeOnly` requires 6 bytes for second resolution or 8 bytes for ticks resolution. This is automatically selected based on the original value. Closes #1240 # Conflicts: # src/MessagePack/net6.0/PublicAPI.Unshipped.txt
-rw-r--r--README.md44
-rw-r--r--src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Formatters/DateTimeFormatters.cs46
-rw-r--r--src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/BuiltinResolver.cs6
-rw-r--r--src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/StandardClassLibraryFormatterTests.cs57
-rw-r--r--src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/TestUtilities.cs2
-rw-r--r--src/MessagePack/net6.0/PublicAPI.Unshipped.txt8
6 files changed, 145 insertions, 18 deletions
diff --git a/README.md b/README.md
index b6427567..77d2c655 100644
--- a/README.md
+++ b/README.md
@@ -1499,24 +1499,36 @@ var resolver = MessagePack.Resolvers.CompositeResolver.Create(
## Reserved Extension Types
-MessagePack for C# already used some MessagePack extension type codes, be careful to use same ext code.
+MessagePack for C# already used some MessagePack extension type codes, be careful to avoid using the same ext code for other purposes.
+
+Range | Reserved for
+--|--
+\[-128, -1\] | Reserved by the msgpack spec for predefined types
+\[30, 120) | Reserved for this library's use to support common types in .NET
+
+This leaves the following ranges for your use:
+
+- \[0, 30)
+- \[120, 127]
+
+Within the *reserved* ranges, this library defines or implements extensions that use these type codes:
| Code | Type | Use by |
-| --- | --- | --- |
-| -1 | DateTime | MessagePack-spec reserved for timestamp |
-| 30 | Vector2[] | for Unity, UnsafeBlitFormatter |
-| 31 | Vector3[] | for Unity, UnsafeBlitFormatter |
-| 32 | Vector4[] | for Unity, UnsafeBlitFormatter |
-| 33 | Quaternion[] | for Unity, UnsafeBlitFormatter |
-| 34 | Color[] | for Unity, UnsafeBlitFormatter |
-| 35 | Bounds[] | for Unity, UnsafeBlitFormatter |
-| 36 | Rect[] | for Unity, UnsafeBlitFormatter |
-| 37 | Int[] | for Unity, UnsafeBlitFormatter |
-| 38 | Float[] | for Unity, UnsafeBlitFormatter |
-| 39 | Double[] | for Unity, UnsafeBlitFormatter |
-| 98 | All | MessagePackCompression.Lz4BlockArray |
-| 99 | All | MessagePackCompression.Lz4Block |
-| 100 | object | TypelessFormatter |
+| ---- | ---- | --- |
+| -1 | DateTime | MessagePack-spec reserved for timestamp |
+| 30 | Vector2[] | for Unity, UnsafeBlitFormatter |
+| 31 | Vector3[] | for Unity, UnsafeBlitFormatter |
+| 32 | Vector4[] | for Unity, UnsafeBlitFormatter |
+| 33 | Quaternion[] | for Unity, UnsafeBlitFormatter |
+| 34 | Color[] | for Unity, UnsafeBlitFormatter |
+| 35 | Bounds[] | for Unity, UnsafeBlitFormatter |
+| 36 | Rect[] | for Unity, UnsafeBlitFormatter |
+| 37 | Int[] | for Unity, UnsafeBlitFormatter |
+| 38 | Float[] | for Unity, UnsafeBlitFormatter |
+| 39 | Double[] | for Unity, UnsafeBlitFormatter |
+| 98 | All | MessagePackCompression.Lz4BlockArray |
+| 99 | All | MessagePackCompression.Lz4Block |
+| 100 | object | TypelessFormatter |
## Unity support
diff --git a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Formatters/DateTimeFormatters.cs b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Formatters/DateTimeFormatters.cs
index 06d2ef80..07da2097 100644
--- a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Formatters/DateTimeFormatters.cs
+++ b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Formatters/DateTimeFormatters.cs
@@ -70,4 +70,50 @@ namespace MessagePack.Formatters
return array;
}
}
+
+#if NET6_0_OR_GREATER
+ /// <summary>
+ /// Serializes a <see cref="DateOnly"/> value as an ordinary <see cref="int"/> using the <see cref="DateOnly.DayNumber"/>.
+ /// </summary>
+ public sealed class DateOnlyFormatter : IMessagePackFormatter<DateOnly>
+ {
+ public static readonly DateOnlyFormatter Instance = new DateOnlyFormatter();
+
+ private DateOnlyFormatter()
+ {
+ }
+
+ public void Serialize(ref MessagePackWriter writer, DateOnly value, MessagePackSerializerOptions options)
+ {
+ writer.Write(value.DayNumber);
+ }
+
+ public DateOnly Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
+ {
+ return DateOnly.FromDayNumber(reader.ReadInt32());
+ }
+ }
+
+ /// <summary>
+ /// Serializes a <see cref="TimeOnly"/> value as an extension, recording either seconds or ticks depending on the resolution required.
+ /// </summary>
+ public sealed class TimeOnlyFormatter : IMessagePackFormatter<TimeOnly>
+ {
+ public static readonly TimeOnlyFormatter Instance = new TimeOnlyFormatter();
+
+ private TimeOnlyFormatter()
+ {
+ }
+
+ public void Serialize(ref MessagePackWriter writer, TimeOnly value, MessagePackSerializerOptions options)
+ {
+ writer.Write(value.Ticks);
+ }
+
+ public TimeOnly Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
+ {
+ return new TimeOnly(reader.ReadInt64());
+ }
+ }
+#endif
}
diff --git a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/BuiltinResolver.cs b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/BuiltinResolver.cs
index 000b9fbd..0defd99f 100644
--- a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/BuiltinResolver.cs
+++ b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/BuiltinResolver.cs
@@ -64,9 +64,13 @@ namespace MessagePack.Internal
{ typeof(byte), ByteFormatter.Instance },
{ typeof(sbyte), SByteFormatter.Instance },
{ typeof(DateTime), DateTimeFormatter.Instance },
+#if NET6_0_OR_GREATER
+ { typeof(DateOnly), DateOnlyFormatter.Instance },
+ { typeof(TimeOnly), TimeOnlyFormatter.Instance },
+#endif
{ typeof(char), CharFormatter.Instance },
- // Nulllable Primitive
+ // Nullable Primitive
{ typeof(Int16?), NullableInt16Formatter.Instance },
{ typeof(Int32?), NullableInt32Formatter.Instance },
{ typeof(Int64?), NullableInt64Formatter.Instance },
diff --git a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/StandardClassLibraryFormatterTests.cs b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/StandardClassLibraryFormatterTests.cs
index 12abda44..35123476 100644
--- a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/StandardClassLibraryFormatterTests.cs
+++ b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/StandardClassLibraryFormatterTests.cs
@@ -2,7 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
-using System.Linq;
+using Nerdbank.Streams;
using Xunit;
using Xunit.Abstractions;
@@ -77,5 +77,60 @@ namespace MessagePack.Tests
byte[] byte_array = MessagePackSerializer.Deserialize<byte[]>(input);
Assert.Equal(new byte[] { 1, 2, 3 }, byte_array);
}
+
+#if NET6_0_OR_GREATER
+ [Fact]
+ public void DateOnly()
+ {
+ var value = new DateOnly(2012, 3, 5);
+ this.AssertRoundtrip(value);
+ this.AssertRoundtrip<DateOnly?>(value);
+ this.AssertRoundtrip(new[] { value });
+ }
+
+ [Fact]
+ public void TimeOnly()
+ {
+ TimeOnly lowRes = new TimeOnly(5, 4, 3);
+ this.AssertRoundtrip(lowRes);
+ this.AssertRoundtrip<TimeOnly?>(lowRes);
+ this.AssertRoundtrip(new[] { lowRes });
+
+ TimeOnly mediumRes = new TimeOnly(5, 4, 3, 2);
+ this.AssertRoundtrip(mediumRes);
+ this.AssertRoundtrip<TimeOnly?>(mediumRes);
+ this.AssertRoundtrip(new[] { mediumRes });
+
+ TimeOnly highRes = new TimeOnly(lowRes.Ticks + 1);
+ this.AssertRoundtrip(highRes);
+ this.AssertRoundtrip(System.TimeOnly.MaxValue);
+ }
+#endif
+
+ private void AssertRoundtrip<T>(T value)
+ {
+ Assert.Equal(value, this.Roundtrip(value, breakupBuffer: false));
+ Assert.Equal(value, this.Roundtrip(value, breakupBuffer: true));
+ }
+
+ private T Roundtrip<T>(T value, bool breakupBuffer = false)
+ {
+ byte[] msgpack = MessagePackSerializer.Serialize(value, MessagePackSerializerOptions.Standard);
+ this.logger.WriteLine("{0} 0x{1}", value, TestUtilities.ToHex(msgpack));
+
+ if (breakupBuffer)
+ {
+ using (Sequence<byte> seq = new Sequence<byte>())
+ {
+ seq.Append(msgpack.AsMemory(0, msgpack.Length - 1));
+ seq.Append(msgpack.AsMemory(msgpack.Length - 1, 1));
+ return MessagePackSerializer.Deserialize<T>(seq, MessagePackSerializerOptions.Standard);
+ }
+ }
+ else
+ {
+ return MessagePackSerializer.Deserialize<T>(msgpack, MessagePackSerializerOptions.Standard);
+ }
+ }
}
}
diff --git a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/TestUtilities.cs b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/TestUtilities.cs
index 0a4bf9fb..abc85b0f 100644
--- a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/TestUtilities.cs
+++ b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/TestUtilities.cs
@@ -15,6 +15,8 @@ namespace MessagePack.Tests
/// Gets a value indicating whether the mono runtime is executing this code.
/// </summary>
internal static bool IsRunningOnMono => Type.GetType("Mono.Runtime") != null;
+
+ internal static string ToHex(byte[] buffer) => BitConverter.ToString(buffer).Replace("-", string.Empty).ToLowerInvariant();
}
public class NullTestOutputHelper : ITestOutputHelper
diff --git a/src/MessagePack/net6.0/PublicAPI.Unshipped.txt b/src/MessagePack/net6.0/PublicAPI.Unshipped.txt
index 9ba64088..78006a92 100644
--- a/src/MessagePack/net6.0/PublicAPI.Unshipped.txt
+++ b/src/MessagePack/net6.0/PublicAPI.Unshipped.txt
@@ -1,6 +1,14 @@
+MessagePack.Formatters.DateOnlyFormatter
+MessagePack.Formatters.DateOnlyFormatter.Deserialize(ref MessagePack.MessagePackReader reader, MessagePack.MessagePackSerializerOptions options) -> System.DateOnly
+MessagePack.Formatters.DateOnlyFormatter.Serialize(ref MessagePack.MessagePackWriter writer, System.DateOnly value, MessagePack.MessagePackSerializerOptions options) -> void
MessagePack.Formatters.StringInterningFormatter
MessagePack.Formatters.StringInterningFormatter.Deserialize(ref MessagePack.MessagePackReader reader, MessagePack.MessagePackSerializerOptions options) -> string
MessagePack.Formatters.StringInterningFormatter.Serialize(ref MessagePack.MessagePackWriter writer, string value, MessagePack.MessagePackSerializerOptions options) -> void
MessagePack.Formatters.StringInterningFormatter.StringInterningFormatter() -> void
+MessagePack.Formatters.TimeOnlyFormatter
+MessagePack.Formatters.TimeOnlyFormatter.Deserialize(ref MessagePack.MessagePackReader reader, MessagePack.MessagePackSerializerOptions options) -> System.TimeOnly
+MessagePack.Formatters.TimeOnlyFormatter.Serialize(ref MessagePack.MessagePackWriter writer, System.TimeOnly value, MessagePack.MessagePackSerializerOptions options) -> void
MessagePack.MessagePackSerializerOptions.CompressionMinLength.get -> int
MessagePack.MessagePackSerializerOptions.WithCompressionMinLength(int compressionMinLength) -> MessagePack.MessagePackSerializerOptions
+static readonly MessagePack.Formatters.DateOnlyFormatter.Instance -> MessagePack.Formatters.DateOnlyFormatter
+static readonly MessagePack.Formatters.TimeOnlyFormatter.Instance -> MessagePack.Formatters.TimeOnlyFormatter