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 <andrewarnott@live.com>2022-05-24 19:24:58 +0300
committerGitHub <noreply@github.com>2022-05-24 19:24:58 +0300
commit623aaf27bcbb254f2e5e02c6c37ddb1a650df31f (patch)
tree9c12d0b3d41af9de75d5c5972c85d92e5e13f97e
parentc3fcd1d87c222314bcf108337687d6ff40b140f1 (diff)
parent14ed43cf395c61b4a6aeefa6fe90b72e5d05c0ce (diff)
Merge pull request #1427 from AArnott/fix1240_dateonly
Add built-in support for .NET 6 `DateOnly` and `TimeOnly` types
-rw-r--r--README.md44
-rw-r--r--sandbox/DynamicCodeDumper/DynamicCodeDumper.csproj2
-rw-r--r--sandbox/PerfBenchmarkDotNet/PerfBenchmarkDotNet.csproj2
-rw-r--r--sandbox/PerfNetFramework/PerfNetFramework.csproj2
-rw-r--r--src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Formatters/DateTimeFormatters.cs46
-rw-r--r--src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Internal/Sequence`1.cs120
-rw-r--r--src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/BuiltinResolver.cs6
-rw-r--r--src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/MessagePackWriterTests.cs2
-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
-rw-r--r--tests/MessagePack.GeneratedCode.Tests/MessagePack.GeneratedCode.Tests.csproj2
-rw-r--r--tests/MessagePack.Generator.Tests/MessagePack.Generator.Tests.csproj2
-rw-r--r--tests/MessagePack.Tests/MessagePack.Tests.csproj2
14 files changed, 250 insertions, 47 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/sandbox/DynamicCodeDumper/DynamicCodeDumper.csproj b/sandbox/DynamicCodeDumper/DynamicCodeDumper.csproj
index 633265af..0daf9da4 100644
--- a/sandbox/DynamicCodeDumper/DynamicCodeDumper.csproj
+++ b/sandbox/DynamicCodeDumper/DynamicCodeDumper.csproj
@@ -143,7 +143,7 @@
</Compile>
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Nerdbank.Streams" Version="2.4.48" />
+ <PackageReference Include="Nerdbank.Streams" Version="2.8.57" />
<PackageReference Include="Microsoft.NET.StringTools" Version="1.0.0" />
</ItemGroup>
</Project>
diff --git a/sandbox/PerfBenchmarkDotNet/PerfBenchmarkDotNet.csproj b/sandbox/PerfBenchmarkDotNet/PerfBenchmarkDotNet.csproj
index 36fe6baf..d9a575d0 100644
--- a/sandbox/PerfBenchmarkDotNet/PerfBenchmarkDotNet.csproj
+++ b/sandbox/PerfBenchmarkDotNet/PerfBenchmarkDotNet.csproj
@@ -19,7 +19,7 @@
<PackageReference Include="Jil" version="2.15.4" />
<PackageReference Include="MessagePack" version="1.4.3" />
<PackageReference Include="MsgPack.Cli" version="0.9.0-rc1" />
- <PackageReference Include="Nerdbank.Streams" Version="2.4.48" />
+ <PackageReference Include="Nerdbank.Streams" Version="2.8.57" />
<PackageReference Include="Newtonsoft.Json" version="10.0.3" />
<PackageReference Include="protobuf-net" version="2.3.2" />
<PackageReference Include="RandomFixtureKit" Version="1.0.0" />
diff --git a/sandbox/PerfNetFramework/PerfNetFramework.csproj b/sandbox/PerfNetFramework/PerfNetFramework.csproj
index 080b4fb7..89e5cedf 100644
--- a/sandbox/PerfNetFramework/PerfNetFramework.csproj
+++ b/sandbox/PerfNetFramework/PerfNetFramework.csproj
@@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MsgPack.Cli" version="0.9.0-beta2" />
- <PackageReference Include="Nerdbank.Streams" Version="2.4.48" />
+ <PackageReference Include="Nerdbank.Streams" Version="2.8.57" />
<PackageReference Include="Newtonsoft.Json" version="10.0.3" />
<PackageReference Include="protobuf-net" version="2.1.0" />
<PackageReference Include="ZeroFormatter" version="1.6.4" />
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/Internal/Sequence`1.cs b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Internal/Sequence`1.cs
index 9fe752df..2813b92e 100644
--- a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Internal/Sequence`1.cs
+++ b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Internal/Sequence`1.cs
@@ -27,7 +27,11 @@ namespace Nerdbank.Streams
[DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")]
internal class Sequence<T> : IBufferWriter<T>, IDisposable
{
- private static readonly int DefaultLengthFromArrayPool = 1 + (4095 / Marshal.SizeOf<T>());
+ private const int MaximumAutoGrowSize = 32 * 1024;
+
+ private static readonly int DefaultLengthFromArrayPool = 1 + (4095 / Unsafe.SizeOf<T>());
+
+ private static readonly ReadOnlySequence<T> Empty = new ReadOnlySequence<T>(SequenceSegment.Empty, 0, SequenceSegment.Empty, 0);
private readonly Stack<SequenceSegment> segmentPool = new Stack<SequenceSegment>();
@@ -87,10 +91,22 @@ namespace Nerdbank.Streams
/// The <see cref="MemoryPool{T}"/> in use may itself have a minimum array length as well,
/// in which case the higher of the two minimums dictate the minimum array size that will be allocated.
/// </para>
+ /// <para>
+ /// If <see cref="AutoIncreaseMinimumSpanLength"/> is <c>true</c>, this value may be automatically increased as the length of a sequence grows.
+ /// </para>
/// </remarks>
public int MinimumSpanLength { get; set; } = 0;
/// <summary>
+ /// Gets or sets a value indicating whether the <see cref="MinimumSpanLength"/> should be
+ /// intelligently increased as the length of the sequence grows.
+ /// </summary>
+ /// <remarks>
+ /// This can help prevent long sequences made up of many very small arrays.
+ /// </remarks>
+ public bool AutoIncreaseMinimumSpanLength { get; set; } = true;
+
+ /// <summary>
/// Gets this sequence expressed as a <see cref="ReadOnlySequence{T}"/>.
/// </summary>
/// <returns>A read only sequence representing the data in this object.</returns>
@@ -112,9 +128,9 @@ namespace Nerdbank.Streams
/// <param name="sequence">The sequence to convert.</param>
public static implicit operator ReadOnlySequence<T>(Sequence<T> sequence)
{
- return sequence.first != null
+ return sequence.first != null && sequence.last != null
? new ReadOnlySequence<T>(sequence.first, sequence.first.Start, sequence.last, sequence.last.End)
- : ReadOnlySequence<T>.Empty;
+ : Empty;
}
/// <summary>
@@ -128,10 +144,22 @@ namespace Nerdbank.Streams
public void AdvanceTo(SequencePosition position)
{
var firstSegment = (SequenceSegment)position.GetObject();
+ if (firstSegment == null)
+ {
+ // Emulate PipeReader behavior which is to just return for default(SequencePosition)
+ return;
+ }
+
+ if (ReferenceEquals(firstSegment, SequenceSegment.Empty) && this.Length == 0)
+ {
+ // We were called with our own empty buffer segment.
+ return;
+ }
+
int firstIndex = position.GetInteger();
// Before making any mutations, confirm that the block specified belongs to this sequence.
- var current = this.first;
+ Sequence<T>.SequenceSegment current = this.first;
while (current != firstSegment && current != null)
{
current = current.Next;
@@ -151,12 +179,7 @@ namespace Nerdbank.Streams
firstSegment.AdvanceTo(firstIndex);
- if (firstSegment.Length == 0)
- {
- firstSegment = this.RecycleAndGetNext(firstSegment);
- }
-
- this.first = firstSegment;
+ this.first = firstSegment.Length == 0 ? this.RecycleAndGetNext(firstSegment) : firstSegment;
if (this.first == null)
{
@@ -174,6 +197,7 @@ namespace Nerdbank.Streams
SequenceSegment last = this.last;
Verify.Operation(last != null, "Cannot advance before acquiring memory.");
last.Advance(count);
+ this.ConsiderMinimumSizeIncrease();
}
/// <summary>
@@ -191,6 +215,24 @@ namespace Nerdbank.Streams
public Span<T> GetSpan(int sizeHint) => this.GetSegment(sizeHint).RemainingSpan;
/// <summary>
+ /// Adds an existing memory location to this sequence without copying.
+ /// </summary>
+ /// <param name="memory">The memory to add.</param>
+ /// <remarks>
+ /// This *may* leave significant slack space in a previously allocated block if calls to <see cref="Append(ReadOnlyMemory{T})"/>
+ /// follow calls to <see cref="GetMemory(int)"/> or <see cref="GetSpan(int)"/>.
+ /// </remarks>
+ public void Append(ReadOnlyMemory<T> memory)
+ {
+ if (memory.Length > 0)
+ {
+ Sequence<T>.SequenceSegment segment = this.segmentPool.Count > 0 ? this.segmentPool.Pop() : new SequenceSegment();
+ segment.AssignForeign(memory);
+ this.Append(segment);
+ }
+ }
+
+ /// <summary>
/// Clears the entire sequence, recycles associated memory into pools,
/// and resets this instance for reuse.
/// This invalidates any <see cref="ReadOnlySequence{T}"/> previously produced by this instance.
@@ -204,7 +246,7 @@ namespace Nerdbank.Streams
/// </summary>
public void Reset()
{
- var current = this.first;
+ Sequence<T>.SequenceSegment current = this.first;
while (current != null)
{
current = this.RecycleAndGetNext(current);
@@ -236,7 +278,7 @@ namespace Nerdbank.Streams
if (minBufferSize.HasValue)
{
- var segment = this.segmentPool.Count > 0 ? this.segmentPool.Pop() : new SequenceSegment();
+ Sequence<T>.SequenceSegment segment = this.segmentPool.Count > 0 ? this.segmentPool.Pop() : new SequenceSegment();
if (this.arrayPool != null)
{
segment.Assign(this.arrayPool.Rent(minBufferSize.Value == -1 ? DefaultLengthFromArrayPool : minBufferSize.Value));
@@ -268,7 +310,7 @@ namespace Nerdbank.Streams
else
{
// The last block is completely unused. Replace it instead of appending to it.
- var current = this.first;
+ Sequence<T>.SequenceSegment current = this.first;
if (this.first != this.last)
{
while (current.Next != this.last)
@@ -291,24 +333,40 @@ namespace Nerdbank.Streams
private SequenceSegment RecycleAndGetNext(SequenceSegment segment)
{
- var recycledSegment = segment;
- segment = segment.Next;
+ Sequence<T>.SequenceSegment recycledSegment = segment;
+ Sequence<T>.SequenceSegment nextSegment = segment.Next;
recycledSegment.ResetMemory(this.arrayPool);
this.segmentPool.Push(recycledSegment);
- return segment;
+ return nextSegment;
+ }
+
+ private void ConsiderMinimumSizeIncrease()
+ {
+ if (this.AutoIncreaseMinimumSpanLength && this.MinimumSpanLength < MaximumAutoGrowSize)
+ {
+ int autoSize = Math.Min(MaximumAutoGrowSize, (int)Math.Min(int.MaxValue, this.Length / 2));
+ if (this.MinimumSpanLength < autoSize)
+ {
+ this.MinimumSpanLength = autoSize;
+ }
+ }
}
private class SequenceSegment : ReadOnlySequenceSegment<T>
{
+ internal static readonly SequenceSegment Empty = new SequenceSegment();
+
/// <summary>
/// A value indicating whether the element may contain references (and thus must be cleared).
/// </summary>
private static readonly bool MayContainReferences = !typeof(T).GetTypeInfo().IsPrimitive;
+#pragma warning disable SA1011 // Closing square brackets should be spaced correctly
/// <summary>
/// Gets the backing array, when using an <see cref="ArrayPool{T}"/> instead of a <see cref="MemoryPool{T}"/>.
/// </summary>
private T[] array;
+#pragma warning restore SA1011 // Closing square brackets should be spaced correctly
/// <summary>
/// Gets the position within <see cref="ReadOnlySequenceSegment{T}.Memory"/> where the data starts.
@@ -363,6 +421,11 @@ namespace Nerdbank.Streams
}
/// <summary>
+ /// Gets a value indicating whether this segment refers to memory that came from outside and that we cannot write to nor recycle.
+ /// </summary>
+ internal bool IsForeignMemory => this.array == null && this.MemoryOwner == null;
+
+ /// <summary>
/// Assigns this (recyclable) segment a new area in memory.
/// </summary>
/// <param name="memoryOwner">The memory and a means to recycle it.</param>
@@ -383,11 +446,21 @@ namespace Nerdbank.Streams
}
/// <summary>
+ /// Assigns this (recyclable) segment a new area in memory.
+ /// </summary>
+ /// <param name="memory">A memory block obtained from outside, that we do not own and should not recycle.</param>
+ internal void AssignForeign(ReadOnlyMemory<T> memory)
+ {
+ this.Memory = memory;
+ this.End = memory.Length;
+ }
+
+ /// <summary>
/// Clears all fields in preparation to recycle this instance.
/// </summary>
internal void ResetMemory(ArrayPool<T> arrayPool)
{
- this.ClearReferences(this.Start, this.End);
+ this.ClearReferences(this.Start, this.End - this.Start);
this.Memory = default;
this.Next = null;
this.RunningIndex = 0;
@@ -411,14 +484,17 @@ namespace Nerdbank.Streams
/// <param name="segment">The next segment in the linked list.</param>
internal void SetNext(SequenceSegment segment)
{
- Debug.Assert(segment != null, "Null not allowed.");
this.Next = segment;
segment.RunningIndex = this.RunningIndex + this.Start + this.Length;
- // When setting Memory, we start with index 0 instead of this.Start because
- // the first segment has an explicit index set anyway,
- // and we don't want to double-count it here.
- this.Memory = this.AvailableMemory.Slice(0, this.Start + this.Length);
+ // Trim any slack on this segment.
+ if (!this.IsForeignMemory)
+ {
+ // When setting Memory, we start with index 0 instead of this.Start because
+ // the first segment has an explicit index set anyway,
+ // and we don't want to double-count it here.
+ this.Memory = this.AvailableMemory.Slice(0, this.Start + this.Length);
+ }
}
/// <summary>
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/MessagePackWriterTests.cs b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/MessagePackWriterTests.cs
index 5d06e78d..de2aa674 100644
--- a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/MessagePackWriterTests.cs
+++ b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/MessagePackWriterTests.cs
@@ -33,7 +33,7 @@ namespace MessagePack.Tests
#endif
/// <summary>
- /// Verifies that <see cref="MessagePackWriter.WriteRaw(ReadOnlySpan{byte})"/>
+ /// Verifies that <c>MessagePackWriter.WriteRaw(ReadOnlySpan{byte})</c>
/// accepts a span that came from stackalloc.
/// </summary>
[Fact]
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
diff --git a/tests/MessagePack.GeneratedCode.Tests/MessagePack.GeneratedCode.Tests.csproj b/tests/MessagePack.GeneratedCode.Tests/MessagePack.GeneratedCode.Tests.csproj
index 99ef099c..0844ff4e 100644
--- a/tests/MessagePack.GeneratedCode.Tests/MessagePack.GeneratedCode.Tests.csproj
+++ b/tests/MessagePack.GeneratedCode.Tests/MessagePack.GeneratedCode.Tests.csproj
@@ -8,7 +8,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
- <PackageReference Include="Nerdbank.Streams" Version="2.4.48" />
+ <PackageReference Include="Nerdbank.Streams" Version="2.8.57" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="coverlet.collector" Version="1.2.0" />
diff --git a/tests/MessagePack.Generator.Tests/MessagePack.Generator.Tests.csproj b/tests/MessagePack.Generator.Tests/MessagePack.Generator.Tests.csproj
index 9f399389..7c12e7f5 100644
--- a/tests/MessagePack.Generator.Tests/MessagePack.Generator.Tests.csproj
+++ b/tests/MessagePack.Generator.Tests/MessagePack.Generator.Tests.csproj
@@ -13,7 +13,7 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
- <PackageReference Include="Nerdbank.Streams" Version="2.4.48" />
+ <PackageReference Include="Nerdbank.Streams" Version="2.8.57" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
diff --git a/tests/MessagePack.Tests/MessagePack.Tests.csproj b/tests/MessagePack.Tests/MessagePack.Tests.csproj
index 9f7d9832..f6ff6860 100644
--- a/tests/MessagePack.Tests/MessagePack.Tests.csproj
+++ b/tests/MessagePack.Tests/MessagePack.Tests.csproj
@@ -27,7 +27,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="MsgPack.Cli" version="0.9.0-beta2" />
- <PackageReference Include="Nerdbank.Streams" Version="2.4.48" />
+ <PackageReference Include="Nerdbank.Streams" Version="2.8.57" />
<PackageReference Include="ReactiveProperty" version="4.2.2" />
<PackageReference Include="xunit" version="2.4.1" />
<PackageReference Include="xunit.runner.console" Version="2.4.1" />