Delete the in-tree cache, JsonKnownTypes and vendored MessagePack

Cut 8b, deletes first. The old authorities are removed, not demoted:
- ServerShared/CultCache: CultCache.cs, DatabaseEntry.cs (root [Union],
  DatabaseLink, INamedEntry), RegisterResolver.cs, TypeFormatterResolver.cs,
  JsonConverters.cs, JsonKnownTypes/**.
- Assets/Plugins/MessagePack/** and System.Runtime.CompilerServices.Unsafe.dll
  (org.gamecult.cultlib ships both).
- GalaxyMapLayerData, PlayerData, GlobalSettingsAttribute.
- The inspector attributes CultLib already carries or nothing reads.

Kept and moved: MathFormatters.cs and MathResolver.cs to
ServerShared/Serialization; GetAllChildClasses, SplitCamelCase,
FormatTypeName, MaxBy and MinBy to Extensions.cs; Inspectable,
PreferredInspectorAttribute and the five Aetheria drawer attributes to
ServerShared/Attributes.cs. Aetheria.Shared.csproj drops the vendored
MessagePack include and the Unsafe package; the asmdef drops MessagePack.

Does not build: the data model moves onto CultLib in the next commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-09-14 18:42:09 +02:00
commit b4c06b50cb
266 changed files with 67 additions and 33150 deletions

View file

@ -3,7 +3,7 @@
Compiles ServerShared and its dependencies from source with no Unity defines, so a successful build is the
check that the simulation stays independent of the engine. Tools and test harnesses reference this project. -->
<PropertyGroup>
<!-- Unity compiles ServerShared against .NET Standard 2.1; newer targets also impose C# 11 ref-safety rules the vendored MessagePack predates -->
<!-- Unity compiles ServerShared against .NET Standard 2.1 -->
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>9.0</LangVersion>
<Nullable>disable</Nullable>
@ -18,7 +18,6 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="$(Assets)Scripts\ServerShared\**\*.cs" />
<Compile Include="$(Assets)Plugins\MessagePack\**\*.cs" Exclude="$(Assets)Plugins\MessagePack\Unity\**" />
<Compile Include="$(Assets)Plugins\UniRx\Scripts\**\*.cs" Exclude="$(Assets)Plugins\UniRx\Scripts\UnityEngineBridge\**;$(Assets)Plugins\UniRx\Scripts\UnityWinRTBridge\**;$(Assets)Plugins\UniRx\Scripts\InternalUtil\MicroCoroutine.cs" />
<!-- The reactive collections live in UniRx's Unity bridge but fence their Unity parts behind UniRxLibrary -->
<Compile Include="$(Assets)Plugins\UniRx\Scripts\UnityEngineBridge\ReactiveProperty.cs;$(Assets)Plugins\UniRx\Scripts\UnityEngineBridge\ReactiveCollection.cs;$(Assets)Plugins\UniRx\Scripts\UnityEngineBridge\ReactiveDictionary.cs" />
@ -27,7 +26,5 @@
<ItemGroup>
<ProjectReference Include="$(CultLibRoot)\packages\cultmath\src\CultMath\CultMath.csproj" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<!-- Bundled by Unity; .NET Standard 2.1 lacks it -->
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
</ItemGroup>
</Project>

View file

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 78d7ac1a75fbd3f4d91b72ac2de5f552
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 258cef354b8273b4ca696ab53c01327a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,81 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = true)]
public class MessagePackObjectAttribute : Attribute
{
public bool KeyAsPropertyName { get; private set; }
public MessagePackObjectAttribute(bool keyAsPropertyName = false)
{
this.KeyAsPropertyName = keyAsPropertyName;
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class KeyAttribute : Attribute
{
public int? IntKey { get; private set; }
public string StringKey { get; private set; }
public KeyAttribute(int x)
{
this.IntKey = x;
}
public KeyAttribute(string x)
{
this.StringKey = x;
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class IgnoreMemberAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public class UnionAttribute : Attribute
{
public int Key { get; private set; }
public Type SubType { get; private set; }
public UnionAttribute(int key, Type subType)
{
this.Key = key;
this.SubType = subType;
}
}
[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = true)]
public class SerializationConstructorAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class MessagePackFormatterAttribute : Attribute
{
public Type FormatterType { get; private set; }
public object[] Arguments { get; private set; }
public MessagePackFormatterAttribute(Type formatterType)
{
this.FormatterType = formatterType;
}
public MessagePackFormatterAttribute(Type formatterType, params object[] arguments)
{
this.FormatterType = formatterType;
this.Arguments = arguments;
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: db21d74c4f54408a9acd69873192155c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,12 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace MessagePack
{
public interface IMessagePackSerializationCallbackReceiver
{
void OnBeforeSerialize();
void OnAfterDeserialize();
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: ef32599edd0f43366891b8da5d4aed1e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,36 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// <auto-generated />
#if !NETCOREAPP
using System.Runtime.CompilerServices;
// Some routines inspired by the Stanford Bit Twiddling Hacks by Sean Eron Anderson:
// http://graphics.stanford.edu/~seander/bithacks.html
namespace System.Numerics
{
/// <summary>
/// Utility methods for intrinsic bit-twiddling operations.
/// The methods use hardware intrinsics when available on the underlying platform,
/// otherwise they use optimized software fallbacks.
/// </summary>
internal static class BitOperations
{
/// <summary>
/// Rotates the specified value left by the specified number of bits.
/// Similar in behavior to the x86 instruction ROL.
/// </summary>
/// <param name="value">The value to rotate.</param>
/// <param name="offset">The number of bits to rotate by.
/// Any value outside the range [0..31] is treated as congruent mod 32.</param>
/// <returns>The rotated value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint RotateLeft(uint value, int offset)
=> (value << offset) | (value >> (32 - offset));
}
}
#endif

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 3c1e411a42f526567af32d094a9de348
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,260 +0,0 @@
// <auto-generated /> // We want to keep this file as-is since it's shared with other repos.
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) Andrew Arnott. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace MessagePack
{
/// <summary>
/// A fast access struct that wraps <see cref="IBufferWriter{T}"/>.
/// </summary>
internal ref struct BufferWriter
{
/// <summary>
/// The underlying <see cref="IBufferWriter{T}"/>.
/// </summary>
private IBufferWriter<byte> _output;
/// <summary>
/// The result of the last call to <see cref="IBufferWriter{T}.GetSpan(int)"/>, less any bytes already "consumed" with <see cref="Advance(int)"/>.
/// Backing field for the <see cref="Span"/> property.
/// </summary>
private Span<byte> _span;
/// <summary>
/// The result of the last call to <see cref="IBufferWriter{T}.GetMemory(int)"/>, less any bytes already "consumed" with <see cref="Advance(int)"/>.
/// </summary>
private ArraySegment<byte> _segment;
/// <summary>
/// The number of uncommitted bytes (all the calls to <see cref="Advance(int)"/> since the last call to <see cref="Commit"/>).
/// </summary>
private int _buffered;
/// <summary>
/// The total number of bytes written with this writer.
/// Backing field for the <see cref="BytesCommitted"/> property.
/// </summary>
private long _bytesCommitted;
private SequencePool _sequencePool;
private SequencePool.Rental _rental;
/// <summary>
/// Initializes a new instance of the <see cref="BufferWriter"/> struct.
/// </summary>
/// <param name="output">The <see cref="IBufferWriter{T}"/> to be wrapped.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public BufferWriter(IBufferWriter<byte> output)
{
_buffered = 0;
_bytesCommitted = 0;
_output = output ?? throw new ArgumentNullException(nameof(output));
_sequencePool = default;
_rental = default;
var memory = _output.GetMemoryCheckResult();
MemoryMarshal.TryGetArray(memory, out _segment);
_span = memory.Span;
}
/// <summary>
/// Initializes a new instance of the <see cref="BufferWriter"/> struct.
/// </summary>
/// <param name="sequencePool">The pool from which to draw an <see cref="IBufferWriter{T}"/> if required..</param>
/// <param name="array">An array to start with so we can avoid accessing the <paramref name="sequencePool"/> if possible.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal BufferWriter(SequencePool sequencePool, byte[] array)
{
_buffered = 0;
_bytesCommitted = 0;
_sequencePool = sequencePool ?? throw new ArgumentNullException(nameof(sequencePool));
_rental = default;
_output = null;
_segment = new ArraySegment<byte>(array);
_span = _segment.AsSpan();
}
/// <summary>
/// Gets the result of the last call to <see cref="IBufferWriter{T}.GetSpan(int)"/>.
/// </summary>
public Span<byte> Span => _span;
/// <summary>
/// Gets the total number of bytes written with this writer.
/// </summary>
public long BytesCommitted => _bytesCommitted;
/// <summary>
/// Gets the <see cref="IBufferWriter{T}"/> underlying this instance.
/// </summary>
internal IBufferWriter<byte> UnderlyingWriter => _output;
internal SequencePool.Rental SequenceRental => _rental;
public Span<byte> GetSpan(int sizeHint)
{
Ensure(sizeHint);
return this.Span;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref byte GetPointer(int sizeHint)
{
Ensure(sizeHint);
if (_segment.Array != null)
{
return ref _segment.Array[_segment.Offset + _buffered];
}
else
{
return ref _span.GetPinnableReference();
}
}
/// <summary>
/// Calls <see cref="IBufferWriter{T}.Advance(int)"/> on the underlying writer
/// with the number of uncommitted bytes.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Commit()
{
var buffered = _buffered;
if (buffered > 0)
{
this.MigrateToSequence();
_bytesCommitted += buffered;
_buffered = 0;
_output.Advance(buffered);
_span = default;
}
}
/// <summary>
/// Used to indicate that part of the buffer has been written to.
/// </summary>
/// <param name="count">The number of bytes written to.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Advance(int count)
{
_buffered += count;
_span = _span.Slice(count);
}
/// <summary>
/// Copies the caller's buffer into this writer and calls <see cref="Advance(int)"/> with the length of the source buffer.
/// </summary>
/// <param name="source">The buffer to copy in.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Write(ReadOnlySpan<byte> source)
{
if (_span.Length >= source.Length)
{
source.CopyTo(_span);
Advance(source.Length);
}
else
{
WriteMultiBuffer(source);
}
}
/// <summary>
/// Acquires a new buffer if necessary to ensure that some given number of bytes can be written to a single buffer.
/// </summary>
/// <param name="count">The number of bytes that must be allocated in a single buffer.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Ensure(int count = 1)
{
if (_span.Length < count)
{
EnsureMore(count);
}
}
/// <summary>
/// Gets the span to the bytes written if they were never committed to the underlying buffer writer.
/// </summary>
/// <param name="span"></param>
/// <returns></returns>
internal bool TryGetUncommittedSpan(out ReadOnlySpan<byte> span)
{
if (this._sequencePool != null)
{
span = _segment.AsSpan(0, _buffered);
return true;
}
span = default;
return false;
}
/// <summary>
/// Gets a fresh span to write to, with an optional minimum size.
/// </summary>
/// <param name="count">The minimum size for the next requested buffer.</param>
[MethodImpl(MethodImplOptions.NoInlining)]
private void EnsureMore(int count = 0)
{
if (_buffered > 0)
{
Commit();
}
else
{
this.MigrateToSequence();
}
var memory = _output.GetMemoryCheckResult(count);
MemoryMarshal.TryGetArray(memory, out _segment);
_span = memory.Span;
}
/// <summary>
/// Copies the caller's buffer into this writer, potentially across multiple buffers from the underlying writer.
/// </summary>
/// <param name="source">The buffer to copy into this writer.</param>
private void WriteMultiBuffer(ReadOnlySpan<byte> source)
{
int copiedBytes = 0;
int bytesLeftToCopy = source.Length;
while (bytesLeftToCopy > 0)
{
if (_span.Length == 0)
{
EnsureMore();
}
var writable = Math.Min(bytesLeftToCopy, _span.Length);
source.Slice(copiedBytes, writable).CopyTo(_span);
copiedBytes += writable;
bytesLeftToCopy -= writable;
Advance(writable);
}
}
private void MigrateToSequence()
{
if (this._sequencePool != null)
{
// We were writing to our private scratch memory, so we have to copy it into the actual writer.
_rental = _sequencePool.Rent();
_output = _rental.Value;
var realSpan = _output.GetSpan(_buffered);
_segment.AsSpan(0, _buffered).CopyTo(realSpan);
_sequencePool = null;
}
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 91a2222860edec5ff9ee6e4fe1af7668
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,33 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace MessagePack
{
#if MESSAGEPACK_INTERNAL
internal
#else
public
#endif
struct ExtensionHeader : IEquatable<ExtensionHeader>
{
public sbyte TypeCode { get; private set; }
public uint Length { get; private set; }
public ExtensionHeader(sbyte typeCode, uint length)
{
this.TypeCode = typeCode;
this.Length = length;
}
public ExtensionHeader(sbyte typeCode, int length)
{
this.TypeCode = typeCode;
this.Length = (uint)length;
}
public bool Equals(ExtensionHeader other) => this.TypeCode == other.TypeCode && this.Length == other.Length;
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 92a76851178ab369fbc386556cb866ce
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,34 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Buffers;
namespace MessagePack
{
#if MESSAGEPACK_INTERNAL
internal
#else
public
#endif
struct ExtensionResult
{
public ExtensionResult(sbyte typeCode, Memory<byte> data)
{
this.TypeCode = typeCode;
this.Data = new ReadOnlySequence<byte>(data);
}
public ExtensionResult(sbyte typeCode, ReadOnlySequence<byte> data)
{
this.TypeCode = typeCode;
this.Data = data;
}
public sbyte TypeCode { get; private set; }
public ReadOnlySequence<byte> Data { get; private set; }
public ExtensionHeader Header => new ExtensionHeader(this.TypeCode, (uint)this.Data.Length);
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 153f71ac242b4218d9debb5971c7b5d4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 4e7629820f4485c4790dbe9265bb2830
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: f92b8946eec0ab476a689a0dfa8c2498
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,52 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Linq.Expressions;
namespace MessagePack.Formatters
{
/// <summary>
/// Provides general helpers for creating collections (including dictionaries).
/// </summary>
/// <typeparam name="TCollection">The concrete type of collection to create.</typeparam>
/// <typeparam name="TEqualityComparer">The type of equality comparer that we would hope to pass into the collection's constructor.</typeparam>
internal static class CollectionHelpers<TCollection, TEqualityComparer>
where TCollection : new()
{
/// <summary>
/// The delegate that will create the collection, if the typical (int count, IEqualityComparer{T} equalityComparer) constructor was found.
/// </summary>
private static Func<int, TEqualityComparer, TCollection> collectionCreator;
/// <summary>
/// Initializes static members of the <see cref="CollectionHelpers{TCollection, TEqualityComparer}"/> class.
/// </summary>
/// <remarks>
/// Initializes a delegate that is optimized to create a collection of a given size and using the given equality comparer, if possible.
/// </remarks>
static CollectionHelpers()
{
var ctor = typeof(TCollection).GetConstructor(new Type[] { typeof(int), typeof(TEqualityComparer) });
if (ctor != null)
{
ParameterExpression param1 = Expression.Parameter(typeof(int), "count");
ParameterExpression param2 = Expression.Parameter(typeof(TEqualityComparer), "equalityComparer");
NewExpression body = Expression.New(ctor, param1, param2);
collectionCreator = Expression.Lambda<Func<int, TEqualityComparer, TCollection>>(body, param1, param2).Compile();
}
}
/// <summary>
/// Initializes a new instance of the <typeparamref name="TCollection"/> collection.
/// </summary>
/// <param name="count">The number of elements the collection should be prepared to receive.</param>
/// <param name="equalityComparer">The equality comparer to initialize the collection with.</param>
/// <returns>The newly initialized collection.</returns>
/// <remarks>
/// Use of the <paramref name="count"/> and <paramref name="equalityComparer"/> are a best effort.
/// If we can't find a constructor on the collection in the expected shape, we'll just instantiate the collection with its default constructor.
/// </remarks>
internal static TCollection CreateHashCollection(int count, TEqualityComparer equalityComparer) => collectionCreator != null ? collectionCreator.Invoke(count, equalityComparer) : new TCollection();
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 25f9fe82ddb369c8f9600901293b80f8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,70 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack.Formatters
{
/// <summary>
/// Serialize by .NET native DateTime binary format.
/// </summary>
public sealed class NativeDateTimeFormatter : IMessagePackFormatter<DateTime>
{
public static readonly NativeDateTimeFormatter Instance = new NativeDateTimeFormatter();
public void Serialize(ref MessagePackWriter writer, DateTime value, MessagePackSerializerOptions options)
{
var dateData = value.ToBinary();
writer.Write(dateData);
}
public DateTime Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
var dateData = reader.ReadInt64();
return DateTime.FromBinary(dateData);
}
}
public sealed class NativeDateTimeArrayFormatter : IMessagePackFormatter<DateTime[]>
{
public static readonly NativeDateTimeArrayFormatter Instance = new NativeDateTimeArrayFormatter();
public void Serialize(ref MessagePackWriter writer, DateTime[] value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
writer.WriteArrayHeader(value.Length);
for (int i = 0; i < value.Length; i++)
{
writer.Write(value[i].ToBinary());
}
}
}
public DateTime[] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
var len = reader.ReadArrayHeader();
var array = new DateTime[len];
for (int i = 0; i < array.Length; i++)
{
var dateData = reader.ReadInt64();
array[i] = DateTime.FromBinary(dateData);
}
return array;
}
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: e28b94bd9483c36efae78067f97c65cb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,280 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack.Formatters
{
// unfortunately, can't use IDictionary<KVP> because supports IReadOnlyDictionary.
public abstract class DictionaryFormatterBase<TKey, TValue, TIntermediate, TEnumerator, TDictionary> : IMessagePackFormatter<TDictionary>
where TDictionary : IEnumerable<KeyValuePair<TKey, TValue>>
where TEnumerator : IEnumerator<KeyValuePair<TKey, TValue>>
{
public void Serialize(ref MessagePackWriter writer, TDictionary value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
IFormatterResolver resolver = options.Resolver;
IMessagePackFormatter<TKey> keyFormatter = resolver.GetFormatterWithVerify<TKey>();
IMessagePackFormatter<TValue> valueFormatter = resolver.GetFormatterWithVerify<TValue>();
int count;
{
var col = value as ICollection<KeyValuePair<TKey, TValue>>;
if (col != null)
{
count = col.Count;
}
else
{
var col2 = value as IReadOnlyCollection<KeyValuePair<TKey, TValue>>;
if (col2 != null)
{
count = col2.Count;
}
else
{
throw new MessagePackSerializationException("DictionaryFormatterBase's TDictionary supports only ICollection<KVP> or IReadOnlyCollection<KVP>");
}
}
}
writer.WriteMapHeader(count);
TEnumerator e = this.GetSourceEnumerator(value);
try
{
while (e.MoveNext())
{
writer.CancellationToken.ThrowIfCancellationRequested();
KeyValuePair<TKey, TValue> item = e.Current;
keyFormatter.Serialize(ref writer, item.Key, options);
valueFormatter.Serialize(ref writer, item.Value, options);
}
}
finally
{
e.Dispose();
}
}
}
public TDictionary Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return default(TDictionary);
}
else
{
IFormatterResolver resolver = options.Resolver;
IMessagePackFormatter<TKey> keyFormatter = resolver.GetFormatterWithVerify<TKey>();
IMessagePackFormatter<TValue> valueFormatter = resolver.GetFormatterWithVerify<TValue>();
var len = reader.ReadMapHeader();
TIntermediate dict = this.Create(len, options);
options.Security.DepthStep(ref reader);
try
{
for (int i = 0; i < len; i++)
{
reader.CancellationToken.ThrowIfCancellationRequested();
TKey key = keyFormatter.Deserialize(ref reader, options);
TValue value = valueFormatter.Deserialize(ref reader, options);
this.Add(dict, i, key, value, options);
}
}
finally
{
reader.Depth--;
}
return this.Complete(dict);
}
}
// abstraction for serialize
// Some collections can use struct iterator, this is optimization path
protected abstract TEnumerator GetSourceEnumerator(TDictionary source);
// abstraction for deserialize
protected abstract TIntermediate Create(int count, MessagePackSerializerOptions options);
protected abstract void Add(TIntermediate collection, int index, TKey key, TValue value, MessagePackSerializerOptions options);
protected abstract TDictionary Complete(TIntermediate intermediateCollection);
}
public abstract class DictionaryFormatterBase<TKey, TValue, TIntermediate, TDictionary> : DictionaryFormatterBase<TKey, TValue, TIntermediate, IEnumerator<KeyValuePair<TKey, TValue>>, TDictionary>
where TDictionary : IEnumerable<KeyValuePair<TKey, TValue>>
{
protected override IEnumerator<KeyValuePair<TKey, TValue>> GetSourceEnumerator(TDictionary source)
{
return source.GetEnumerator();
}
}
public abstract class DictionaryFormatterBase<TKey, TValue, TDictionary> : DictionaryFormatterBase<TKey, TValue, TDictionary, TDictionary>
where TDictionary : IDictionary<TKey, TValue>
{
protected override TDictionary Complete(TDictionary intermediateCollection)
{
return intermediateCollection;
}
}
public sealed class DictionaryFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, Dictionary<TKey, TValue>, Dictionary<TKey, TValue>.Enumerator, Dictionary<TKey, TValue>>
{
protected override void Add(Dictionary<TKey, TValue> collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.Add(key, value);
}
protected override Dictionary<TKey, TValue> Complete(Dictionary<TKey, TValue> intermediateCollection)
{
return intermediateCollection;
}
protected override Dictionary<TKey, TValue> Create(int count, MessagePackSerializerOptions options)
{
return new Dictionary<TKey, TValue>(count, options.Security.GetEqualityComparer<TKey>());
}
protected override Dictionary<TKey, TValue>.Enumerator GetSourceEnumerator(Dictionary<TKey, TValue> source)
{
return source.GetEnumerator();
}
}
public sealed class GenericDictionaryFormatter<TKey, TValue, TDictionary> : DictionaryFormatterBase<TKey, TValue, TDictionary>
where TDictionary : IDictionary<TKey, TValue>, new()
{
protected override void Add(TDictionary collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.Add(key, value);
}
protected override TDictionary Create(int count, MessagePackSerializerOptions options)
{
return CollectionHelpers<TDictionary, IEqualityComparer<TKey>>.CreateHashCollection(count, options.Security.GetEqualityComparer<TKey>());
}
}
public sealed class InterfaceDictionaryFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, Dictionary<TKey, TValue>, IDictionary<TKey, TValue>>
{
protected override void Add(Dictionary<TKey, TValue> collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.Add(key, value);
}
protected override Dictionary<TKey, TValue> Create(int count, MessagePackSerializerOptions options)
{
return new Dictionary<TKey, TValue>(count, options.Security.GetEqualityComparer<TKey>());
}
protected override IDictionary<TKey, TValue> Complete(Dictionary<TKey, TValue> intermediateCollection)
{
return intermediateCollection;
}
}
public sealed class SortedListFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, SortedList<TKey, TValue>>
{
protected override void Add(SortedList<TKey, TValue> collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.Add(key, value);
}
protected override SortedList<TKey, TValue> Create(int count, MessagePackSerializerOptions options)
{
return new SortedList<TKey, TValue>(count);
}
}
public sealed class SortedDictionaryFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, SortedDictionary<TKey, TValue>, SortedDictionary<TKey, TValue>.Enumerator, SortedDictionary<TKey, TValue>>
{
protected override void Add(SortedDictionary<TKey, TValue> collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.Add(key, value);
}
protected override SortedDictionary<TKey, TValue> Complete(SortedDictionary<TKey, TValue> intermediateCollection)
{
return intermediateCollection;
}
protected override SortedDictionary<TKey, TValue> Create(int count, MessagePackSerializerOptions options)
{
return new SortedDictionary<TKey, TValue>();
}
protected override SortedDictionary<TKey, TValue>.Enumerator GetSourceEnumerator(SortedDictionary<TKey, TValue> source)
{
return source.GetEnumerator();
}
}
public sealed class ReadOnlyDictionaryFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, Dictionary<TKey, TValue>, ReadOnlyDictionary<TKey, TValue>>
{
protected override void Add(Dictionary<TKey, TValue> collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.Add(key, value);
}
protected override ReadOnlyDictionary<TKey, TValue> Complete(Dictionary<TKey, TValue> intermediateCollection)
{
return new ReadOnlyDictionary<TKey, TValue>(intermediateCollection);
}
protected override Dictionary<TKey, TValue> Create(int count, MessagePackSerializerOptions options)
{
return new Dictionary<TKey, TValue>(count, options.Security.GetEqualityComparer<TKey>());
}
}
public sealed class InterfaceReadOnlyDictionaryFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, Dictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>>
{
protected override void Add(Dictionary<TKey, TValue> collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.Add(key, value);
}
protected override IReadOnlyDictionary<TKey, TValue> Complete(Dictionary<TKey, TValue> intermediateCollection)
{
return intermediateCollection;
}
protected override Dictionary<TKey, TValue> Create(int count, MessagePackSerializerOptions options)
{
return new Dictionary<TKey, TValue>(count, options.Security.GetEqualityComparer<TKey>());
}
}
public sealed class ConcurrentDictionaryFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>>
{
protected override void Add(ConcurrentDictionary<TKey, TValue> collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.TryAdd(key, value);
}
protected override ConcurrentDictionary<TKey, TValue> Create(int count, MessagePackSerializerOptions options)
{
// concurrent dictionary can't access defaultConcurrecyLevel so does not use count overload.
return new ConcurrentDictionary<TKey, TValue>(options.Security.GetEqualityComparer<TKey>());
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 3f0984a238b11bd2c97eb781371bb121
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,82 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace MessagePack.Formatters
{
/// <summary>
/// This formatter can serialize any value whose static type is <see cref="object"/>
/// for which another resolver can provide a formatter for the runtime type.
/// Its deserialization is limited to forwarding all calls to the <see cref="PrimitiveObjectFormatter"/>.
/// </summary>
public sealed class DynamicObjectTypeFallbackFormatter : IMessagePackFormatter<object>
{
public static readonly IMessagePackFormatter<object> Instance = new DynamicObjectTypeFallbackFormatter();
private delegate void SerializeMethod(object dynamicFormatter, ref MessagePackWriter writer, object value, MessagePackSerializerOptions options);
private static readonly Internal.ThreadsafeTypeKeyHashTable<SerializeMethod> SerializerDelegates = new Internal.ThreadsafeTypeKeyHashTable<SerializeMethod>();
private DynamicObjectTypeFallbackFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, object value, MessagePackSerializerOptions options)
{
if (value is null)
{
writer.WriteNil();
return;
}
Type type = value.GetType();
TypeInfo ti = type.GetTypeInfo();
if (type == typeof(object))
{
// serialize to empty map
writer.WriteMapHeader(0);
return;
}
object formatter = options.Resolver.GetFormatterDynamicWithVerify(type);
if (!SerializerDelegates.TryGetValue(type, out SerializeMethod serializerDelegate))
{
lock (SerializerDelegates)
{
if (!SerializerDelegates.TryGetValue(type, out serializerDelegate))
{
Type formatterType = typeof(IMessagePackFormatter<>).MakeGenericType(type);
ParameterExpression param0 = Expression.Parameter(typeof(object), "formatter");
ParameterExpression param1 = Expression.Parameter(typeof(MessagePackWriter).MakeByRefType(), "writer");
ParameterExpression param2 = Expression.Parameter(typeof(object), "value");
ParameterExpression param3 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options");
MethodInfo serializeMethodInfo = formatterType.GetRuntimeMethod("Serialize", new[] { typeof(MessagePackWriter).MakeByRefType(), type, typeof(MessagePackSerializerOptions) });
MethodCallExpression body = Expression.Call(
Expression.Convert(param0, formatterType),
serializeMethodInfo,
param1,
ti.IsValueType ? Expression.Unbox(param2, type) : Expression.Convert(param2, type),
param3);
serializerDelegate = Expression.Lambda<SerializeMethod>(body, param0, param1, param2, param3).Compile();
SerializerDelegates.TryAdd(type, serializerDelegate);
}
}
}
serializerDelegate(formatter, ref writer, value, options);
}
public object Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
return PrimitiveObjectFormatter.Instance.Deserialize(ref reader, options);
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: bc47abc7cd51279d9ac40fe1da6ffa1d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,128 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
namespace MessagePack.Formatters
{
// Note:This implementation is 'not' fastest, should more improve.
public sealed class EnumAsStringFormatter<T> : IMessagePackFormatter<T>
{
private readonly IReadOnlyDictionary<string, T> nameValueMapping;
private readonly IReadOnlyDictionary<T, string> valueNameMapping;
private readonly IReadOnlyDictionary<string, string> clrToSerializationName;
private readonly IReadOnlyDictionary<string, string> serializationToClrName;
private readonly bool enumMemberOverridesPresent;
private readonly bool isFlags;
public EnumAsStringFormatter()
{
this.isFlags = typeof(T).GetCustomAttribute<FlagsAttribute>() is object;
var fields = typeof(T).GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static);
var nameValueMapping = new Dictionary<string, T>(fields.Length);
var valueNameMapping = new Dictionary<T, string>();
Dictionary<string, string> clrToSerializationName = null;
Dictionary<string, string> serializationToClrName = null;
foreach (FieldInfo enumValueMember in fields)
{
string name = enumValueMember.Name;
T value = (T)enumValueMember.GetValue(null);
// Consider the case where the serialized form of the enum value is overridden via an attribute.
var attribute = enumValueMember.GetCustomAttribute<EnumMemberAttribute>();
if (attribute?.IsValueSetExplicitly ?? false)
{
clrToSerializationName = clrToSerializationName ?? new Dictionary<string, string>();
serializationToClrName = serializationToClrName ?? new Dictionary<string, string>();
clrToSerializationName.Add(name, attribute.Value);
serializationToClrName.Add(attribute.Value, name);
name = attribute.Value;
this.enumMemberOverridesPresent = true;
}
nameValueMapping[name] = value;
valueNameMapping[value] = name;
}
this.nameValueMapping = nameValueMapping;
this.valueNameMapping = valueNameMapping;
this.clrToSerializationName = clrToSerializationName;
this.serializationToClrName = serializationToClrName;
}
public void Serialize(ref MessagePackWriter writer, T value, MessagePackSerializerOptions options)
{
// Enum.ToString() is slow, so avoid it when we can.
if (!this.valueNameMapping.TryGetValue(value, out string valueString))
{
// fallback for flags, values with no name, etc
valueString = this.GetSerializedNames(value.ToString());
}
writer.Write(valueString);
}
public T Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
string name = reader.ReadString();
// Avoid Enum.Parse when we can because it is too slow.
if (!this.nameValueMapping.TryGetValue(name, out T value))
{
value = (T)Enum.Parse(typeof(T), this.GetClrNames(name));
}
return value;
}
private string GetClrNames(string serializedNames)
{
if (this.enumMemberOverridesPresent && this.isFlags && serializedNames.IndexOf(", ", StringComparison.Ordinal) >= 0)
{
return Translate(serializedNames, this.serializationToClrName);
}
// We don't need to consider the trivial case of no commas because our caller would have found that in the lookup table and not called us.
return serializedNames;
}
private string GetSerializedNames(string clrNames)
{
if (this.enumMemberOverridesPresent && this.isFlags && clrNames.IndexOf(", ", StringComparison.Ordinal) >= 0)
{
return Translate(clrNames, this.clrToSerializationName);
}
// We don't need to consider the trivial case of no commas because our caller would have found that in the lookup table and not called us.
return clrNames;
}
private static string Translate(string items, IReadOnlyDictionary<string, string> mapping)
{
string[] elements = items.Split(',');
for (int i = 0; i < elements.Length; i++)
{
// Trim the leading space if there is one (due to the delimiter being ", ").
if (i > 0 && elements[i].Length > 0 && elements[i][0] == ' ')
{
elements[i] = elements[i].Substring(1);
}
if (mapping.TryGetValue(elements[i], out string substituteValue))
{
elements[i] = substituteValue;
}
}
return string.Join(", ", elements);
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: f7cdc1e759af9873989648baa08f0350
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,73 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Runtime.CompilerServices;
namespace MessagePack.Formatters
{
public sealed class GenericEnumFormatter<T> : IMessagePackFormatter<T>
where T : Enum
{
private delegate void EnumSerialize(ref MessagePackWriter writer, ref T value);
private delegate T EnumDeserialize(ref MessagePackReader reader);
private readonly EnumSerialize serializer;
private readonly EnumDeserialize deserializer;
public GenericEnumFormatter()
{
var underlyingType = typeof(T).GetEnumUnderlyingType();
switch (Type.GetTypeCode(underlyingType))
{
#pragma warning disable SA1107 // Avoid multiple statements on same line.
case TypeCode.Byte:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, Byte>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadByte(); return Unsafe.As<Byte, T>(ref v); };
break;
case TypeCode.Int16:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, Int16>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadInt16(); return Unsafe.As<Int16, T>(ref v); };
break;
case TypeCode.Int32:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, Int32>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadInt32(); return Unsafe.As<Int32, T>(ref v); };
break;
case TypeCode.Int64:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, Int64>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadInt64(); return Unsafe.As<Int64, T>(ref v); };
break;
case TypeCode.SByte:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, SByte>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadSByte(); return Unsafe.As<SByte, T>(ref v); };
break;
case TypeCode.UInt16:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, UInt16>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadUInt16(); return Unsafe.As<UInt16, T>(ref v); };
break;
case TypeCode.UInt32:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, UInt32>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadUInt32(); return Unsafe.As<UInt32, T>(ref v); };
break;
case TypeCode.UInt64:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, UInt64>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadUInt64(); return Unsafe.As<UInt64, T>(ref v); };
break;
default:
break;
#pragma warning restore SA1107 // Avoid multiple statements on same line.
}
}
public void Serialize(ref MessagePackWriter writer, T value, MessagePackSerializerOptions options)
{
serializer(ref writer, ref value);
}
public T Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
return deserializer(ref reader);
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 7f3275d9a9f3275ec9cc43d6859964fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,42 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Buffers;
using System.ComponentModel;
namespace MessagePack.Formatters
{
#pragma warning disable SA1649 // File name should match first type name
/// <summary>
/// A base interface for <see cref="IMessagePackFormatter{T}"/> so that all generic implementations
/// can be detected by a common base type.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public interface IMessagePackFormatter
{
}
#pragma warning restore SA1649 // File name should match first type name
/// <summary>
/// The contract for serialization of some specific type.
/// </summary>
/// <typeparam name="T">The type to be serialized or deserialized.</typeparam>
public interface IMessagePackFormatter<T> : IMessagePackFormatter
{
/// <summary>
/// Serializes a value.
/// </summary>
/// <param name="writer">The writer to use when serializing the value.</param>
/// <param name="value">The value to be serialized.</param>
/// <param name="options">The serialization settings to use, including the resolver to use to obtain formatters for types that make up the composite type <typeparamref name="T"/>.</param>
void Serialize(ref MessagePackWriter writer, T value, MessagePackSerializerOptions options);
/// <summary>
/// Deserializes a value.
/// </summary>
/// <param name="reader">The reader to deserialize from.</param>
/// <param name="options">The serialization settings to use, including the resolver to use to obtain formatters for types that make up the composite type <typeparamref name="T"/>.</param>
/// <returns>The deserialized value.</returns>
T Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options);
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: cd75a2bcccf20dfb6824d447ec99a1fa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,21 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Buffers;
namespace MessagePack.Formatters
{
public sealed class IgnoreFormatter<T> : IMessagePackFormatter<T>
{
public void Serialize(ref MessagePackWriter writer, T value, MessagePackSerializerOptions options)
{
writer.WriteNil();
}
public T Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
reader.Skip();
return default(T);
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 64fa7163708478803a466c61cdb596d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,293 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Text;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack.Formatters
{
/* multi dimensional array serialize to [i, j, [seq]] */
public sealed class TwoDimensionalArrayFormatter<T> : IMessagePackFormatter<T[,]>
{
private const int ArrayLength = 3;
public void Serialize(ref MessagePackWriter writer, T[,] value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
var i = value.GetLength(0);
var j = value.GetLength(1);
IMessagePackFormatter<T> formatter = options.Resolver.GetFormatterWithVerify<T>();
writer.WriteArrayHeader(ArrayLength);
writer.Write(i);
writer.Write(j);
writer.WriteArrayHeader(value.Length);
foreach (T item in value)
{
writer.CancellationToken.ThrowIfCancellationRequested();
formatter.Serialize(ref writer, item, options);
}
}
}
public T[,] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
IMessagePackFormatter<T> formatter = options.Resolver.GetFormatterWithVerify<T>();
var len = reader.ReadArrayHeader();
if (len != ArrayLength)
{
throw new MessagePackSerializationException("Invalid T[,] format");
}
var iLength = reader.ReadInt32();
var jLength = reader.ReadInt32();
var maxLen = reader.ReadArrayHeader();
var array = new T[iLength, jLength];
var i = 0;
var j = -1;
options.Security.DepthStep(ref reader);
try
{
for (int loop = 0; loop < maxLen; loop++)
{
reader.CancellationToken.ThrowIfCancellationRequested();
if (j < jLength - 1)
{
j++;
}
else
{
j = 0;
i++;
}
array[i, j] = formatter.Deserialize(ref reader, options);
}
}
finally
{
reader.Depth--;
}
return array;
}
}
}
public sealed class ThreeDimensionalArrayFormatter<T> : IMessagePackFormatter<T[,,]>
{
private const int ArrayLength = 4;
public void Serialize(ref MessagePackWriter writer, T[,,] value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
var i = value.GetLength(0);
var j = value.GetLength(1);
var k = value.GetLength(2);
IMessagePackFormatter<T> formatter = options.Resolver.GetFormatterWithVerify<T>();
writer.WriteArrayHeader(ArrayLength);
writer.Write(i);
writer.Write(j);
writer.Write(k);
writer.WriteArrayHeader(value.Length);
foreach (T item in value)
{
writer.CancellationToken.ThrowIfCancellationRequested();
formatter.Serialize(ref writer, item, options);
}
}
}
public T[,,] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
IMessagePackFormatter<T> formatter = options.Resolver.GetFormatterWithVerify<T>();
var len = reader.ReadArrayHeader();
if (len != ArrayLength)
{
throw new MessagePackSerializationException("Invalid T[,,] format");
}
var iLength = reader.ReadInt32();
var jLength = reader.ReadInt32();
var kLength = reader.ReadInt32();
var maxLen = reader.ReadArrayHeader();
var array = new T[iLength, jLength, kLength];
var i = 0;
var j = 0;
var k = -1;
options.Security.DepthStep(ref reader);
try
{
for (int loop = 0; loop < maxLen; loop++)
{
reader.CancellationToken.ThrowIfCancellationRequested();
if (k < kLength - 1)
{
k++;
}
else if (j < jLength - 1)
{
k = 0;
j++;
}
else
{
k = 0;
j = 0;
i++;
}
array[i, j, k] = formatter.Deserialize(ref reader, options);
}
}
finally
{
reader.Depth--;
}
return array;
}
}
}
public sealed class FourDimensionalArrayFormatter<T> : IMessagePackFormatter<T[,,,]>
{
private const int ArrayLength = 5;
public void Serialize(ref MessagePackWriter writer, T[,,,] value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
var i = value.GetLength(0);
var j = value.GetLength(1);
var k = value.GetLength(2);
var l = value.GetLength(3);
IMessagePackFormatter<T> formatter = options.Resolver.GetFormatterWithVerify<T>();
writer.WriteArrayHeader(ArrayLength);
writer.Write(i);
writer.Write(j);
writer.Write(k);
writer.Write(l);
writer.WriteArrayHeader(value.Length);
foreach (T item in value)
{
writer.CancellationToken.ThrowIfCancellationRequested();
formatter.Serialize(ref writer, item, options);
}
}
}
public T[,,,] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
IMessagePackFormatter<T> formatter = options.Resolver.GetFormatterWithVerify<T>();
var len = reader.ReadArrayHeader();
if (len != ArrayLength)
{
throw new MessagePackSerializationException("Invalid T[,,,] format");
}
var iLength = reader.ReadInt32();
var jLength = reader.ReadInt32();
var kLength = reader.ReadInt32();
var lLength = reader.ReadInt32();
var maxLen = reader.ReadArrayHeader();
var array = new T[iLength, jLength, kLength, lLength];
var i = 0;
var j = 0;
var k = 0;
var l = -1;
options.Security.DepthStep(ref reader);
try
{
for (int loop = 0; loop < maxLen; loop++)
{
reader.CancellationToken.ThrowIfCancellationRequested();
if (l < lLength - 1)
{
l++;
}
else if (k < kLength - 1)
{
l = 0;
k++;
}
else if (j < jLength - 1)
{
l = 0;
k = 0;
j++;
}
else
{
l = 0;
k = 0;
j = 0;
i++;
}
array[i, j, k, l] = formatter.Deserialize(ref reader, options);
}
}
finally
{
reader.Depth--;
}
return array;
}
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 8a4af86ee0f0a74de9e88b1fe8c9826d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,44 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace MessagePack.Formatters
{
public class NilFormatter : IMessagePackFormatter<Nil>
{
public static readonly IMessagePackFormatter<Nil> Instance = new NilFormatter();
private NilFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, Nil value, MessagePackSerializerOptions options)
{
writer.WriteNil();
}
public Nil Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
return reader.ReadNil();
}
}
// NullableNil is same as Nil.
public class NullableNilFormatter : IMessagePackFormatter<Nil?>
{
public static readonly IMessagePackFormatter<Nil?> Instance = new NullableNilFormatter();
private NullableNilFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, Nil? value, MessagePackSerializerOptions options)
{
writer.WriteNil();
}
public Nil? Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
return reader.ReadNil();
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 708c91d45dcbf19469504ec78aa2abee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,73 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Buffers;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack.Formatters
{
public sealed class NullableFormatter<T> : IMessagePackFormatter<T?>
where T : struct
{
public void Serialize(ref MessagePackWriter writer, T? value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
options.Resolver.GetFormatterWithVerify<T>().Serialize(ref writer, value.Value, options);
}
}
public T? Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.IsNil)
{
reader.ReadNil();
return null;
}
else
{
return options.Resolver.GetFormatterWithVerify<T>().Deserialize(ref reader, options);
}
}
}
public sealed class StaticNullableFormatter<T> : IMessagePackFormatter<T?>
where T : struct
{
private readonly IMessagePackFormatter<T> underlyingFormatter;
public StaticNullableFormatter(IMessagePackFormatter<T> underlyingFormatter)
{
this.underlyingFormatter = underlyingFormatter;
}
public void Serialize(ref MessagePackWriter writer, T? value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
this.underlyingFormatter.Serialize(ref writer, value.Value, options);
}
}
public T? Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
return this.underlyingFormatter.Deserialize(ref reader, options);
}
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 88e906d65ee7d29d3ae1fb5865b8f6ab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,337 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Reflection;
namespace MessagePack.Formatters
{
public sealed class PrimitiveObjectFormatter : IMessagePackFormatter<object>
{
public static readonly IMessagePackFormatter<object> Instance = new PrimitiveObjectFormatter();
private static readonly Dictionary<Type, int> TypeToJumpCode = new Dictionary<Type, int>()
{
// When adding types whose size exceeds 32-bits, add support in MessagePackSecurity.GetHashCollisionResistantEqualityComparer<T>()
{ typeof(Boolean), 0 },
{ typeof(Char), 1 },
{ typeof(SByte), 2 },
{ typeof(Byte), 3 },
{ typeof(Int16), 4 },
{ typeof(UInt16), 5 },
{ typeof(Int32), 6 },
{ typeof(UInt32), 7 },
{ typeof(Int64), 8 },
{ typeof(UInt64), 9 },
{ typeof(Single), 10 },
{ typeof(Double), 11 },
{ typeof(DateTime), 12 },
{ typeof(string), 13 },
{ typeof(byte[]), 14 },
};
private PrimitiveObjectFormatter()
{
}
#if !UNITY_2018_3_OR_NEWER
public static bool IsSupportedType(Type type, TypeInfo typeInfo, object value)
{
if (value == null)
{
return true;
}
if (TypeToJumpCode.ContainsKey(type))
{
return true;
}
if (typeInfo.IsEnum)
{
return true;
}
if (value is System.Collections.IDictionary)
{
return true;
}
if (value is System.Collections.ICollection)
{
return true;
}
return false;
}
#endif
public void Serialize(ref MessagePackWriter writer, object value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
return;
}
Type t = value.GetType();
int code;
if (TypeToJumpCode.TryGetValue(t, out code))
{
switch (code)
{
case 0:
writer.Write((bool)value);
return;
case 1:
writer.Write((char)value);
return;
case 2:
writer.WriteInt8((sbyte)value);
return;
case 3:
writer.WriteUInt8((byte)value);
return;
case 4:
writer.WriteInt16((Int16)value);
return;
case 5:
writer.WriteUInt16((UInt16)value);
return;
case 6:
writer.WriteInt32((Int32)value);
return;
case 7:
writer.WriteUInt32((UInt32)value);
return;
case 8:
writer.WriteInt64((Int64)value);
return;
case 9:
writer.WriteUInt64((UInt64)value);
return;
case 10:
writer.Write((Single)value);
return;
case 11:
writer.Write((double)value);
return;
case 12:
writer.Write((DateTime)value);
return;
case 13:
writer.Write((string)value);
return;
case 14:
writer.Write((byte[])value);
return;
default:
throw new MessagePackSerializationException("Not supported primitive object resolver. type:" + t.Name);
}
}
else
{
#if UNITY_2018_3_OR_NEWER && !NETFX_CORE
if (t.IsEnum)
#else
if (t.GetTypeInfo().IsEnum)
#endif
{
Type underlyingType = Enum.GetUnderlyingType(t);
var code2 = TypeToJumpCode[underlyingType];
switch (code2)
{
case 2:
writer.WriteInt8((sbyte)value);
return;
case 3:
writer.WriteUInt8((byte)value);
return;
case 4:
writer.WriteInt16((Int16)value);
return;
case 5:
writer.WriteUInt16((UInt16)value);
return;
case 6:
writer.WriteInt32((Int32)value);
return;
case 7:
writer.WriteUInt32((UInt32)value);
return;
case 8:
writer.WriteInt64((Int64)value);
return;
case 9:
writer.WriteUInt64((UInt64)value);
return;
default:
break;
}
}
else if (value is System.Collections.IDictionary)
{
// check IDictionary first
var d = value as System.Collections.IDictionary;
writer.WriteMapHeader(d.Count);
foreach (System.Collections.DictionaryEntry item in d)
{
this.Serialize(ref writer, item.Key, options);
this.Serialize(ref writer, item.Value, options);
}
return;
}
else if (value is System.Collections.ICollection)
{
var c = value as System.Collections.ICollection;
writer.WriteArrayHeader(c.Count);
foreach (var item in c)
{
this.Serialize(ref writer, item, options);
}
return;
}
}
throw new MessagePackSerializationException("Not supported primitive object resolver. type:" + t.Name);
}
public object Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
MessagePackType type = reader.NextMessagePackType;
IFormatterResolver resolver = options.Resolver;
switch (type)
{
case MessagePackType.Integer:
var code = reader.NextCode;
if (code >= MessagePackCode.MinNegativeFixInt && code <= MessagePackCode.MaxNegativeFixInt)
{
return reader.ReadSByte();
}
else if (code >= MessagePackCode.MinFixInt && code <= MessagePackCode.MaxFixInt)
{
return reader.ReadByte();
}
else if (code == MessagePackCode.Int8)
{
return reader.ReadSByte();
}
else if (code == MessagePackCode.Int16)
{
return reader.ReadInt16();
}
else if (code == MessagePackCode.Int32)
{
return reader.ReadInt32();
}
else if (code == MessagePackCode.Int64)
{
return reader.ReadInt64();
}
else if (code == MessagePackCode.UInt8)
{
return reader.ReadByte();
}
else if (code == MessagePackCode.UInt16)
{
return reader.ReadUInt16();
}
else if (code == MessagePackCode.UInt32)
{
return reader.ReadUInt32();
}
else if (code == MessagePackCode.UInt64)
{
return reader.ReadUInt64();
}
throw new MessagePackSerializationException("Invalid primitive bytes.");
case MessagePackType.Boolean:
return reader.ReadBoolean();
case MessagePackType.Float:
if (reader.NextCode == MessagePackCode.Float32)
{
return reader.ReadSingle();
}
else
{
return reader.ReadDouble();
}
case MessagePackType.String:
return reader.ReadString();
case MessagePackType.Binary:
// We must copy the sequence returned by ReadBytes since the reader's sequence is only valid during deserialization.
return reader.ReadBytes()?.ToArray();
case MessagePackType.Extension:
ExtensionHeader ext = reader.ReadExtensionFormatHeader();
if (ext.TypeCode == ReservedMessagePackExtensionTypeCode.DateTime)
{
return reader.ReadDateTime(ext);
}
throw new MessagePackSerializationException("Invalid primitive bytes.");
case MessagePackType.Array:
{
var length = reader.ReadArrayHeader();
IMessagePackFormatter<object> objectFormatter = resolver.GetFormatter<object>();
var array = new object[length];
options.Security.DepthStep(ref reader);
try
{
for (int i = 0; i < length; i++)
{
array[i] = objectFormatter.Deserialize(ref reader, options);
}
}
finally
{
reader.Depth--;
}
return array;
}
case MessagePackType.Map:
{
var length = reader.ReadMapHeader();
IMessagePackFormatter<object> objectFormatter = resolver.GetFormatter<object>();
var hash = new Dictionary<object, object>(length, options.Security.GetEqualityComparer<object>());
options.Security.DepthStep(ref reader);
try
{
for (int i = 0; i < length; i++)
{
var key = objectFormatter.Deserialize(ref reader, options);
var value = objectFormatter.Deserialize(ref reader, options);
hash.Add(key, value);
}
}
finally
{
reader.Depth--;
}
return hash;
}
case MessagePackType.Nil:
reader.ReadNil();
return null;
default:
throw new MessagePackSerializationException("Invalid primitive bytes.");
}
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: d46d293dc804af1669409cc12690a3ad
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,599 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using MessagePack.Internal;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack.Formatters
{
// NET40 -> BigInteger, Complex, Tuple
// byte[] is special. represents bin type.
public sealed class ByteArrayFormatter : IMessagePackFormatter<byte[]>
{
public static readonly ByteArrayFormatter Instance = new ByteArrayFormatter();
private ByteArrayFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, byte[] value, MessagePackSerializerOptions options)
{
writer.Write(value);
}
public byte[] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
return reader.ReadBytes()?.ToArray();
}
}
public sealed class NullableStringFormatter : IMessagePackFormatter<String>
{
public static readonly NullableStringFormatter Instance = new NullableStringFormatter();
private NullableStringFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, string value, MessagePackSerializerOptions options)
{
writer.Write(value);
}
public string Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
return reader.ReadString();
}
}
public sealed class NullableStringArrayFormatter : IMessagePackFormatter<String[]>
{
public static readonly NullableStringArrayFormatter Instance = new NullableStringArrayFormatter();
private NullableStringArrayFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, String[] value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
writer.WriteArrayHeader(value.Length);
for (int i = 0; i < value.Length; i++)
{
writer.Write(value[i]);
}
}
}
public String[] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
var len = reader.ReadArrayHeader();
var array = new String[len];
for (int i = 0; i < array.Length; i++)
{
array[i] = reader.ReadString();
}
return array;
}
}
}
public sealed class DecimalFormatter : IMessagePackFormatter<Decimal>
{
public static readonly DecimalFormatter Instance = new DecimalFormatter();
private DecimalFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, decimal value, MessagePackSerializerOptions options)
{
var dest = writer.GetSpan(MessagePackRange.MaxFixStringLength);
if (System.Buffers.Text.Utf8Formatter.TryFormat(value, dest.Slice(1), out var written))
{
// write header
dest[0] = (byte)(MessagePackCode.MinFixStr | written);
writer.Advance(written + 1);
}
else
{
// reset writer's span previously acquired that does not use
writer.Advance(0);
writer.Write(value.ToString(CultureInfo.InvariantCulture));
}
}
public decimal Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (!(reader.ReadStringSequence() is ReadOnlySequence<byte> sequence))
{
throw new MessagePackSerializationException(string.Format("Unexpected msgpack code {0} ({1}) encountered.", MessagePackCode.Nil, MessagePackCode.ToFormatName(MessagePackCode.Nil)));
}
if (sequence.IsSingleSegment)
{
var span = sequence.First.Span;
if (System.Buffers.Text.Utf8Parser.TryParse(span, out decimal result, out var bytesConsumed))
{
if (span.Length != bytesConsumed)
{
throw new MessagePackSerializationException("Unexpected length of string.");
}
return result;
}
}
else
{
// sequence.Length is not free
var seqLen = (int)sequence.Length;
if (seqLen < 128)
{
Span<byte> span = stackalloc byte[seqLen];
sequence.CopyTo(span);
if (System.Buffers.Text.Utf8Parser.TryParse(span, out decimal result, out var bytesConsumed))
{
if (seqLen != bytesConsumed)
{
throw new MessagePackSerializationException("Unexpected length of string.");
}
return result;
}
}
else
{
var rentArray = ArrayPool<byte>.Shared.Rent(seqLen);
try
{
sequence.CopyTo(rentArray);
if (System.Buffers.Text.Utf8Parser.TryParse(rentArray.AsSpan(0, seqLen), out decimal result, out var bytesConsumed))
{
if (seqLen != bytesConsumed)
{
throw new MessagePackSerializationException("Unexpected length of string.");
}
return result;
}
}
finally
{
ArrayPool<byte>.Shared.Return(rentArray);
}
}
}
throw new MessagePackSerializationException("Can't parse to decimal, input string was not in a correct format.");
}
}
public sealed class TimeSpanFormatter : IMessagePackFormatter<TimeSpan>
{
public static readonly IMessagePackFormatter<TimeSpan> Instance = new TimeSpanFormatter();
private TimeSpanFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, TimeSpan value, MessagePackSerializerOptions options)
{
writer.Write(value.Ticks);
return;
}
public TimeSpan Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
return new TimeSpan(reader.ReadInt64());
}
}
public sealed class DateTimeOffsetFormatter : IMessagePackFormatter<DateTimeOffset>
{
public static readonly IMessagePackFormatter<DateTimeOffset> Instance = new DateTimeOffsetFormatter();
private DateTimeOffsetFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, DateTimeOffset value, MessagePackSerializerOptions options)
{
writer.WriteArrayHeader(2);
writer.Write(new DateTime(value.Ticks, DateTimeKind.Utc)); // current ticks as is
writer.Write((short)value.Offset.TotalMinutes); // offset is normalized in minutes
return;
}
public DateTimeOffset Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
var count = reader.ReadArrayHeader();
if (count != 2)
{
throw new MessagePackSerializationException("Invalid DateTimeOffset format.");
}
DateTime utc = reader.ReadDateTime();
var dtOffsetMinutes = reader.ReadInt16();
return new DateTimeOffset(utc.Ticks, TimeSpan.FromMinutes(dtOffsetMinutes));
}
}
public sealed class GuidFormatter : IMessagePackFormatter<Guid>
{
public static readonly IMessagePackFormatter<Guid> Instance = new GuidFormatter();
private GuidFormatter()
{
}
public unsafe void Serialize(ref MessagePackWriter writer, Guid value, MessagePackSerializerOptions options)
{
byte* pBytes = stackalloc byte[36];
Span<byte> bytes = new Span<byte>(pBytes, 36);
new GuidBits(ref value).Write(bytes);
writer.WriteString(bytes);
}
public Guid Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
ReadOnlySequence<byte> segment = reader.ReadStringSequence().Value;
if (segment.Length != 36)
{
throw new MessagePackSerializationException("Unexpected length of string.");
}
GuidBits result;
if (segment.IsSingleSegment)
{
result = new GuidBits(segment.First.Span);
}
else
{
Span<byte> bytes = stackalloc byte[36];
segment.CopyTo(bytes);
result = new GuidBits(bytes);
}
return result.Value;
}
}
public sealed class UriFormatter : IMessagePackFormatter<Uri>
{
public static readonly IMessagePackFormatter<Uri> Instance = new UriFormatter();
private UriFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, Uri value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
writer.Write(value.ToString());
}
}
public Uri Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
return new Uri(reader.ReadString(), UriKind.RelativeOrAbsolute);
}
}
}
public sealed class VersionFormatter : IMessagePackFormatter<Version>
{
public static readonly IMessagePackFormatter<Version> Instance = new VersionFormatter();
private VersionFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, Version value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
writer.Write(value.ToString());
}
}
public Version Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
return new Version(reader.ReadString());
}
}
}
public sealed class KeyValuePairFormatter<TKey, TValue> : IMessagePackFormatter<KeyValuePair<TKey, TValue>>
{
public void Serialize(ref MessagePackWriter writer, KeyValuePair<TKey, TValue> value, MessagePackSerializerOptions options)
{
writer.WriteArrayHeader(2);
IFormatterResolver resolver = options.Resolver;
resolver.GetFormatterWithVerify<TKey>().Serialize(ref writer, value.Key, options);
resolver.GetFormatterWithVerify<TValue>().Serialize(ref writer, value.Value, options);
return;
}
public KeyValuePair<TKey, TValue> Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
var count = reader.ReadArrayHeader();
if (count != 2)
{
throw new MessagePackSerializationException("Invalid KeyValuePair format.");
}
IFormatterResolver resolver = options.Resolver;
options.Security.DepthStep(ref reader);
try
{
TKey key = resolver.GetFormatterWithVerify<TKey>().Deserialize(ref reader, options);
TValue value = resolver.GetFormatterWithVerify<TValue>().Deserialize(ref reader, options);
return new KeyValuePair<TKey, TValue>(key, value);
}
finally
{
reader.Depth--;
}
}
}
public sealed class StringBuilderFormatter : IMessagePackFormatter<StringBuilder>
{
public static readonly IMessagePackFormatter<StringBuilder> Instance = new StringBuilderFormatter();
private StringBuilderFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, StringBuilder value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
writer.Write(value.ToString());
}
}
public StringBuilder Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
return new StringBuilder(reader.ReadString());
}
}
}
public sealed class BitArrayFormatter : IMessagePackFormatter<BitArray>
{
public static readonly IMessagePackFormatter<BitArray> Instance = new BitArrayFormatter();
private BitArrayFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, BitArray value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
var len = value.Length;
writer.WriteArrayHeader(len);
for (int i = 0; i < len; i++)
{
writer.Write(value.Get(i));
}
return;
}
}
public BitArray Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
var len = reader.ReadArrayHeader();
var array = new BitArray(len);
for (int i = 0; i < len; i++)
{
array[i] = reader.ReadBoolean();
}
return array;
}
}
}
public sealed class BigIntegerFormatter : IMessagePackFormatter<System.Numerics.BigInteger>
{
public static readonly IMessagePackFormatter<System.Numerics.BigInteger> Instance = new BigIntegerFormatter();
private BigIntegerFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, System.Numerics.BigInteger value, MessagePackSerializerOptions options)
{
#if NETCOREAPP2_1
if (!writer.OldSpec)
{
// try to get bin8 buffer.
var span = writer.GetSpan(byte.MaxValue);
if (value.TryWriteBytes(span.Slice(2), out var written))
{
span[0] = MessagePackCode.Bin8;
span[1] = (byte)written;
writer.Advance(written + 2);
return;
}
else
{
// reset writer's span previously acquired that does not use
writer.Advance(0);
}
}
#endif
writer.Write(value.ToByteArray());
return;
}
public System.Numerics.BigInteger Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
ReadOnlySequence<byte> bytes = reader.ReadBytes().Value;
#if NETCOREAPP2_1
if (bytes.IsSingleSegment)
{
return new System.Numerics.BigInteger(bytes.First.Span);
}
else
{
byte[] bytesArray = ArrayPool<byte>.Shared.Rent((int)bytes.Length);
try
{
bytes.CopyTo(bytesArray);
return new System.Numerics.BigInteger(bytesArray.AsSpan(0, (int)bytes.Length));
}
finally
{
ArrayPool<byte>.Shared.Return(bytesArray);
}
}
#else
return new System.Numerics.BigInteger(bytes.ToArray());
#endif
}
}
public sealed class ComplexFormatter : IMessagePackFormatter<System.Numerics.Complex>
{
public static readonly IMessagePackFormatter<System.Numerics.Complex> Instance = new ComplexFormatter();
private ComplexFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, System.Numerics.Complex value, MessagePackSerializerOptions options)
{
writer.WriteArrayHeader(2);
writer.Write(value.Real);
writer.Write(value.Imaginary);
return;
}
public System.Numerics.Complex Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
var count = reader.ReadArrayHeader();
if (count != 2)
{
throw new MessagePackSerializationException("Invalid Complex format.");
}
var real = reader.ReadDouble();
var imaginary = reader.ReadDouble();
return new System.Numerics.Complex(real, imaginary);
}
}
public sealed class LazyFormatter<T> : IMessagePackFormatter<Lazy<T>>
{
public void Serialize(ref MessagePackWriter writer, Lazy<T> value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
IFormatterResolver resolver = options.Resolver;
resolver.GetFormatterWithVerify<T>().Serialize(ref writer, value.Value, options);
}
}
public Lazy<T> Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
options.Security.DepthStep(ref reader);
try
{
// deserialize immediately(no delay, because capture byte[] causes memory leak)
IFormatterResolver resolver = options.Resolver;
T v = resolver.GetFormatterWithVerify<T>().Deserialize(ref reader, options);
return new Lazy<T>(() => v);
}
finally
{
reader.Depth--;
}
}
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 6dc8f5f9191421c21bd1ba87f5a70d27
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,309 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using MessagePack.Internal;
namespace MessagePack.Formatters
{
/// <summary>
/// For `object` field that holds derived from `object` value, ex: var arr = new object[] { 1, "a", new Model() };.
/// </summary>
public sealed class TypelessFormatter : IMessagePackFormatter<object>
{
private delegate void SerializeMethod(object dynamicContractlessFormatter, ref MessagePackWriter writer, object value, MessagePackSerializerOptions options);
private delegate object DeserializeMethod(object dynamicContractlessFormatter, ref MessagePackReader reader, MessagePackSerializerOptions options);
/// <summary>
/// The singleton instance that can be used.
/// </summary>
public static readonly IMessagePackFormatter<object> Instance = new TypelessFormatter();
private readonly ThreadsafeTypeKeyHashTable<SerializeMethod> serializers = new ThreadsafeTypeKeyHashTable<SerializeMethod>();
private readonly ThreadsafeTypeKeyHashTable<DeserializeMethod> deserializers = new ThreadsafeTypeKeyHashTable<DeserializeMethod>();
private readonly ThreadsafeTypeKeyHashTable<byte[]> fullTypeNameCache = new ThreadsafeTypeKeyHashTable<byte[]>();
private readonly ThreadsafeTypeKeyHashTable<byte[]> shortenedTypeNameCache = new ThreadsafeTypeKeyHashTable<byte[]>();
private readonly AsymmetricKeyHashTable<byte[], ArraySegment<byte>, Type> typeCache = new AsymmetricKeyHashTable<byte[], ArraySegment<byte>, Type>(new StringArraySegmentByteAscymmetricEqualityComparer());
private static readonly HashSet<Type> UseBuiltinTypes = new HashSet<Type>
{
typeof(Boolean),
////typeof(Char),
typeof(SByte),
typeof(Byte),
typeof(Int16),
typeof(UInt16),
typeof(Int32),
typeof(UInt32),
typeof(Int64),
typeof(UInt64),
typeof(Single),
typeof(Double),
typeof(string),
typeof(byte[]),
// array should save their types.
////typeof(Boolean[]),
////typeof(Char[]),
////typeof(SByte[]),
////typeof(Int16[]),
////typeof(UInt16[]),
////typeof(Int32[]),
////typeof(UInt32[]),
////typeof(Int64[]),
////typeof(UInt64[]),
////typeof(Single[]),
////typeof(Double[]),
////typeof(string[]),
typeof(Boolean?),
////typeof(Char?),
typeof(SByte?),
typeof(Byte?),
typeof(Int16?),
typeof(UInt16?),
typeof(Int32?),
typeof(UInt32?),
typeof(Int64?),
typeof(UInt64?),
typeof(Single?),
typeof(Double?),
};
//ForceSizePrimitiveObjectResolver.Instance,
//ContractlessStandardResolverAllowPrivate.Instance);
// mscorlib or System.Private.CoreLib
private static readonly bool IsMscorlib = typeof(int).AssemblyQualifiedName.Contains("mscorlib");
public TypelessFormatter()
{
this.serializers.TryAdd(typeof(object), _ => (object p1, ref MessagePackWriter p2, object p3, MessagePackSerializerOptions p4) => { });
this.deserializers.TryAdd(typeof(object), _ => (object p1, ref MessagePackReader p2, MessagePackSerializerOptions p3) => new object());
}
private string BuildTypeName(Type type, MessagePackSerializerOptions options)
{
if (options.OmitAssemblyVersion)
{
string full = type.AssemblyQualifiedName;
var shortened = MessagePackSerializerOptions.AssemblyNameVersionSelectorRegex.Replace(full, string.Empty);
if (Type.GetType(shortened, false) == null)
{
// if type cannot be found with shortened name - use full name
shortened = full;
}
return shortened;
}
else
{
return type.AssemblyQualifiedName;
}
}
public void Serialize(ref MessagePackWriter writer, object value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
return;
}
Type type = value.GetType();
byte[] typeName;
var typeNameCache = options.OmitAssemblyVersion ? this.shortenedTypeNameCache : this.fullTypeNameCache;
if (!typeNameCache.TryGetValue(type, out typeName))
{
TypeInfo ti = type.GetTypeInfo();
if (ti.IsAnonymous() || UseBuiltinTypes.Contains(type))
{
typeName = null;
}
else
{
typeName = StringEncoding.UTF8.GetBytes(this.BuildTypeName(type, options));
}
typeNameCache.TryAdd(type, typeName);
}
if (typeName == null)
{
DynamicObjectTypeFallbackFormatter.Instance.Serialize(ref writer, value, options);
return;
}
var formatter = options.Resolver.GetFormatterDynamicWithVerify(type);
// don't use GetOrAdd for avoid closure capture.
if (!this.serializers.TryGetValue(type, out SerializeMethod serializeMethod))
{
// double check locking...
lock (this.serializers)
{
if (!this.serializers.TryGetValue(type, out serializeMethod))
{
TypeInfo ti = type.GetTypeInfo();
Type formatterType = typeof(IMessagePackFormatter<>).MakeGenericType(type);
ParameterExpression param0 = Expression.Parameter(typeof(object), "formatter");
ParameterExpression param1 = Expression.Parameter(typeof(MessagePackWriter).MakeByRefType(), "writer");
ParameterExpression param2 = Expression.Parameter(typeof(object), "value");
ParameterExpression param3 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options");
MethodInfo serializeMethodInfo = formatterType.GetRuntimeMethod("Serialize", new[] { typeof(MessagePackWriter).MakeByRefType(), type, typeof(MessagePackSerializerOptions) });
MethodCallExpression body = Expression.Call(
Expression.Convert(param0, formatterType),
serializeMethodInfo,
param1,
ti.IsValueType ? Expression.Unbox(param2, type) : Expression.Convert(param2, type),
param3);
serializeMethod = Expression.Lambda<SerializeMethod>(body, param0, param1, param2, param3).Compile();
this.serializers.TryAdd(type, serializeMethod);
}
}
}
// mark will be written at the end, when size is known
using (var scratchRental = SequencePool.Shared.Rent())
{
MessagePackWriter scratchWriter = writer.Clone(scratchRental.Value);
scratchWriter.WriteString(typeName);
serializeMethod(formatter, ref scratchWriter, value, options);
scratchWriter.Flush();
// mark as extension with code 100
writer.WriteExtensionFormat(new ExtensionResult((sbyte)ThisLibraryExtensionTypeCodes.TypelessFormatter, scratchRental.Value));
}
}
public object Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
if (reader.NextMessagePackType == MessagePackType.Extension)
{
ExtensionHeader ext = reader.ReadExtensionFormatHeader();
if (ext.TypeCode == ThisLibraryExtensionTypeCodes.TypelessFormatter)
{
// it has type name serialized
ReadOnlySequence<byte> typeName = reader.ReadStringSequence().Value;
ArraySegment<byte> typeNameArraySegment;
byte[] rented = null;
if (!typeName.IsSingleSegment || !MemoryMarshal.TryGetArray(typeName.First, out typeNameArraySegment))
{
rented = ArrayPool<byte>.Shared.Rent((int)typeName.Length);
typeName.CopyTo(rented);
typeNameArraySegment = new ArraySegment<byte>(rented, 0, (int)typeName.Length);
}
var result = this.DeserializeByTypeName(typeNameArraySegment, ref reader, options);
if (rented != null)
{
ArrayPool<byte>.Shared.Return(rented);
}
return result;
}
}
// fallback
return DynamicObjectTypeFallbackFormatter.Instance.Deserialize(ref reader, options);
}
/// <summary>
/// Does not support deserializing of anonymous types
/// Type should be covered by preceeding resolvers in complex/standard resolver.
/// </summary>
private object DeserializeByTypeName(ArraySegment<byte> typeName, ref MessagePackReader byteSequence, MessagePackSerializerOptions options)
{
// try get type with assembly name, throw if not found
Type type;
if (!this.typeCache.TryGetValue(typeName, out type))
{
var buffer = new byte[typeName.Count];
Buffer.BlockCopy(typeName.Array, typeName.Offset, buffer, 0, buffer.Length);
var str = StringEncoding.UTF8.GetString(buffer);
type = options.LoadType(str);
if (type == null)
{
if (IsMscorlib && str.Contains("System.Private.CoreLib"))
{
str = str.Replace("System.Private.CoreLib", "mscorlib");
type = Type.GetType(str, true); // throw
}
else if (!IsMscorlib && str.Contains("mscorlib"))
{
str = str.Replace("mscorlib", "System.Private.CoreLib");
type = Type.GetType(str, true); // throw
}
else
{
type = Type.GetType(str, true); // re-throw
}
}
this.typeCache.TryAdd(buffer, type);
}
options.ThrowIfDeserializingTypeIsDisallowed(type);
var formatter = options.Resolver.GetFormatterDynamicWithVerify(type);
if (!this.deserializers.TryGetValue(type, out DeserializeMethod deserializeMethod))
{
lock (this.deserializers)
{
if (!this.deserializers.TryGetValue(type, out deserializeMethod))
{
TypeInfo ti = type.GetTypeInfo();
Type formatterType = typeof(IMessagePackFormatter<>).MakeGenericType(type);
ParameterExpression param0 = Expression.Parameter(typeof(object), "formatter");
ParameterExpression param1 = Expression.Parameter(typeof(MessagePackReader).MakeByRefType(), "reader");
ParameterExpression param2 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options");
MethodInfo deserializeMethodInfo = formatterType.GetRuntimeMethod("Deserialize", new[] { typeof(MessagePackReader).MakeByRefType(), typeof(MessagePackSerializerOptions) });
MethodCallExpression deserialize = Expression.Call(
Expression.Convert(param0, formatterType),
deserializeMethodInfo,
param1,
param2);
Expression body = deserialize;
if (ti.IsValueType)
{
body = Expression.Convert(deserialize, typeof(object));
}
deserializeMethod = Expression.Lambda<DeserializeMethod>(body, param0, param1, param2).Compile();
this.deserializers.TryAdd(type, deserializeMethod);
}
}
}
return deserializeMethod(formatter, ref byteSequence, options);
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: fe17a811684aa2fa786684f83f7fbbe7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,100 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Buffers;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack.Formatters
{
public sealed class NativeGuidFormatter : IMessagePackFormatter<Guid>
{
/// <summary>
/// Unsafe binary Guid formatter. this is only allowed on LittleEndian environment.
/// </summary>
public static readonly IMessagePackFormatter<Guid> Instance = new NativeGuidFormatter();
private NativeGuidFormatter()
{
}
/* Guid's underlying _a,...,_k field is sequential and same layout as .NET Framework and Mono(Unity).
* But target machines must be same endian so restrict only for little endian. */
public unsafe void Serialize(ref MessagePackWriter writer, Guid value, MessagePackSerializerOptions options)
{
if (!BitConverter.IsLittleEndian)
{
throw new InvalidOperationException("NativeGuidFormatter only allows on little endian env.");
}
var valueSpan = new ReadOnlySpan<byte>(&value, sizeof(Guid));
writer.Write(valueSpan);
}
public unsafe Guid Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (!BitConverter.IsLittleEndian)
{
throw new InvalidOperationException("NativeGuidFormatter only allows on little endian env.");
}
ReadOnlySequence<byte> valueSequence = reader.ReadBytes().Value;
if (valueSequence.Length != sizeof(Guid))
{
throw new MessagePackSerializationException("Invalid Guid Size.");
}
Guid result;
var resultSpan = new Span<byte>(&result, sizeof(Guid));
valueSequence.CopyTo(resultSpan);
return result;
}
}
public sealed class NativeDecimalFormatter : IMessagePackFormatter<Decimal>
{
/// <summary>
/// Unsafe binary Decimal formatter. this is only allows on LittleEndian environment.
/// </summary>
public static readonly IMessagePackFormatter<Decimal> Instance = new NativeDecimalFormatter();
private NativeDecimalFormatter()
{
}
/* decimal underlying "flags, hi, lo, mid" fields are sequential and same layuout with .NET Framework and Mono(Unity)
* But target machines must be same endian so restrict only for little endian. */
public unsafe void Serialize(ref MessagePackWriter writer, Decimal value, MessagePackSerializerOptions options)
{
if (!BitConverter.IsLittleEndian)
{
throw new InvalidOperationException("NativeDecimalFormatter only allows on little endian env.");
}
var valueSpan = new ReadOnlySpan<byte>(&value, sizeof(Decimal));
writer.Write(valueSpan);
}
public unsafe Decimal Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (!BitConverter.IsLittleEndian)
{
throw new InvalidOperationException("NativeDecimalFormatter only allows on little endian env.");
}
ReadOnlySequence<byte> valueSequence = reader.ReadBytes().Value;
if (valueSequence.Length != sizeof(decimal))
{
throw new MessagePackSerializationException("Invalid decimal Size.");
}
decimal result;
var resultSpan = new Span<byte>(&result, sizeof(decimal));
valueSequence.CopyTo(resultSpan);
return result;
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 2c4fcfc3f496806c7915aba0cdb3f1ba
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,481 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// <auto-generated />
/*
The xxHash32 implementation is based on the code published by Yann Collet:
https://raw.githubusercontent.com/Cyan4973/xxHash/5c174cfa4e45a42f94082dc0d4539b39696afea1/xxhash.c
xxHash - Fast Hash algorithm
Copyright (C) 2012-2016, Yann Collet
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- xxHash homepage: http://www.xxhash.com
- xxHash source repository : https://github.com/Cyan4973/xxHash
*/
#if !NETCOREAPP
using System.Collections.Generic;
using System.ComponentModel;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
namespace System
{
// xxHash32 is used for the hash code.
// https://github.com/Cyan4973/xxHash
internal struct HashCode
{
private static readonly uint s_seed = GenerateGlobalSeed();
private const uint Prime1 = 2654435761U;
private const uint Prime2 = 2246822519U;
private const uint Prime3 = 3266489917U;
private const uint Prime4 = 668265263U;
private const uint Prime5 = 374761393U;
private uint _v1, _v2, _v3, _v4;
private uint _queue1, _queue2, _queue3;
private uint _length;
private static uint GenerateGlobalSeed()
{
var bytes = new byte[4];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(bytes);
}
return BitConverter.ToUInt32(bytes, 0);
}
public static int Combine<T1>(T1 value1)
{
unchecked
{
// Provide a way of diffusing bits from something with a limited
// input hash space. For example, many enums only have a few
// possible hashes, only using the bottom few bits of the code. Some
// collections are built on the assumption that hashes are spread
// over a larger space, so diffusing the bits may help the
// collection work more efficiently.
uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
uint hash = MixEmptyState();
hash += 4;
hash = QueueRound(hash, hc1);
hash = MixFinal(hash);
return (int)hash;
}
}
public static int Combine<T1, T2>(T1 value1, T2 value2)
{
unchecked
{
uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
uint hash = MixEmptyState();
hash += 8;
hash = QueueRound(hash, hc1);
hash = QueueRound(hash, hc2);
hash = MixFinal(hash);
return (int)hash;
}
}
public static int Combine<T1, T2, T3>(T1 value1, T2 value2, T3 value3)
{
unchecked
{
uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
uint hash = MixEmptyState();
hash += 12;
hash = QueueRound(hash, hc1);
hash = QueueRound(hash, hc2);
hash = QueueRound(hash, hc3);
hash = MixFinal(hash);
return (int)hash;
}
}
public static int Combine<T1, T2, T3, T4>(T1 value1, T2 value2, T3 value3, T4 value4)
{
unchecked
{
uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
v1 = Round(v1, hc1);
v2 = Round(v2, hc2);
v3 = Round(v3, hc3);
v4 = Round(v4, hc4);
uint hash = MixState(v1, v2, v3, v4);
hash += 16;
hash = MixFinal(hash);
return (int)hash;
}
}
public static int Combine<T1, T2, T3, T4, T5>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5)
{
unchecked
{
uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
uint hc5 = (uint)(value5?.GetHashCode() ?? 0);
Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
v1 = Round(v1, hc1);
v2 = Round(v2, hc2);
v3 = Round(v3, hc3);
v4 = Round(v4, hc4);
uint hash = MixState(v1, v2, v3, v4);
hash += 20;
hash = QueueRound(hash, hc5);
hash = MixFinal(hash);
return (int)hash;
}
}
public static int Combine<T1, T2, T3, T4, T5, T6>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6)
{
unchecked
{
uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
uint hc5 = (uint)(value5?.GetHashCode() ?? 0);
uint hc6 = (uint)(value6?.GetHashCode() ?? 0);
Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
v1 = Round(v1, hc1);
v2 = Round(v2, hc2);
v3 = Round(v3, hc3);
v4 = Round(v4, hc4);
uint hash = MixState(v1, v2, v3, v4);
hash += 24;
hash = QueueRound(hash, hc5);
hash = QueueRound(hash, hc6);
hash = MixFinal(hash);
return (int)hash;
}
}
public static int Combine<T1, T2, T3, T4, T5, T6, T7>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7)
{
unchecked
{
uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
uint hc5 = (uint)(value5?.GetHashCode() ?? 0);
uint hc6 = (uint)(value6?.GetHashCode() ?? 0);
uint hc7 = (uint)(value7?.GetHashCode() ?? 0);
Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
v1 = Round(v1, hc1);
v2 = Round(v2, hc2);
v3 = Round(v3, hc3);
v4 = Round(v4, hc4);
uint hash = MixState(v1, v2, v3, v4);
hash += 28;
hash = QueueRound(hash, hc5);
hash = QueueRound(hash, hc6);
hash = QueueRound(hash, hc7);
hash = MixFinal(hash);
return (int)hash;
}
}
public static int Combine<T1, T2, T3, T4, T5, T6, T7, T8>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8)
{
unchecked
{
uint hc1 = (uint)(value1?.GetHashCode() ?? 0);
uint hc2 = (uint)(value2?.GetHashCode() ?? 0);
uint hc3 = (uint)(value3?.GetHashCode() ?? 0);
uint hc4 = (uint)(value4?.GetHashCode() ?? 0);
uint hc5 = (uint)(value5?.GetHashCode() ?? 0);
uint hc6 = (uint)(value6?.GetHashCode() ?? 0);
uint hc7 = (uint)(value7?.GetHashCode() ?? 0);
uint hc8 = (uint)(value8?.GetHashCode() ?? 0);
Initialize(out uint v1, out uint v2, out uint v3, out uint v4);
v1 = Round(v1, hc1);
v2 = Round(v2, hc2);
v3 = Round(v3, hc3);
v4 = Round(v4, hc4);
v1 = Round(v1, hc5);
v2 = Round(v2, hc6);
v3 = Round(v3, hc7);
v4 = Round(v4, hc8);
uint hash = MixState(v1, v2, v3, v4);
hash += 32;
hash = MixFinal(hash);
return (int)hash;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void Initialize(out uint v1, out uint v2, out uint v3, out uint v4)
{
unchecked
{
v1 = s_seed + Prime1 + Prime2;
v2 = s_seed + Prime2;
v3 = s_seed;
v4 = s_seed - Prime1;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Round(uint hash, uint input)
{
unchecked
{
return BitOperations.RotateLeft(hash + input * Prime2, 13) * Prime1;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint QueueRound(uint hash, uint queuedValue)
{
unchecked
{
return BitOperations.RotateLeft(hash + queuedValue * Prime3, 17) * Prime4;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint MixState(uint v1, uint v2, uint v3, uint v4)
{
unchecked
{
return BitOperations.RotateLeft(v1, 1) + BitOperations.RotateLeft(v2, 7) + BitOperations.RotateLeft(v3, 12) + BitOperations.RotateLeft(v4, 18);
}
}
private static uint MixEmptyState()
{
unchecked
{
return s_seed + Prime5;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint MixFinal(uint hash)
{
unchecked
{
hash ^= hash >> 15;
hash *= Prime2;
hash ^= hash >> 13;
hash *= Prime3;
hash ^= hash >> 16;
return hash;
}
}
public void Add<T>(T value)
{
Add(value?.GetHashCode() ?? 0);
}
public void Add<T>(T value, IEqualityComparer<T> comparer)
{
Add(comparer != null ? comparer.GetHashCode(value) : (value?.GetHashCode() ?? 0));
}
private void Add(int value)
{
unchecked
{
// The original xxHash works as follows:
// 0. Initialize immediately. We can't do this in a struct (no
// default ctor).
// 1. Accumulate blocks of length 16 (4 uints) into 4 accumulators.
// 2. Accumulate remaining blocks of length 4 (1 uint) into the
// hash.
// 3. Accumulate remaining blocks of length 1 into the hash.
// There is no need for #3 as this type only accepts ints. _queue1,
// _queue2 and _queue3 are basically a buffer so that when
// ToHashCode is called we can execute #2 correctly.
// We need to initialize the xxHash32 state (_v1 to _v4) lazily (see
// #0) nd the last place that can be done if you look at the
// original code is just before the first block of 16 bytes is mixed
// in. The xxHash32 state is never used for streams containing fewer
// than 16 bytes.
// To see what's really going on here, have a look at the Combine
// methods.
uint val = (uint)value;
// Storing the value of _length locally shaves of quite a few bytes
// in the resulting machine code.
uint previousLength = _length++;
uint position = previousLength % 4;
// Switch can't be inlined.
if (position == 0)
_queue1 = val;
else if (position == 1)
_queue2 = val;
else if (position == 2)
_queue3 = val;
else // position == 3
{
if (previousLength == 3)
Initialize(out _v1, out _v2, out _v3, out _v4);
_v1 = Round(_v1, _queue1);
_v2 = Round(_v2, _queue2);
_v3 = Round(_v3, _queue3);
_v4 = Round(_v4, val);
}
}
}
public int ToHashCode()
{
unchecked
{
// Storing the value of _length locally shaves of quite a few bytes
// in the resulting machine code.
uint length = _length;
// position refers to the *next* queue position in this method, so
// position == 1 means that _queue1 is populated; _queue2 would have
// been populated on the next call to Add.
uint position = length % 4;
// If the length is less than 4, _v1 to _v4 don't contain anything
// yet. xxHash32 treats this differently.
uint hash = length < 4 ? MixEmptyState() : MixState(_v1, _v2, _v3, _v4);
// _length is incremented once per Add(Int32) and is therefore 4
// times too small (xxHash length is in bytes, not ints).
hash += length * 4;
// Mix what remains in the queue
// Switch can't be inlined right now, so use as few branches as
// possible by manually excluding impossible scenarios (position > 1
// is always false if position is not > 0).
if (position > 0)
{
hash = QueueRound(hash, _queue1);
if (position > 1)
{
hash = QueueRound(hash, _queue2);
if (position > 2)
hash = QueueRound(hash, _queue3);
}
}
hash = MixFinal(hash);
return (int)hash;
}
}
#pragma warning disable 0809
// Obsolete member 'memberA' overrides non-obsolete member 'memberB'.
// Disallowing GetHashCode and Equals is by design
// * We decided to not override GetHashCode() to produce the hash code
// as this would be weird, both naming-wise as well as from a
// behavioral standpoint (GetHashCode() should return the object's
// hash code, not the one being computed).
// * Even though ToHashCode() can be called safely multiple times on
// this implementation, it is not part of the contract. If the
// implementation has to change in the future we don't want to worry
// about people who might have incorrectly used this type.
[Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes. Use ToHashCode to retrieve the computed hash code.", error: true)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => throw new NotSupportedException();
[Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes.", error: true)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object obj) => throw new NotSupportedException();
#pragma warning restore 0809
}
}
#endif

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 9909e9074ddc955f18803bd2037102f7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,104 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using MessagePack.Formatters;
namespace MessagePack
{
/// <summary>
/// Allows querying for a formatter for serializing or deserializing a particular <see cref="Type" />.
/// </summary>
public interface IFormatterResolver
{
/// <summary>
/// Gets an <see cref="IMessagePackFormatter{T}"/> instance that can serialize or deserialize some type <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The type of value to be serialized or deserialized.</typeparam>
/// <returns>A formatter, if this resolver supplies one for type <typeparamref name="T"/>; otherwise <c>null</c>.</returns>
IMessagePackFormatter<T> GetFormatter<T>();
}
public static class FormatterResolverExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IMessagePackFormatter<T> GetFormatterWithVerify<T>(this IFormatterResolver resolver)
{
if (resolver is null)
{
throw new ArgumentNullException(nameof(resolver));
}
IMessagePackFormatter<T> formatter;
try
{
formatter = resolver.GetFormatter<T>();
}
catch (TypeInitializationException ex)
{
// The fact that we're using static constructors to initialize this is an internal detail.
// Rethrow the inner exception if there is one.
// Do it carefully so as to not stomp on the original callstack.
Throw(ex);
return default; // not reachable
}
if (formatter == null)
{
Throw(typeof(T), resolver);
}
return formatter;
}
private static void Throw(TypeInitializationException ex)
{
ExceptionDispatchInfo.Capture(ex.InnerException ?? ex).Throw();
}
private static void Throw(Type t, IFormatterResolver resolver)
{
throw new FormatterNotRegisteredException(t.FullName + " is not registered in resolver: " + resolver.GetType());
}
public static object GetFormatterDynamic(this IFormatterResolver resolver, Type type)
{
if (resolver is null)
{
throw new ArgumentNullException(nameof(resolver));
}
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
MethodInfo methodInfo = typeof(IFormatterResolver).GetRuntimeMethod(nameof(IFormatterResolver.GetFormatter), Type.EmptyTypes);
var formatter = methodInfo.MakeGenericMethod(type).Invoke(resolver, null);
return formatter;
}
internal static object GetFormatterDynamicWithVerify(this IFormatterResolver resolver, Type type)
{
object result = GetFormatterDynamic(resolver, type);
if (result == null)
{
Throw(type, resolver);
}
return result;
}
}
public class FormatterNotRegisteredException : MessagePackSerializationException
{
public FormatterNotRegisteredException(string message)
: base(message)
{
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 51a5ebbfbdf12b0cc80f0f57550f61a0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 7303cf02620047543873c4663322e112
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,302 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack.Internal
{
/* Safe for multiple-read, single-write.
* Add and Get Key is asymmetric. */
internal interface IAsymmetricEqualityComparer<TKey1, TKey2>
{
int GetHashCode(TKey1 key1);
int GetHashCode(TKey2 key2);
bool Equals(TKey1 x, TKey1 y); // when used rehash
bool Equals(TKey1 x, TKey2 y); // when used get
}
internal class StringArraySegmentByteAscymmetricEqualityComparer : IAsymmetricEqualityComparer<byte[], ArraySegment<byte>>
{
private static readonly bool Is32Bit = IntPtr.Size == 4;
public bool Equals(byte[] x, byte[] y)
{
if (x.Length != y.Length)
{
return false;
}
for (int i = 0; i < x.Length; i++)
{
if (x[i] != y[i])
{
return false;
}
}
return true;
}
public bool Equals(byte[] x, ArraySegment<byte> y)
{
return x.AsSpan().SequenceEqual(y);
}
public int GetHashCode(byte[] key1)
{
return this.GetHashCode(new ArraySegment<byte>(key1, 0, key1.Length));
}
public int GetHashCode(ArraySegment<byte> key2)
{
unchecked
{
if (Is32Bit)
{
return (int)FarmHash.Hash32(key2);
}
else
{
return (int)FarmHash.Hash64(key2);
}
}
}
}
internal sealed class AsymmetricKeyHashTable<TKey1, TKey2, TValue>
{
private Entry[] buckets;
private int size; // only use in writer lock
private readonly object writerLock = new object();
private readonly float loadFactor;
private readonly IAsymmetricEqualityComparer<TKey1, TKey2> comparer;
public AsymmetricKeyHashTable(IAsymmetricEqualityComparer<TKey1, TKey2> comparer)
: this(4, 0.72f, comparer)
{
}
public AsymmetricKeyHashTable(int capacity, float loadFactor, IAsymmetricEqualityComparer<TKey1, TKey2> comparer)
{
var tableSize = CalculateCapacity(capacity, loadFactor);
this.buckets = new Entry[tableSize];
this.loadFactor = loadFactor;
this.comparer = comparer;
}
public TValue AddOrGet(TKey1 key1, Func<TKey1, TValue> valueFactory)
{
TValue v;
this.TryAddInternal(key1, valueFactory, out v);
return v;
}
public bool TryAdd(TKey1 key, TValue value)
{
return this.TryAdd(key, _ => value); // closure capture
}
public bool TryAdd(TKey1 key, Func<TKey1, TValue> valueFactory)
{
return this.TryAddInternal(key, valueFactory, out TValue _);
}
private bool TryAddInternal(TKey1 key, Func<TKey1, TValue> valueFactory, out TValue resultingValue)
{
lock (this.writerLock)
{
var nextCapacity = CalculateCapacity(this.size + 1, this.loadFactor);
if (this.buckets.Length < nextCapacity)
{
// rehash
var nextBucket = new Entry[nextCapacity];
for (int i = 0; i < this.buckets.Length; i++)
{
Entry e = this.buckets[i];
while (e != null)
{
var newEntry = new Entry { Key = e.Key, Value = e.Value, Hash = e.Hash };
this.AddToBuckets(nextBucket, key, newEntry, null, out resultingValue);
e = e.Next;
}
}
// add entry(if failed to add, only do resize)
var successAdd = this.AddToBuckets(nextBucket, key, null, valueFactory, out resultingValue);
// replace field(threadsafe for read)
VolatileWrite(ref this.buckets, nextBucket);
if (successAdd)
{
this.size++;
}
return successAdd;
}
else
{
// add entry(insert last is thread safe for read)
var successAdd = this.AddToBuckets(this.buckets, key, null, valueFactory, out resultingValue);
if (successAdd)
{
this.size++;
}
return successAdd;
}
}
}
private bool AddToBuckets(Entry[] buckets, TKey1 newKey, Entry newEntryOrNull, Func<TKey1, TValue> valueFactory, out TValue resultingValue)
{
var h = (newEntryOrNull != null) ? newEntryOrNull.Hash : this.comparer.GetHashCode(newKey);
if (buckets[h & (buckets.Length - 1)] == null)
{
if (newEntryOrNull != null)
{
resultingValue = newEntryOrNull.Value;
VolatileWrite(ref buckets[h & (buckets.Length - 1)], newEntryOrNull);
}
else
{
resultingValue = valueFactory(newKey);
VolatileWrite(ref buckets[h & (buckets.Length - 1)], new Entry { Key = newKey, Value = resultingValue, Hash = h });
}
}
else
{
Entry searchLastEntry = buckets[h & (buckets.Length - 1)];
while (true)
{
if (this.comparer.Equals(searchLastEntry.Key, newKey))
{
resultingValue = searchLastEntry.Value;
return false;
}
if (searchLastEntry.Next == null)
{
if (newEntryOrNull != null)
{
resultingValue = newEntryOrNull.Value;
VolatileWrite(ref searchLastEntry.Next, newEntryOrNull);
}
else
{
resultingValue = valueFactory(newKey);
VolatileWrite(ref searchLastEntry.Next, new Entry { Key = newKey, Value = resultingValue, Hash = h });
}
break;
}
searchLastEntry = searchLastEntry.Next;
}
}
return true;
}
public bool TryGetValue(TKey2 key, out TValue value)
{
Entry[] table = this.buckets;
var hash = this.comparer.GetHashCode(key);
Entry entry = table[hash & table.Length - 1];
if (entry == null)
{
goto NOT_FOUND;
}
if (this.comparer.Equals(entry.Key, key))
{
value = entry.Value;
return true;
}
Entry next = entry.Next;
while (next != null)
{
if (this.comparer.Equals(next.Key, key))
{
value = next.Value;
return true;
}
next = next.Next;
}
NOT_FOUND:
value = default(TValue);
return false;
}
private static int CalculateCapacity(int collectionSize, float loadFactor)
{
var initialCapacity = (int)(((float)collectionSize) / loadFactor);
var capacity = 1;
while (capacity < initialCapacity)
{
capacity <<= 1;
}
if (capacity < 8)
{
return 8;
}
return capacity;
}
private static void VolatileWrite(ref Entry location, Entry value)
{
System.Threading.Volatile.Write(ref location, value);
}
private static void VolatileWrite(ref Entry[] location, Entry[] value)
{
System.Threading.Volatile.Write(ref location, value);
}
private class Entry
{
#pragma warning disable SA1401 // Fields should be private
internal TKey1 Key;
internal TValue Value;
internal int Hash;
internal Entry Next;
#pragma warning restore SA1401 // Fields should be private
// from debugger only
public override string ToString()
{
return "Count:" + this.Count;
}
internal int Count
{
get
{
var count = 1;
Entry n = this;
while (n.Next != null)
{
count++;
n = n.Next;
}
return count;
}
}
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 6862254987b9738ab9482616a323c2b5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,504 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Text;
#pragma warning disable SA1509 // Opening braces should not be preceded by blank line
namespace MessagePack.Internal
{
// Key = long, Value = int for UTF8String Dictionary
/// <remarks>
/// This code is used by dynamically generated code as well as AOT generated code,
/// and thus must be public for the "C# generated and compiled into saved assembly" scenario.
/// </remarks>
public class AutomataDictionary : IEnumerable<KeyValuePair<string, int>>
{
private readonly AutomataNode root;
public AutomataDictionary()
{
this.root = new AutomataNode(0);
}
public void Add(string str, int value)
{
ReadOnlySpan<byte> bytes = Encoding.UTF8.GetBytes(str);
AutomataNode node = this.root;
while (bytes.Length > 0)
{
var key = AutomataKeyGen.GetKey(ref bytes);
if (bytes.Length == 0)
{
node = node.Add(key, value, str);
}
else
{
node = node.Add(key);
}
}
}
public bool TryGetValue(in ReadOnlySequence<byte> bytes, out int value) => this.TryGetValue(bytes.ToArray(), out value);
public bool TryGetValue(ReadOnlySpan<byte> bytes, out int value)
{
AutomataNode node = this.root;
while (bytes.Length > 0 && node != null)
{
node = node.SearchNext(ref bytes);
}
if (node == null)
{
value = -1;
return false;
}
else
{
value = node.Value;
return true;
}
}
// for debugging
public override string ToString()
{
var sb = new StringBuilder();
ToStringCore(this.root.YieldChildren(), sb, 0);
return sb.ToString();
}
private static void ToStringCore(IEnumerable<AutomataNode> nexts, StringBuilder sb, int depth)
{
foreach (AutomataNode item in nexts)
{
if (depth != 0)
{
sb.Append(' ', depth * 2);
}
sb.Append("[" + item.Key + "]");
if (item.Value != -1)
{
sb.Append("(" + item.OriginalKey + ")");
sb.Append(" = ");
sb.Append(item.Value);
}
sb.AppendLine();
ToStringCore(item.YieldChildren(), sb, depth + 1);
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public IEnumerator<KeyValuePair<string, int>> GetEnumerator()
{
return YieldCore(this.root.YieldChildren()).GetEnumerator();
}
private static IEnumerable<KeyValuePair<string, int>> YieldCore(IEnumerable<AutomataNode> nexts)
{
foreach (AutomataNode item in nexts)
{
if (item.Value != -1)
{
yield return new KeyValuePair<string, int>(item.OriginalKey, item.Value);
}
foreach (KeyValuePair<string, int> x in YieldCore(item.YieldChildren()))
{
yield return x;
}
}
}
/* IL Emit */
#if !NET_STANDARD_2_0
public void EmitMatch(ILGenerator il, LocalBuilder bytesSpan, LocalBuilder key, Action<KeyValuePair<string, int>> onFound, Action onNotFound)
{
this.root.EmitSearchNext(il, bytesSpan, key, onFound, onNotFound);
}
#endif
private class AutomataNode : IComparable<AutomataNode>
{
private static readonly AutomataNode[] EmptyNodes = new AutomataNode[0];
private static readonly ulong[] EmptyKeys = new ulong[0];
#pragma warning disable SA1401 // Fields should be private
internal ulong Key;
internal int Value;
internal string OriginalKey;
#pragma warning restore SA1401 // Fields should be private
private AutomataNode[] nexts;
private ulong[] nextKeys;
private int count;
public bool HasChildren
{
get { return this.count != 0; }
}
public AutomataNode(ulong key)
{
this.Key = key;
this.Value = -1;
this.nexts = EmptyNodes;
this.nextKeys = EmptyKeys;
this.count = 0;
this.OriginalKey = null;
}
public AutomataNode Add(ulong key)
{
var index = Array.BinarySearch(this.nextKeys, 0, this.count, key);
if (index < 0)
{
if (this.nexts.Length == this.count)
{
Array.Resize<AutomataNode>(ref this.nexts, (this.count == 0) ? 4 : (this.count * 2));
Array.Resize<ulong>(ref this.nextKeys, (this.count == 0) ? 4 : (this.count * 2));
}
this.count++;
var nextNode = new AutomataNode(key);
this.nexts[this.count - 1] = nextNode;
this.nextKeys[this.count - 1] = key;
Array.Sort(this.nexts, 0, this.count);
Array.Sort(this.nextKeys, 0, this.count);
return nextNode;
}
else
{
return this.nexts[index];
}
}
public AutomataNode Add(ulong key, int value, string originalKey)
{
AutomataNode v = this.Add(key);
v.Value = value;
v.OriginalKey = originalKey;
return v;
}
public AutomataNode SearchNext(ref ReadOnlySpan<byte> value)
{
var key = AutomataKeyGen.GetKey(ref value);
if (this.count < 4)
{
// linear search
for (int i = 0; i < this.count; i++)
{
if (this.nextKeys[i] == key)
{
return this.nexts[i];
}
}
}
else
{
// binary search
var index = BinarySearch(this.nextKeys, 0, this.count, key);
if (index >= 0)
{
return this.nexts[index];
}
}
return null;
}
internal static int BinarySearch(ulong[] array, int index, int length, ulong value)
{
int lo = index;
int hi = index + length - 1;
while (lo <= hi)
{
int i = lo + ((hi - lo) >> 1);
var arrayValue = array[i];
int order;
if (arrayValue < value)
{
order = -1;
}
else if (arrayValue > value)
{
order = 1;
}
else
{
order = 0;
}
if (order == 0)
{
return i;
}
if (order < 0)
{
lo = i + 1;
}
else
{
hi = i - 1;
}
}
return ~lo;
}
public int CompareTo(AutomataNode other)
{
return this.Key.CompareTo(other.Key);
}
public IEnumerable<AutomataNode> YieldChildren()
{
for (int i = 0; i < this.count; i++)
{
yield return this.nexts[i];
}
}
#if !NET_STANDARD_2_0
// SearchNext(ref ReadOnlySpan<byte> bytes)
public void EmitSearchNext(ILGenerator il, LocalBuilder bytesSpan, LocalBuilder key, Action<KeyValuePair<string, int>> onFound, Action onNotFound)
{
// key = AutomataKeyGen.GetKey(ref bytesSpan);
il.EmitLdloca(bytesSpan);
il.EmitCall(AutomataKeyGen.GetKeyMethod);
il.EmitStloc(key);
// match children.
EmitSearchNextCore(il, bytesSpan, key, onFound, onNotFound, this.nexts, this.count);
}
private static void EmitSearchNextCore(ILGenerator il, LocalBuilder bytesSpan, LocalBuilder key, Action<KeyValuePair<string, int>> onFound, Action onNotFound, AutomataNode[] nexts, int count)
{
if (count < 4)
{
// linear-search
AutomataNode[] valueExists = nexts.Take(count).Where(x => x.Value != -1).ToArray();
AutomataNode[] childrenExists = nexts.Take(count).Where(x => x.HasChildren).ToArray();
Label gotoSearchNext = il.DefineLabel();
Label gotoNotFound = il.DefineLabel();
{
// bytesSpan.Length
il.EmitLdloca(bytesSpan);
il.EmitCall(typeof(ReadOnlySpan<byte>).GetRuntimeProperty(nameof(ReadOnlySpan<byte>.Length)).GetMethod);
if (childrenExists.Length != 0 && valueExists.Length == 0)
{
il.Emit(OpCodes.Brfalse, gotoNotFound); // if(bytesSpan.Length == 0)
}
else
{
il.Emit(OpCodes.Brtrue, gotoSearchNext); // if(bytesSpan.Length != 0)
}
}
{
Label[] ifValueNexts = Enumerable.Range(0, Math.Max(valueExists.Length - 1, 0)).Select(_ => il.DefineLabel()).ToArray();
for (int i = 0; i < valueExists.Length; i++)
{
Label notFoundLabel = il.DefineLabel();
if (i != 0)
{
il.MarkLabel(ifValueNexts[i - 1]);
}
il.EmitLdloc(key);
il.EmitULong(valueExists[i].Key);
il.Emit(OpCodes.Bne_Un, notFoundLabel);
// found
onFound(new KeyValuePair<string, int>(valueExists[i].OriginalKey, valueExists[i].Value));
// notfound
il.MarkLabel(notFoundLabel);
if (i != valueExists.Length - 1)
{
il.Emit(OpCodes.Br, ifValueNexts[i]);
}
else
{
onNotFound();
}
}
}
il.MarkLabel(gotoSearchNext);
Label[] ifRecNext = Enumerable.Range(0, Math.Max(childrenExists.Length - 1, 0)).Select(_ => il.DefineLabel()).ToArray();
for (int i = 0; i < childrenExists.Length; i++)
{
Label notFoundLabel = il.DefineLabel();
if (i != 0)
{
il.MarkLabel(ifRecNext[i - 1]);
}
il.EmitLdloc(key);
il.EmitULong(childrenExists[i].Key);
il.Emit(OpCodes.Bne_Un, notFoundLabel);
// found
childrenExists[i].EmitSearchNext(il, bytesSpan, key, onFound, onNotFound);
// notfound
il.MarkLabel(notFoundLabel);
if (i != childrenExists.Length - 1)
{
il.Emit(OpCodes.Br, ifRecNext[i]);
}
else
{
onNotFound();
}
}
il.MarkLabel(gotoNotFound);
onNotFound();
}
else
{
// binary-search
var midline = count / 2;
var mid = nexts[midline].Key;
AutomataNode[] l = nexts.Take(count).Take(midline).ToArray();
AutomataNode[] r = nexts.Take(count).Skip(midline).ToArray();
Label gotoRight = il.DefineLabel();
// if(key < mid)
il.EmitLdloc(key);
il.EmitULong(mid);
il.Emit(OpCodes.Bge, gotoRight);
EmitSearchNextCore(il, bytesSpan, key, onFound, onNotFound, l, l.Length);
// else
il.MarkLabel(gotoRight);
EmitSearchNextCore(il, bytesSpan, key, onFound, onNotFound, r, r.Length);
}
}
#endif
}
}
/// <remarks>
/// This is used by dynamically generated code. It can be made internal after we enable our dynamic assemblies to access internals.
/// But that trick may require net46, so maybe we should leave this as public.
/// </remarks>
public static class AutomataKeyGen
{
public static readonly MethodInfo GetKeyMethod = typeof(AutomataKeyGen).GetRuntimeMethod(nameof(GetKey), new[] { typeof(ReadOnlySpan<byte>).MakeByRefType() });
public static ulong GetKey(ref ReadOnlySpan<byte> span)
{
ulong key;
unchecked
{
if (span.Length >= 8)
{
key = MemoryMarshal.Cast<byte, ulong>(span)[0];
span = span.Slice(8);
}
else
{
switch (span.Length)
{
case 1:
{
key = span[0];
span = span.Slice(1);
break;
}
case 2:
{
key = MemoryMarshal.Cast<byte, ushort>(span)[0];
span = span.Slice(2);
break;
}
case 3:
{
var a = span[0];
var b = MemoryMarshal.Cast<byte, ushort>(span.Slice(1))[0];
key = a | (ulong)b << 8;
span = span.Slice(3);
break;
}
case 4:
{
key = MemoryMarshal.Cast<byte, uint>(span)[0];
span = span.Slice(4);
break;
}
case 5:
{
var a = span[0];
var b = MemoryMarshal.Cast<byte, uint>(span.Slice(1))[0];
key = a | (ulong)b << 8;
span = span.Slice(5);
break;
}
case 6:
{
ulong a = MemoryMarshal.Cast<byte, ushort>(span)[0];
ulong b = MemoryMarshal.Cast<byte, uint>(span.Slice(2))[0];
key = a | (b << 16);
span = span.Slice(6);
break;
}
case 7:
{
var a = span[0];
var b = MemoryMarshal.Cast<byte, ushort>(span.Slice(1))[0];
var c = MemoryMarshal.Cast<byte, uint>(span.Slice(3))[0];
key = a | (ulong)b << 8 | (ulong)c << 24;
span = span.Slice(7);
break;
}
default:
throw new MessagePackSerializationException("Not Supported Length");
}
}
return key;
}
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: fc94f4e5525f7ba44b4e68f3cdcb1050
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,193 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace MessagePack.Internal
{
// like ArraySegment<byte> hashtable.
// Add is safe for construction phase only and requires capacity(does not do rehash)
// and specialized for internal use(nongenerics, TValue is int)
// internal, but code generator requires this class
// or at least PerfBenchmarkDotNet
public class ByteArrayStringHashTable : IEnumerable<KeyValuePair<string, int>>
{
private readonly Entry[][] buckets; // immutable array(faster than linkedlist)
private readonly ulong indexFor;
public ByteArrayStringHashTable(int capacity)
: this(capacity, 0.42f) // default: 0.75f -> 0.42f
{
}
public ByteArrayStringHashTable(int capacity, float loadFactor)
{
var tableSize = CalculateCapacity(capacity, loadFactor);
this.buckets = new Entry[tableSize][];
this.indexFor = (ulong)this.buckets.Length - 1;
}
public void Add(string key, int value)
{
if (!this.TryAddInternal(Encoding.UTF8.GetBytes(key), value))
{
throw new ArgumentException("Key was already exists. Key:" + key);
}
}
public void Add(byte[] key, int value)
{
if (!this.TryAddInternal(key, value))
{
throw new ArgumentException("Key was already exists. Key:" + key);
}
}
private bool TryAddInternal(byte[] key, int value)
{
var h = ByteArrayGetHashCode(key);
var entry = new Entry { Key = key, Value = value };
Entry[] array = this.buckets[h & this.indexFor];
if (array == null)
{
this.buckets[h & this.indexFor] = new[] { entry };
}
else
{
// check duplicate
for (int i = 0; i < array.Length; i++)
{
byte[] e = array[i].Key;
if (key.AsSpan().SequenceEqual(e))
{
return false;
}
}
var newArray = new Entry[array.Length + 1];
Array.Copy(array, newArray, array.Length);
array = newArray;
array[array.Length - 1] = entry;
this.buckets[h & this.indexFor] = array;
}
return true;
}
public bool TryGetValue(in ReadOnlySequence<byte> key, out int value) => this.TryGetValue(CodeGenHelpers.GetSpanFromSequence(key), out value);
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public bool TryGetValue(ReadOnlySpan<byte> key, out int value)
{
Entry[][] table = this.buckets;
var hash = ByteArrayGetHashCode(key);
Entry[] entry = table[hash & this.indexFor];
if (entry == null)
{
value = default(int);
return false;
}
ref Entry v = ref entry[0];
if (key.SequenceEqual(v.Key))
{
value = v.Value;
return true;
}
return TryGetValueSlow(key, entry, out value);
}
private bool TryGetValueSlow(ReadOnlySpan<byte> key, Entry[] entry, out int value)
{
for (int i = 1; i < entry.Length; i++)
{
ref Entry v = ref entry[i];
if (key.SequenceEqual(v.Key))
{
value = v.Value;
return true;
}
}
value = default(int);
return false;
}
private static readonly bool Is32Bit = IntPtr.Size == 4;
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
private static ulong ByteArrayGetHashCode(ReadOnlySpan<byte> x)
{
// FarmHash https://github.com/google/farmhash
if (Is32Bit)
{
return (ulong)FarmHash.Hash32(x);
}
else
{
return FarmHash.Hash64(x);
}
}
private static int CalculateCapacity(int collectionSize, float loadFactor)
{
var initialCapacity = (int)(((float)collectionSize) / loadFactor);
var capacity = 1;
while (capacity < initialCapacity)
{
capacity <<= 1;
}
if (capacity < 8)
{
return 8;
}
return capacity;
}
// only for Debug use
public IEnumerator<KeyValuePair<string, int>> GetEnumerator()
{
Entry[][] b = this.buckets;
foreach (Entry[] item in b)
{
if (item == null)
{
continue;
}
foreach (Entry item2 in item)
{
yield return new KeyValuePair<string, int>(Encoding.UTF8.GetString(item2.Key), item2.Value);
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
private struct Entry
{
public byte[] Key;
public int Value;
// for debugging
public override string ToString()
{
return "(" + Encoding.UTF8.GetString(this.Key) + ", " + this.Value + ")";
}
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 28c84212e5b4fc4d7b4b66cdb741984d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,87 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Buffers;
using System.ComponentModel;
namespace MessagePack.Internal
{
/// <summary>
/// Helpers for generated code.
/// </summary>
/// <remarks>
/// This code is used by dynamically generated code as well as AOT generated code,
/// and thus must be public for the "C# generated and compiled into saved assembly" scenario.
/// </remarks>
[EditorBrowsable(EditorBrowsableState.Never)]
public static class CodeGenHelpers
{
public static byte[] GetEncodedStringBytes(string value)
{
var byteCount = StringEncoding.UTF8.GetByteCount(value);
if (byteCount <= MessagePackRange.MaxFixStringLength)
{
var bytes = new byte[byteCount + 1];
bytes[0] = (byte)(MessagePackCode.MinFixStr | byteCount);
StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, 1);
return bytes;
}
else if (byteCount <= byte.MaxValue)
{
var bytes = new byte[byteCount + 2];
bytes[0] = MessagePackCode.Str8;
bytes[1] = unchecked((byte)byteCount);
StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, 2);
return bytes;
}
else if (byteCount <= ushort.MaxValue)
{
var bytes = new byte[byteCount + 3];
bytes[0] = MessagePackCode.Str16;
bytes[1] = unchecked((byte)(byteCount >> 8));
bytes[2] = unchecked((byte)byteCount);
StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, 3);
return bytes;
}
else
{
var bytes = new byte[byteCount + 5];
bytes[0] = MessagePackCode.Str32;
bytes[1] = unchecked((byte)(byteCount >> 24));
bytes[2] = unchecked((byte)(byteCount >> 16));
bytes[3] = unchecked((byte)(byteCount >> 8));
bytes[4] = unchecked((byte)byteCount);
StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, 5);
return bytes;
}
}
public static ReadOnlySpan<byte> GetSpanFromSequence(in ReadOnlySequence<byte> sequence)
{
if (sequence.IsSingleSegment)
{
return sequence.First.Span;
}
return sequence.ToArray();
}
public static ReadOnlySpan<byte> ReadStringSpan(ref MessagePackReader reader)
{
if (!reader.TryReadStringSpan(out ReadOnlySpan<byte> result))
{
return GetSpanFromSequence(reader.ReadStringSequence());
}
return result;
}
public static byte[] GetArrayFromNullableSequence(in ReadOnlySequence<byte>? sequence) => sequence?.ToArray();
private static ReadOnlySpan<byte> GetSpanFromSequence(in ReadOnlySequence<byte>? sequence)
{
return sequence.HasValue ? GetSpanFromSequence(sequence.Value) : default;
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 4f2dcc1d826e7ff7da02bd691c4dd6a0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,14 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace MessagePack.Internal
{
internal static class DateTimeConstants
{
internal const long BclSecondsAtUnixEpoch = 62135596800;
internal const int NanosecondsPerTick = 100;
internal static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: a0cf18db43b878d71a216123e3309b65
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,75 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#if !(UNITY_2018_3_OR_NEWER && NET_STANDARD_2_0)
using System;
using System.Reflection;
using System.Reflection.Emit;
namespace MessagePack.Internal
{
internal class DynamicAssembly
{
#if NETFRAMEWORK // We don't ship a net472 target, but we might add one for debugging purposes
private readonly string moduleName;
#endif
private readonly AssemblyBuilder assemblyBuilder;
private readonly ModuleBuilder moduleBuilder;
// don't expose ModuleBuilder
//// public ModuleBuilder ModuleBuilder { get { return moduleBuilder; } }
private readonly object gate = new object();
public DynamicAssembly(string moduleName)
{
#if NETFRAMEWORK // We don't ship a net472 target, but we might add one for debugging purposes
AssemblyBuilderAccess builderAccess = AssemblyBuilderAccess.RunAndSave;
this.moduleName = moduleName;
#else
AssemblyBuilderAccess builderAccess = AssemblyBuilderAccess.Run;
#endif
this.assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(moduleName), builderAccess);
this.moduleBuilder = this.assemblyBuilder.DefineDynamicModule(moduleName + ".dll");
}
/* requires lock on mono environment. see: https://github.com/neuecc/MessagePack-CSharp/issues/161 */
public TypeBuilder DefineType(string name, TypeAttributes attr)
{
lock (this.gate)
{
return this.moduleBuilder.DefineType(name, attr);
}
}
public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent)
{
lock (this.gate)
{
return this.moduleBuilder.DefineType(name, attr, parent);
}
}
public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, Type[] interfaces)
{
lock (this.gate)
{
return this.moduleBuilder.DefineType(name, attr, parent, interfaces);
}
}
#if NETFRAMEWORK
public AssemblyBuilder Save()
{
this.assemblyBuilder.Save(this.moduleName + ".dll");
return this.assemblyBuilder;
}
#endif
}
}
#endif

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: f44ca64eddd25f5a896a2f72b21fcc9b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,85 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace MessagePack.Internal
{
internal static class ExpressionUtility
{
private static MethodInfo GetMethodInfoCore(LambdaExpression expression)
{
if (expression == null)
{
throw new ArgumentNullException("expression");
}
return (expression.Body as MethodCallExpression).Method;
}
/// <summary>
/// Get MethodInfo from Expression for Static(with result) method.
/// </summary>
public static MethodInfo GetMethodInfo<T>(Expression<Func<T>> expression)
{
return GetMethodInfoCore(expression);
}
/// <summary>
/// Get MethodInfo from Expression for Static(void) method.
/// </summary>
public static MethodInfo GetMethodInfo(Expression<Action> expression)
{
return GetMethodInfoCore(expression);
}
/// <summary>
/// Get MethodInfo from Expression for Instance(with result) method.
/// </summary>
public static MethodInfo GetMethodInfo<T, TR>(Expression<Func<T, TR>> expression)
{
return GetMethodInfoCore(expression);
}
/// <summary>
/// Get MethodInfo from Expression for Instance(void) method.
/// </summary>
public static MethodInfo GetMethodInfo<T>(Expression<Action<T>> expression)
{
return GetMethodInfoCore(expression);
}
// WithArgument(for ref, out) helper
/// <summary>
/// Get MethodInfo from Expression for Instance(with result) method.
/// </summary>
public static MethodInfo GetMethodInfo<T, TArg1, TR>(Expression<Func<T, TArg1, TR>> expression)
{
return GetMethodInfoCore(expression);
}
private static MemberInfo GetMemberInfoCore<T>(Expression<T> source)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
var memberExpression = source.Body as MemberExpression;
return memberExpression.Member;
}
public static PropertyInfo GetPropertyInfo<T, TR>(Expression<Func<T, TR>> expression)
{
return GetMemberInfoCore(expression) as PropertyInfo;
}
public static FieldInfo GetFieldInfo<T, TR>(Expression<Func<T, TR>> expression)
{
return GetMemberInfoCore(expression) as FieldInfo;
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 1e2163b0f9d41a70599e1d5bd231a4b6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,601 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Runtime.CompilerServices;
#pragma warning disable SA1300 // Element should begin with uppercase letter
#pragma warning disable SA1303 // Const field names should begin with uppercase letter
#pragma warning disable SA1307 // (public) field names should begin with uppercase letter
namespace MessagePack.Internal
{
internal static class FarmHash
{
#region Hash32
// entry point of 32bit
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe uint Hash32(ReadOnlySpan<byte> bytes)
{
if (bytes.Length <= 4)
{
return Hash32Len0to4(bytes);
}
fixed (byte* p = bytes)
{
return Hash32(p, (uint)bytes.Length);
}
}
// port of farmhash.cc, 32bit only
// Magic numbers for 32-bit hashing. Copied from Murmur3.
private const uint c1 = 0xcc9e2d51;
private const uint c2 = 0x1b873593;
private static unsafe uint Fetch32(byte* p)
{
return *(uint*)p;
}
private static uint Rotate32(uint val, int shift)
{
return shift == 0 ? val : ((val >> shift) | (val << (32 - shift)));
}
// A 32-bit to 32-bit integer hash copied from Murmur3.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint fmix(uint h)
{
unchecked
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Mur(uint a, uint h)
{
unchecked
{
// Helper from Murmur3 for combining two 32-bit values.
a *= c1;
a = Rotate32(a, 17);
a *= c2;
h ^= a;
h = Rotate32(h, 19);
return (h * 5) + 0xe6546b64;
}
}
// 0-4
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe uint Hash32Len0to4(ReadOnlySpan<byte> s)
{
unchecked
{
uint b = 0;
uint c = 9;
for (int i = 0; i < s.Length; i++)
{
b = (b * c1) + s[i];
c ^= b;
}
return fmix(Mur(b, Mur((uint)s.Length, c)));
}
}
// 5-12
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe uint Hash32Len5to12(byte* s, uint len)
{
unchecked
{
uint a = len, b = len * 5, c = 9, d = b;
a += Fetch32(s);
b += Fetch32(s + len - 4);
c += Fetch32(s + ((len >> 1) & 4));
return fmix(Mur(c, Mur(b, Mur(a, d))));
}
}
// 13-24
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe uint Hash32Len13to24(byte* s, uint len)
{
unchecked
{
uint a = Fetch32(s - 4 + (len >> 1));
uint b = Fetch32(s + 4);
uint c = Fetch32(s + len - 8);
uint d = Fetch32(s + (len >> 1));
uint e = Fetch32(s);
uint f = Fetch32(s + len - 4);
uint h = (d * c1) + len;
a = Rotate32(a, 12) + f;
h = Mur(c, h) + a;
a = Rotate32(a, 3) + c;
h = Mur(e, h) + a;
a = Rotate32(a + f, 12) + d;
h = Mur(b, h) + a;
return fmix(h);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe uint Hash32(byte* s, uint len)
{
if (len <= 24)
{
return len <= 12 ? Hash32Len5to12(s, len) : Hash32Len13to24(s, len);
}
unchecked
{
// len > 24
uint h = len, g = c1 * len, f = g;
uint a0 = Rotate32(Fetch32(s + len - 4) * c1, 17) * c2;
uint a1 = Rotate32(Fetch32(s + len - 8) * c1, 17) * c2;
uint a2 = Rotate32(Fetch32(s + len - 16) * c1, 17) * c2;
uint a3 = Rotate32(Fetch32(s + len - 12) * c1, 17) * c2;
uint a4 = Rotate32(Fetch32(s + len - 20) * c1, 17) * c2;
h ^= a0;
h = Rotate32(h, 19);
h = (h * 5) + 0xe6546b64;
h ^= a2;
h = Rotate32(h, 19);
h = (h * 5) + 0xe6546b64;
g ^= a1;
g = Rotate32(g, 19);
g = (g * 5) + 0xe6546b64;
g ^= a3;
g = Rotate32(g, 19);
g = (g * 5) + 0xe6546b64;
f += a4;
f = Rotate32(f, 19) + 113;
uint iters = (len - 1) / 20;
do
{
uint a = Fetch32(s);
uint b = Fetch32(s + 4);
uint c = Fetch32(s + 8);
uint d = Fetch32(s + 12);
uint e = Fetch32(s + 16);
h += a;
g += b;
f += c;
h = Mur(d, h) + e;
g = Mur(c, g) + a;
f = Mur(b + (e * c1), f) + d;
f += g;
g += f;
s += 20;
}
while (--iters != 0);
g = Rotate32(g, 11) * c1;
g = Rotate32(g, 17) * c1;
f = Rotate32(f, 11) * c1;
f = Rotate32(f, 17) * c1;
h = Rotate32(h + g, 19);
h = (h * 5) + 0xe6546b64;
h = Rotate32(h, 17) * c1;
h = Rotate32(h + f, 19);
h = (h * 5) + 0xe6546b64;
h = Rotate32(h, 17) * c1;
return h;
}
}
#endregion
#region hash64
// entry point
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe ulong Hash64(ReadOnlySpan<byte> bytes)
{
fixed (byte* p = bytes)
{
return Hash64(p, (uint)bytes.Length);
}
}
/* port from farmhash.cc */
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void swap(ref ulong x, ref ulong z)
{
var temp = z;
z = x;
x = temp;
}
// Some primes between 2^63 and 2^64 for various uses.
private const ulong k0 = 0xc3a5c85c97cb3127UL;
private const ulong k1 = 0xb492b66fbe98f273UL;
private const ulong k2 = 0x9ae16a3b2f90404fUL;
private static unsafe ulong Fetch64(byte* p)
{
return *(ulong*)p;
}
private static ulong Rotate64(ulong val, int shift)
{
return shift == 0 ? val : (val >> shift) | (val << (64 - shift));
}
// farmhashna.cc
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong ShiftMix(ulong val)
{
return val ^ (val >> 47);
}
// farmhashna.cc
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong HashLen16(ulong u, ulong v, ulong mul)
{
unchecked
{
// Murmur-inspired hashing.
ulong a = (u ^ v) * mul;
a ^= a >> 47;
ulong b = (v ^ a) * mul;
b ^= b >> 47;
b *= mul;
return b;
}
}
// farmhashxo.cc
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe ulong Hash64(byte* s, uint len)
{
if (len <= 16)
{
// farmhashna::
return HashLen0to16(s, len);
}
if (len <= 32)
{
// farmhashna::
return HashLen17to32(s, len);
}
if (len <= 64)
{
return HashLen33to64(s, len);
}
if (len <= 96)
{
return HashLen65to96(s, len);
}
if (len <= 256)
{
// farmhashna::
return Hash64NA(s, len);
}
// farmhashuo::
return Hash64UO(s, len);
}
// 0-16 farmhashna.cc
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe ulong HashLen0to16(byte* s, uint len)
{
unchecked
{
if (len >= 8)
{
ulong mul = k2 + (len * 2);
ulong a = Fetch64(s) + k2;
ulong b = Fetch64(s + len - 8);
ulong c = (Rotate64(b, 37) * mul) + a;
ulong d = (Rotate64(a, 25) + b) * mul;
return HashLen16(c, d, mul);
}
if (len >= 4)
{
ulong mul = k2 + (len * 2);
ulong a = Fetch32(s);
return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul);
}
if (len > 0)
{
ushort a = s[0];
ushort b = s[len >> 1];
ushort c = s[len - 1];
uint y = a + ((uint)b << 8);
uint z = len + ((uint)c << 2);
return ShiftMix(y * k2 ^ z * k0) * k2;
}
return k2;
}
}
// 17-32 farmhashna.cc
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe ulong HashLen17to32(byte* s, uint len)
{
unchecked
{
ulong mul = k2 + (len * 2);
ulong a = Fetch64(s) * k1;
ulong b = Fetch64(s + 8);
ulong c = Fetch64(s + len - 8) * mul;
ulong d = Fetch64(s + len - 16) * k2;
return HashLen16(
Rotate64(a + b, 43) + Rotate64(c, 30) + d,
a + Rotate64(b + k2, 18) + c,
mul);
}
}
// farmhashxo.cc
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe ulong H32(byte* s, uint len, ulong mul, ulong seed0 = 0, ulong seed1 = 0)
{
unchecked
{
ulong a = Fetch64(s) * k1;
ulong b = Fetch64(s + 8);
ulong c = Fetch64(s + len - 8) * mul;
ulong d = Fetch64(s + len - 16) * k2;
ulong u = Rotate64(a + b, 43) + Rotate64(c, 30) + d + seed0;
ulong v = a + Rotate64(b + k2, 18) + c + seed1;
a = ShiftMix((u ^ v) * mul);
b = ShiftMix((v ^ a) * mul);
return b;
}
}
// 33-64 farmhashxo.cc
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe ulong HashLen33to64(byte* s, uint len)
{
const ulong mul0 = k2 - 30;
unchecked
{
ulong mul1 = k2 - 30 + (2 * len);
ulong h0 = H32(s, 32, mul0);
ulong h1 = H32(s + len - 32, 32, mul1);
return ((h1 * mul1) + h0) * mul1;
}
}
// 65-96 farmhashxo.cc
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe ulong HashLen65to96(byte* s, uint len)
{
const ulong mul0 = k2 - 114;
unchecked
{
ulong mul1 = k2 - 114 + (2 * len);
ulong h0 = H32(s, 32, mul0);
ulong h1 = H32(s + 32, 32, mul1);
ulong h2 = H32(s + len - 32, 32, mul1, h0, h1);
return ((h2 * 9) + (h0 >> 17) + (h1 >> 21)) * mul1;
}
}
// farmhashna.cc
// Return a 16-byte hash for 48 bytes. Quick and dirty.
// Callers do best to use "random-looking" values for a and b.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe void WeakHashLen32WithSeeds(ulong w, ulong x, ulong y, ulong z, ulong a, ulong b, out ulong first, out ulong second)
{
unchecked
{
a += w;
b = Rotate64(b + a + z, 21);
ulong c = a;
a += x;
a += y;
b += Rotate64(a, 44);
first = a + z;
second = b + c;
}
}
// farmhashna.cc
// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe void WeakHashLen32WithSeeds(byte* s, ulong a, ulong b, out ulong first, out ulong second)
{
WeakHashLen32WithSeeds(
Fetch64(s),
Fetch64(s + 8),
Fetch64(s + 16),
Fetch64(s + 24),
a,
b,
out first,
out second);
}
// na(97-256) farmhashna.cc
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe ulong Hash64NA(byte* s, uint len)
{
const ulong seed = 81;
unchecked
{
// For strings over 64 bytes we loop. Internal state consists of
// 56 bytes: v, w, x, y, and z.
ulong x = seed;
ulong y = (seed * k1) + 113;
ulong z = ShiftMix((y * k2) + 113) * k2;
ulong v_first = 0;
ulong v_second = 0;
ulong w_first = 0;
ulong w_second = 0;
x = (x * k2) + Fetch64(s);
// Set end so that after the loop we have 1 to 64 bytes left to process.
byte* end = s + ((len - 1) / 64 * 64);
byte* last64 = end + ((len - 1) & 63) - 63;
do
{
x = Rotate64(x + y + v_first + Fetch64(s + 8), 37) * k1;
y = Rotate64(y + v_second + Fetch64(s + 48), 42) * k1;
x ^= w_second;
y += v_first + Fetch64(s + 40);
z = Rotate64(z + w_first, 33) * k1;
WeakHashLen32WithSeeds(s, v_second * k1, x + w_first, out v_first, out v_second);
WeakHashLen32WithSeeds(s + 32, z + w_second, y + Fetch64(s + 16), out w_first, out w_second);
swap(ref z, ref x);
s += 64;
}
while (s != end);
ulong mul = k1 + ((z & 0xff) << 1);
// Make s point to the last 64 bytes of input.
s = last64;
w_first += (len - 1) & 63;
v_first += w_first;
w_first += v_first;
x = Rotate64(x + y + v_first + Fetch64(s + 8), 37) * mul;
y = Rotate64(y + v_second + Fetch64(s + 48), 42) * mul;
x ^= w_second * 9;
y += (v_first * 9) + Fetch64(s + 40);
z = Rotate64(z + w_first, 33) * mul;
WeakHashLen32WithSeeds(s, v_second * mul, x + w_first, out v_first, out v_second);
WeakHashLen32WithSeeds(s + 32, z + w_second, y + Fetch64(s + 16), out w_first, out w_second);
swap(ref z, ref x);
return HashLen16(HashLen16(v_first, w_first, mul) + (ShiftMix(y) * k0) + z, HashLen16(v_second, w_second, mul) + x, mul);
}
}
// farmhashuo.cc
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong H(ulong x, ulong y, ulong mul, int r)
{
unchecked
{
ulong a = (x ^ y) * mul;
a ^= a >> 47;
ulong b = (y ^ a) * mul;
return Rotate64(b, r) * mul;
}
}
// uo(257-) farmhashuo.cc, Hash64WithSeeds
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe ulong Hash64UO(byte* s, uint len)
{
const ulong seed0 = 81;
const ulong seed1 = 0;
unchecked
{
// For strings over 64 bytes we loop. Internal state consists of
// 64 bytes: u, v, w, x, y, and z.
ulong x = seed0;
ulong y = (seed1 * k2) + 113;
ulong z = ShiftMix(y * k2) * k2;
ulong v_first = seed0;
ulong v_second = seed1;
ulong w_first = 0;
ulong w_second = 0;
ulong u = x - z;
x *= k2;
ulong mul = k2 + (u & 0x82);
// Set end so that after the loop we have 1 to 64 bytes left to process.
byte* end = s + ((len - 1) / 64 * 64);
byte* last64 = end + ((len - 1) & 63) - 63;
do
{
ulong a0 = Fetch64(s);
ulong a1 = Fetch64(s + 8);
ulong a2 = Fetch64(s + 16);
ulong a3 = Fetch64(s + 24);
ulong a4 = Fetch64(s + 32);
ulong a5 = Fetch64(s + 40);
ulong a6 = Fetch64(s + 48);
ulong a7 = Fetch64(s + 56);
x += a0 + a1;
y += a2;
z += a3;
v_first += a4;
v_second += a5 + a1;
w_first += a6;
w_second += a7;
x = Rotate64(x, 26);
x *= 9;
y = Rotate64(y, 29);
z *= mul;
v_first = Rotate64(v_first, 33);
v_second = Rotate64(v_second, 30);
w_first ^= x;
w_first *= 9;
z = Rotate64(z, 32);
z += w_second;
w_second += z;
z *= 9;
swap(ref u, ref y);
z += a0 + a6;
v_first += a2;
v_second += a3;
w_first += a4;
w_second += a5 + a6;
x += a1;
y += a7;
y += v_first;
v_first += x - y;
v_second += w_first;
w_first += v_second;
w_second += x - y;
x += w_second;
w_second = Rotate64(w_second, 34);
swap(ref u, ref z);
s += 64;
}
while (s != end);
// Make s point to the last 64 bytes of input.
s = last64;
u *= 9;
v_second = Rotate64(v_second, 28);
v_first = Rotate64(v_first, 20);
w_first += (len - 1) & 63;
u += y;
y += u;
x = Rotate64(y - x + v_first + Fetch64(s + 8), 37) * mul;
y = Rotate64(y ^ v_second ^ Fetch64(s + 48), 42) * mul;
x ^= w_second * 9;
y += v_first + Fetch64(s + 40);
z = Rotate64(z + w_first, 33) * mul;
WeakHashLen32WithSeeds(s, v_second * mul, x + w_first, out v_first, out v_second);
WeakHashLen32WithSeeds(s + 32, z + w_second, y + Fetch64(s + 16), out w_first, out w_second);
return H(HashLen16(v_first + x, w_first ^ y, mul) + z - u, H(v_second + y, w_second + z, k2, 30) ^ x, k2, 31);
}
}
#endregion
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: fb5a050df97c09dd9b40337e9c0bbdcd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,391 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Runtime.InteropServices;
namespace MessagePack.Internal
{
[StructLayout(LayoutKind.Explicit, Pack = 1)]
internal struct GuidBits
{
[FieldOffset(0)]
public readonly Guid Value;
[FieldOffset(0)]
public readonly byte Byte0;
[FieldOffset(1)]
public readonly byte Byte1;
[FieldOffset(2)]
public readonly byte Byte2;
[FieldOffset(3)]
public readonly byte Byte3;
[FieldOffset(4)]
public readonly byte Byte4;
[FieldOffset(5)]
public readonly byte Byte5;
[FieldOffset(6)]
public readonly byte Byte6;
[FieldOffset(7)]
public readonly byte Byte7;
[FieldOffset(8)]
public readonly byte Byte8;
[FieldOffset(9)]
public readonly byte Byte9;
[FieldOffset(10)]
public readonly byte Byte10;
[FieldOffset(11)]
public readonly byte Byte11;
[FieldOffset(12)]
public readonly byte Byte12;
[FieldOffset(13)]
public readonly byte Byte13;
[FieldOffset(14)]
public readonly byte Byte14;
[FieldOffset(15)]
public readonly byte Byte15;
// string.Join(", ", Enumerable.Range(0, 256).Select(x => (int)BitConverter.ToString(new byte[] { (byte)x }).ToLower()[0]))
private static byte[] byteToHexStringHigh = new byte[256] { 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102 };
// string.Join(", ", Enumerable.Range(0, 256).Select(x => (int)BitConverter.ToString(new byte[] { (byte)x }).ToLower()[1]))
private static byte[] byteToHexStringLow = new byte[256] { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102 };
public GuidBits(ref Guid value)
{
this = default(GuidBits);
this.Value = value;
}
// 4-pattern, lower/upper and '-' or no
public GuidBits(ReadOnlySpan<byte> utf8string)
{
this = default(GuidBits);
// 32
if (utf8string.Length == 32)
{
if (BitConverter.IsLittleEndian)
{
this.Byte0 = Parse(utf8string, 6);
this.Byte1 = Parse(utf8string, 4);
this.Byte2 = Parse(utf8string, 2);
this.Byte3 = Parse(utf8string, 0);
this.Byte4 = Parse(utf8string, 10);
this.Byte5 = Parse(utf8string, 8);
this.Byte6 = Parse(utf8string, 14);
this.Byte7 = Parse(utf8string, 12);
}
else
{
this.Byte0 = Parse(utf8string, 0);
this.Byte1 = Parse(utf8string, 2);
this.Byte2 = Parse(utf8string, 4);
this.Byte3 = Parse(utf8string, 6);
this.Byte4 = Parse(utf8string, 8);
this.Byte5 = Parse(utf8string, 10);
this.Byte6 = Parse(utf8string, 12);
this.Byte7 = Parse(utf8string, 14);
}
this.Byte8 = Parse(utf8string, 16);
this.Byte9 = Parse(utf8string, 18);
this.Byte10 = Parse(utf8string, 20);
this.Byte11 = Parse(utf8string, 22);
this.Byte12 = Parse(utf8string, 24);
this.Byte13 = Parse(utf8string, 26);
this.Byte14 = Parse(utf8string, 28);
this.Byte15 = Parse(utf8string, 30);
return;
}
else if (utf8string.Length == 36)
{
// '-' => 45
if (BitConverter.IsLittleEndian)
{
this.Byte0 = Parse(utf8string, 6);
this.Byte1 = Parse(utf8string, 4);
this.Byte2 = Parse(utf8string, 2);
this.Byte3 = Parse(utf8string, 0);
if (utf8string[8] != '-')
{
goto ERROR;
}
this.Byte4 = Parse(utf8string, 11);
this.Byte5 = Parse(utf8string, 9);
if (utf8string[13] != '-')
{
goto ERROR;
}
this.Byte6 = Parse(utf8string, 16);
this.Byte7 = Parse(utf8string, 14);
}
else
{
this.Byte0 = Parse(utf8string, 0);
this.Byte1 = Parse(utf8string, 2);
this.Byte2 = Parse(utf8string, 4);
this.Byte3 = Parse(utf8string, 6);
if (utf8string[8] != '-')
{
goto ERROR;
}
this.Byte4 = Parse(utf8string, 9);
this.Byte5 = Parse(utf8string, 11);
if (utf8string[13] != '-')
{
goto ERROR;
}
this.Byte6 = Parse(utf8string, 14);
this.Byte7 = Parse(utf8string, 16);
}
if (utf8string[18] != '-')
{
goto ERROR;
}
this.Byte8 = Parse(utf8string, 19);
this.Byte9 = Parse(utf8string, 21);
if (utf8string[23] != '-')
{
goto ERROR;
}
this.Byte10 = Parse(utf8string, 24);
this.Byte11 = Parse(utf8string, 26);
this.Byte12 = Parse(utf8string, 28);
this.Byte13 = Parse(utf8string, 30);
this.Byte14 = Parse(utf8string, 32);
this.Byte15 = Parse(utf8string, 34);
return;
}
ERROR:
throw new MessagePackSerializationException("Invalid Guid Pattern.");
}
#if !UNITY_2018_3_OR_NEWER
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
#endif
private static byte Parse(ReadOnlySpan<byte> bytes, int highOffset)
{
return unchecked((byte)((SwitchParse(bytes[highOffset]) * 16) + SwitchParse(bytes[highOffset + 1])));
}
#if !UNITY_2018_3_OR_NEWER
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
#endif
private static byte SwitchParse(byte b)
{
// '0'(48) ~ '9'(57) => -48
// 'A'(65) ~ 'F'(70) => -55
// 'a'(97) ~ 'f'(102) => -87
switch (b)
{
case 48:
case 49:
case 50:
case 51:
case 52:
case 53:
case 54:
case 55:
case 56:
case 57:
return unchecked((byte)(b - 48));
case 65:
case 66:
case 67:
case 68:
case 69:
case 70:
return unchecked((byte)(b - 55));
case 97:
case 98:
case 99:
case 100:
case 101:
case 102:
return unchecked((byte)(b - 87));
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
case 31:
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
case 38:
case 39:
case 40:
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
case 58:
case 59:
case 60:
case 61:
case 62:
case 63:
case 64:
case 71:
case 72:
case 73:
case 74:
case 75:
case 76:
case 77:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 84:
case 85:
case 86:
case 87:
case 88:
case 89:
case 90:
case 91:
case 92:
case 93:
case 94:
case 95:
case 96:
default:
throw new MessagePackSerializationException("Invalid Guid Pattern.");
}
}
// 4(x2) - 2(x2) - 2(x2) - 2(x2) - 6(x2)
public void Write(Span<byte> buffer)
{
if (BitConverter.IsLittleEndian)
{
// int(_a)
buffer[6] = byteToHexStringHigh[this.Byte0];
buffer[7] = byteToHexStringLow[this.Byte0];
buffer[4] = byteToHexStringHigh[this.Byte1];
buffer[5] = byteToHexStringLow[this.Byte1];
buffer[2] = byteToHexStringHigh[this.Byte2];
buffer[3] = byteToHexStringLow[this.Byte2];
buffer[0] = byteToHexStringHigh[this.Byte3];
buffer[1] = byteToHexStringLow[this.Byte3];
buffer[8] = (byte)'-';
// short(_b)
buffer[11] = byteToHexStringHigh[this.Byte4];
buffer[12] = byteToHexStringLow[this.Byte4];
buffer[9] = byteToHexStringHigh[this.Byte5];
buffer[10] = byteToHexStringLow[this.Byte5];
buffer[13] = (byte)'-';
// short(_c)
buffer[16] = byteToHexStringHigh[this.Byte6];
buffer[17] = byteToHexStringLow[this.Byte6];
buffer[14] = byteToHexStringHigh[this.Byte7];
buffer[15] = byteToHexStringLow[this.Byte7];
}
else
{
buffer[0] = byteToHexStringHigh[this.Byte0];
buffer[1] = byteToHexStringLow[this.Byte0];
buffer[2] = byteToHexStringHigh[this.Byte1];
buffer[3] = byteToHexStringLow[this.Byte1];
buffer[4] = byteToHexStringHigh[this.Byte2];
buffer[5] = byteToHexStringLow[this.Byte2];
buffer[6] = byteToHexStringHigh[this.Byte3];
buffer[7] = byteToHexStringLow[this.Byte3];
buffer[8] = (byte)'-';
buffer[9] = byteToHexStringHigh[this.Byte4];
buffer[10] = byteToHexStringLow[this.Byte4];
buffer[11] = byteToHexStringHigh[this.Byte5];
buffer[12] = byteToHexStringLow[this.Byte5];
buffer[13] = (byte)'-';
buffer[14] = byteToHexStringHigh[this.Byte6];
buffer[15] = byteToHexStringLow[this.Byte6];
buffer[16] = byteToHexStringHigh[this.Byte7];
buffer[17] = byteToHexStringLow[this.Byte7];
}
buffer[18] = (byte)'-';
buffer[19] = byteToHexStringHigh[this.Byte8];
buffer[20] = byteToHexStringLow[this.Byte8];
buffer[21] = byteToHexStringHigh[this.Byte9];
buffer[22] = byteToHexStringLow[this.Byte9];
buffer[23] = (byte)'-';
buffer[24] = byteToHexStringHigh[this.Byte10];
buffer[25] = byteToHexStringLow[this.Byte10];
buffer[26] = byteToHexStringHigh[this.Byte11];
buffer[27] = byteToHexStringLow[this.Byte11];
buffer[28] = byteToHexStringHigh[this.Byte12];
buffer[29] = byteToHexStringLow[this.Byte12];
buffer[30] = byteToHexStringHigh[this.Byte13];
buffer[31] = byteToHexStringLow[this.Byte13];
buffer[32] = byteToHexStringHigh[this.Byte14];
buffer[33] = byteToHexStringLow[this.Byte14];
buffer[34] = byteToHexStringHigh[this.Byte15];
buffer[35] = byteToHexStringLow[this.Byte15];
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 0bb83f98e290402db9fcb6da74f773ca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,401 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#if !(UNITY_2018_3_OR_NEWER && NET_STANDARD_2_0)
using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack.Internal
{
internal struct ArgumentField
{
private readonly int i;
private readonly bool @ref;
private readonly ILGenerator il;
public ArgumentField(ILGenerator il, int i, bool @ref = false)
{
this.il = il;
this.i = i;
this.@ref = @ref;
}
public ArgumentField(ILGenerator il, int i, Type type)
{
this.il = il;
this.i = i;
TypeInfo ti = type.GetTypeInfo();
this.@ref = (ti.IsClass || ti.IsInterface || ti.IsAbstract) ? false : true;
}
public void EmitLoad()
{
if (this.@ref)
{
this.il.EmitLdarga(this.i);
}
else
{
this.il.EmitLdarg(this.i);
}
}
public void EmitLdarg()
{
this.il.EmitLdarg(this.i);
}
public void EmitLdarga()
{
this.il.EmitLdarga(this.i);
}
public void EmitStore()
{
this.il.EmitStarg(this.i);
}
}
/// <summary>
/// Provides optimized generation code and helpers.
/// </summary>
internal static class ILGeneratorExtensions
{
/// <summary>
/// Loads the local variable at a specific index onto the evaluation stack.
/// </summary>
public static void EmitLdloc(this ILGenerator il, int index)
{
switch (index)
{
case 0:
il.Emit(OpCodes.Ldloc_0);
break;
case 1:
il.Emit(OpCodes.Ldloc_1);
break;
case 2:
il.Emit(OpCodes.Ldloc_2);
break;
case 3:
il.Emit(OpCodes.Ldloc_3);
break;
default:
if (index <= 255)
{
il.Emit(OpCodes.Ldloc_S, (byte)index);
}
else
{
il.Emit(OpCodes.Ldloc, (short)index);
}
break;
}
}
public static void EmitLdloc(this ILGenerator il, LocalBuilder local)
{
EmitLdloc(il, local.LocalIndex);
}
/// <summary>
/// Pops the current value from the top of the evaluation stack and stores it in a the local variable list at a specified index.
/// </summary>
public static void EmitStloc(this ILGenerator il, int index)
{
switch (index)
{
case 0:
il.Emit(OpCodes.Stloc_0);
break;
case 1:
il.Emit(OpCodes.Stloc_1);
break;
case 2:
il.Emit(OpCodes.Stloc_2);
break;
case 3:
il.Emit(OpCodes.Stloc_3);
break;
default:
if (index <= 255)
{
il.Emit(OpCodes.Stloc_S, (byte)index);
}
else
{
il.Emit(OpCodes.Stloc, (short)index);
}
break;
}
}
public static void EmitStloc(this ILGenerator il, LocalBuilder local)
{
EmitStloc(il, local.LocalIndex);
}
/// <summary>
/// Loads the address of the local variable at a specific index onto the evaluation statck.
/// </summary>
public static void EmitLdloca(this ILGenerator il, int index)
{
if (index <= 255)
{
il.Emit(OpCodes.Ldloca_S, (byte)index);
}
else
{
il.Emit(OpCodes.Ldloca, (short)index);
}
}
public static void EmitLdloca(this ILGenerator il, LocalBuilder local)
{
EmitLdloca(il, local.LocalIndex);
}
public static void EmitTrue(this ILGenerator il)
{
EmitBoolean(il, true);
}
public static void EmitFalse(this ILGenerator il)
{
EmitBoolean(il, false);
}
public static void EmitBoolean(this ILGenerator il, bool value)
{
EmitLdc_I4(il, value ? 1 : 0);
}
/// <summary>
/// Pushes a supplied value of type int32 onto the evaluation stack as an int32.
/// </summary>
public static void EmitLdc_I4(this ILGenerator il, int value)
{
switch (value)
{
case -1:
il.Emit(OpCodes.Ldc_I4_M1);
break;
case 0:
il.Emit(OpCodes.Ldc_I4_0);
break;
case 1:
il.Emit(OpCodes.Ldc_I4_1);
break;
case 2:
il.Emit(OpCodes.Ldc_I4_2);
break;
case 3:
il.Emit(OpCodes.Ldc_I4_3);
break;
case 4:
il.Emit(OpCodes.Ldc_I4_4);
break;
case 5:
il.Emit(OpCodes.Ldc_I4_5);
break;
case 6:
il.Emit(OpCodes.Ldc_I4_6);
break;
case 7:
il.Emit(OpCodes.Ldc_I4_7);
break;
case 8:
il.Emit(OpCodes.Ldc_I4_8);
break;
default:
if (value >= -128 && value <= 127)
{
il.Emit(OpCodes.Ldc_I4_S, (sbyte)value);
}
else
{
il.Emit(OpCodes.Ldc_I4, value);
}
break;
}
}
public static void EmitUnboxOrCast(this ILGenerator il, Type type)
{
if (type.GetTypeInfo().IsValueType)
{
il.Emit(OpCodes.Unbox_Any, type);
}
else
{
il.Emit(OpCodes.Castclass, type);
}
}
public static void EmitBoxOrDoNothing(this ILGenerator il, Type type)
{
if (type.GetTypeInfo().IsValueType)
{
il.Emit(OpCodes.Box, type);
}
}
public static void EmitLdarg(this ILGenerator il, int index)
{
switch (index)
{
case 0:
il.Emit(OpCodes.Ldarg_0);
break;
case 1:
il.Emit(OpCodes.Ldarg_1);
break;
case 2:
il.Emit(OpCodes.Ldarg_2);
break;
case 3:
il.Emit(OpCodes.Ldarg_3);
break;
default:
if (index <= 255)
{
il.Emit(OpCodes.Ldarg_S, (byte)index);
}
else
{
il.Emit(OpCodes.Ldarg, index);
}
break;
}
}
public static void EmitLoadThis(this ILGenerator il)
{
EmitLdarg(il, 0);
}
public static void EmitLdarga(this ILGenerator il, int index)
{
if (index <= 255)
{
il.Emit(OpCodes.Ldarga_S, (byte)index);
}
else
{
il.Emit(OpCodes.Ldarga, index);
}
}
public static void EmitStarg(this ILGenerator il, int index)
{
if (index <= 255)
{
il.Emit(OpCodes.Starg_S, (byte)index);
}
else
{
il.Emit(OpCodes.Starg, index);
}
}
/// <summary>
/// Helper for Pop op.
/// </summary>
public static void EmitPop(this ILGenerator il, int count)
{
for (int i = 0; i < count; i++)
{
il.Emit(OpCodes.Pop);
}
}
public static void EmitCall(this ILGenerator il, MethodInfo methodInfo)
{
if (methodInfo.IsFinal || !methodInfo.IsVirtual)
{
il.Emit(OpCodes.Call, methodInfo);
}
else
{
il.Emit(OpCodes.Callvirt, methodInfo);
}
}
public static void EmitLdfld(this ILGenerator il, FieldInfo fieldInfo)
{
il.Emit(OpCodes.Ldfld, fieldInfo);
}
public static void EmitLdsfld(this ILGenerator il, FieldInfo fieldInfo)
{
il.Emit(OpCodes.Ldsfld, fieldInfo);
}
public static void EmitRet(this ILGenerator il)
{
il.Emit(OpCodes.Ret);
}
public static void EmitIntZeroReturn(this ILGenerator il)
{
il.EmitLdc_I4(0);
il.Emit(OpCodes.Ret);
}
public static void EmitNullReturn(this ILGenerator il)
{
il.Emit(OpCodes.Ldnull);
il.Emit(OpCodes.Ret);
}
public static void EmitULong(this ILGenerator il, ulong value)
{
il.Emit(OpCodes.Ldc_I8, unchecked((long)value));
}
public static void EmitThrowNotimplemented(this ILGenerator il)
{
il.Emit(OpCodes.Newobj, typeof(System.NotImplementedException).GetTypeInfo().DeclaredConstructors.First(x => x.GetParameters().Length == 0));
il.Emit(OpCodes.Throw);
}
/// <summary>for var i = 0, i ..., i++. </summary>
public static void EmitIncrementFor(this ILGenerator il, LocalBuilder conditionGreater, Action<LocalBuilder> emitBody)
{
Label loopBegin = il.DefineLabel();
Label condtionLabel = il.DefineLabel();
// var i = 0
LocalBuilder forI = il.DeclareLocal(typeof(int));
il.EmitLdc_I4(0);
il.EmitStloc(forI);
il.Emit(OpCodes.Br, condtionLabel);
il.MarkLabel(loopBegin);
emitBody(forI);
// i++
il.EmitLdloc(forI);
il.EmitLdc_I4(1);
il.Emit(OpCodes.Add);
il.EmitStloc(forI);
//// i < ***
il.MarkLabel(condtionLabel);
il.EmitLdloc(forI);
il.EmitLdloc(conditionGreater);
il.Emit(OpCodes.Blt, loopBegin);
}
}
}
#endif

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: a7fcc89bc1ce33b46b7e5d8bcaa7f0fa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,49 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Reflection;
using System.Runtime.CompilerServices;
namespace MessagePack.Internal
{
internal static class ReflectionExtensions
{
public static bool IsNullable(this System.Reflection.TypeInfo type)
{
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Nullable<>);
}
public static bool IsPublic(this System.Reflection.TypeInfo type)
{
return type.IsPublic;
}
public static bool IsAnonymous(this System.Reflection.TypeInfo type)
{
return type.GetCustomAttribute<CompilerGeneratedAttribute>() != null
&& type.IsGenericType && type.Name.Contains("AnonymousType")
&& (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$"))
&& (type.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic;
}
public static bool IsIndexer(this System.Reflection.PropertyInfo propertyInfo)
{
return propertyInfo.GetIndexParameters().Length > 0;
}
public static bool IsConstructedGenericType(this System.Reflection.TypeInfo type)
{
return type.AsType().IsConstructedGenericType;
}
public static MethodInfo GetGetMethod(this PropertyInfo propInfo)
{
return propInfo.GetMethod;
}
public static MethodInfo GetSetMethod(this PropertyInfo propInfo)
{
return propInfo.SetMethod;
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 82787207c36d0a4a98d7f53b49ba1576
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,573 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
/* Original license and copyright from file copied from https://github.com/AArnott/Nerdbank.Streams/blob/d656899be26d4d7c72c11c9232b4952c64a89bcb/src/Nerdbank.Streams/Sequence%601.cs
* Copyright (c) Andrew Arnott. All rights reserved.
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
*/
using System;
using System.Buffers;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Nerdbank.Streams
{
/// <summary>
/// Manages a sequence of elements, readily castable as a <see cref="ReadOnlySequence{T}"/>.
/// </summary>
/// <typeparam name="T">The type of element stored by the sequence.</typeparam>
/// <remarks>
/// Instance members are not thread-safe.
/// </remarks>
[DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")]
internal class Sequence<T> : IBufferWriter<T>, IDisposable
{
private static readonly int DefaultLengthFromArrayPool = 1 + (4095 / Marshal.SizeOf<T>());
private readonly Stack<SequenceSegment> segmentPool = new Stack<SequenceSegment>();
private readonly MemoryPool<T> memoryPool;
private readonly ArrayPool<T> arrayPool;
private SequenceSegment first;
private SequenceSegment last;
/// <summary>
/// Initializes a new instance of the <see cref="Sequence{T}"/> class
/// that uses a private <see cref="ArrayPool{T}"/> for recycling arrays.
/// </summary>
public Sequence()
: this(ArrayPool<T>.Create())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Sequence{T}"/> class.
/// </summary>
/// <param name="memoryPool">The pool to use for recycling backing arrays.</param>
public Sequence(MemoryPool<T> memoryPool)
{
Requires.NotNull(memoryPool, nameof(memoryPool));
this.memoryPool = memoryPool;
}
/// <summary>
/// Initializes a new instance of the <see cref="Sequence{T}"/> class.
/// </summary>
/// <param name="arrayPool">The pool to use for recycling backing arrays.</param>
public Sequence(ArrayPool<T> arrayPool)
{
Requires.NotNull(arrayPool, nameof(arrayPool));
this.arrayPool = arrayPool;
}
/// <summary>
/// Gets or sets the minimum length for any array allocated as a segment in the sequence.
/// Any non-positive value allows the pool to determine the length of the array.
/// </summary>
/// <value>The default value is 0.</value>
/// <remarks>
/// <para>
/// Each time <see cref="GetSpan(int)"/> or <see cref="GetMemory(int)"/> is called,
/// previously allocated memory is used if it is large enough to satisfy the length demand.
/// If new memory must be allocated, the argument to one of these methods typically dictate
/// the length of array to allocate. When the caller uses very small values (just enough for its immediate need)
/// but the high level scenario can predict that a large amount of memory will be ultimately required,
/// it can be advisable to set this property to a value such that just a few larger arrays are allocated
/// instead of many small ones.
/// </para>
/// <para>
/// 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>
/// </remarks>
public int MinimumSpanLength { get; set; } = 0;
/// <summary>
/// Gets this sequence expressed as a <see cref="ReadOnlySequence{T}"/>.
/// </summary>
/// <returns>A read only sequence representing the data in this object.</returns>
public ReadOnlySequence<T> AsReadOnlySequence => this;
/// <summary>
/// Gets the length of the sequence.
/// </summary>
public long Length => this.AsReadOnlySequence.Length;
/// <summary>
/// Gets the value to display in a debugger datatip.
/// </summary>
private string DebuggerDisplay => $"Length: {this.AsReadOnlySequence.Length}";
/// <summary>
/// Expresses this sequence as a <see cref="ReadOnlySequence{T}"/>.
/// </summary>
/// <param name="sequence">The sequence to convert.</param>
public static implicit operator ReadOnlySequence<T>(Sequence<T> sequence)
{
return sequence.first != null
? new ReadOnlySequence<T>(sequence.first, sequence.first.Start, sequence.last, sequence.last.End)
: ReadOnlySequence<T>.Empty;
}
/// <summary>
/// Removes all elements from the sequence from its beginning to the specified position,
/// considering that data to have been fully processed.
/// </summary>
/// <param name="position">
/// The position of the first element that has not yet been processed.
/// This is typically <see cref="ReadOnlySequence{T}.End"/> after reading all elements from that instance.
/// </param>
public void AdvanceTo(SequencePosition position)
{
var firstSegment = (SequenceSegment)position.GetObject();
int firstIndex = position.GetInteger();
// Before making any mutations, confirm that the block specified belongs to this sequence.
var current = this.first;
while (current != firstSegment && current != null)
{
current = current.Next;
}
Requires.Argument(current != null, nameof(position), "Position does not represent a valid position in this sequence.");
// Also confirm that the position is not a prior position in the block.
Requires.Argument(firstIndex >= current.Start, nameof(position), "Position must not be earlier than current position.");
// Now repeat the loop, performing the mutations.
current = this.first;
while (current != firstSegment)
{
current = this.RecycleAndGetNext(current);
}
firstSegment.AdvanceTo(firstIndex);
if (firstSegment.Length == 0)
{
firstSegment = this.RecycleAndGetNext(firstSegment);
}
this.first = firstSegment;
if (this.first == null)
{
this.last = null;
}
}
/// <summary>
/// Advances the sequence to include the specified number of elements initialized into memory
/// returned by a prior call to <see cref="GetMemory(int)"/>.
/// </summary>
/// <param name="count">The number of elements written into memory.</param>
public void Advance(int count)
{
SequenceSegment last = this.last;
Verify.Operation(last != null, "Cannot advance before acquiring memory.");
last.Advance(count);
}
/// <summary>
/// Gets writable memory that can be initialized and added to the sequence via a subsequent call to <see cref="Advance(int)"/>.
/// </summary>
/// <param name="sizeHint">The size of the memory required, or 0 to just get a convenient (non-empty) buffer.</param>
/// <returns>The requested memory.</returns>
public Memory<T> GetMemory(int sizeHint) => this.GetSegment(sizeHint).RemainingMemory;
/// <summary>
/// Gets writable memory that can be initialized and added to the sequence via a subsequent call to <see cref="Advance(int)"/>.
/// </summary>
/// <param name="sizeHint">The size of the memory required, or 0 to just get a convenient (non-empty) buffer.</param>
/// <returns>The requested memory.</returns>
public Span<T> GetSpan(int sizeHint) => this.GetSegment(sizeHint).RemainingSpan;
/// <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.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public void Dispose() => this.Reset();
/// <summary>
/// Clears the entire sequence and recycles associated memory into pools.
/// This invalidates any <see cref="ReadOnlySequence{T}"/> previously produced by this instance.
/// </summary>
public void Reset()
{
var current = this.first;
while (current != null)
{
current = this.RecycleAndGetNext(current);
}
this.first = this.last = null;
}
private SequenceSegment GetSegment(int sizeHint)
{
Requires.Range(sizeHint >= 0, nameof(sizeHint));
int? minBufferSize = null;
if (sizeHint == 0)
{
if (this.last == null || this.last.WritableBytes == 0)
{
// We're going to need more memory. Take whatever size the pool wants to give us.
minBufferSize = -1;
}
}
else
{
sizeHint = Math.Max(this.MinimumSpanLength, sizeHint);
if (this.last == null || this.last.WritableBytes < sizeHint)
{
minBufferSize = sizeHint;
}
}
if (minBufferSize.HasValue)
{
var 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));
}
else
{
segment.Assign(this.memoryPool.Rent(minBufferSize.Value));
}
this.Append(segment);
}
return this.last;
}
private void Append(SequenceSegment segment)
{
if (this.last == null)
{
this.first = this.last = segment;
}
else
{
if (this.last.Length > 0)
{
// Add a new block.
this.last.SetNext(segment);
}
else
{
// The last block is completely unused. Replace it instead of appending to it.
var current = this.first;
if (this.first != this.last)
{
while (current.Next != this.last)
{
current = current.Next;
}
}
else
{
this.first = segment;
}
current.SetNext(segment);
this.RecycleAndGetNext(this.last);
}
this.last = segment;
}
}
private SequenceSegment RecycleAndGetNext(SequenceSegment segment)
{
var recycledSegment = segment;
segment = segment.Next;
recycledSegment.ResetMemory(this.arrayPool);
this.segmentPool.Push(recycledSegment);
return segment;
}
private class SequenceSegment : ReadOnlySequenceSegment<T>
{
/// <summary>
/// A value indicating whether the element is a value type.
/// </summary>
private static readonly bool IsValueTypeElement = typeof(T).GetTypeInfo().IsValueType;
/// <summary>
/// Gets the backing array, when using an <see cref="ArrayPool{T}"/> instead of a <see cref="MemoryPool{T}"/>.
/// </summary>
private T[] array;
/// <summary>
/// Gets the position within <see cref="ReadOnlySequenceSegment{T}.Memory"/> where the data starts.
/// </summary>
/// <remarks>This may be nonzero as a result of calling <see cref="Sequence{T}.AdvanceTo(SequencePosition)"/>.</remarks>
internal int Start { get; private set; }
/// <summary>
/// Gets the position within <see cref="ReadOnlySequenceSegment{T}.Memory"/> where the data ends.
/// </summary>
internal int End { get; private set; }
/// <summary>
/// Gets the tail of memory that has not yet been committed.
/// </summary>
internal Memory<T> RemainingMemory => this.AvailableMemory.Slice(this.End);
/// <summary>
/// Gets the tail of memory that has not yet been committed.
/// </summary>
internal Span<T> RemainingSpan => this.AvailableMemory.Span.Slice(this.End);
/// <summary>
/// Gets the tracker for the underlying array for this segment, which can be used to recycle the array when we're disposed of.
/// Will be <c>null</c> if using an array pool, in which case the memory is held by <see cref="array"/>.
/// </summary>
internal IMemoryOwner<T> MemoryOwner { get; private set; }
/// <summary>
/// Gets the full memory owned by the <see cref="MemoryOwner"/>.
/// </summary>
internal Memory<T> AvailableMemory => this.array ?? this.MemoryOwner?.Memory ?? default;
/// <summary>
/// Gets the number of elements that are committed in this segment.
/// </summary>
internal int Length => this.End - this.Start;
/// <summary>
/// Gets the amount of writable bytes in this segment.
/// It is the amount of bytes between <see cref="Length"/> and <see cref="End"/>.
/// </summary>
internal int WritableBytes => this.AvailableMemory.Length - this.End;
/// <summary>
/// Gets or sets the next segment in the singly linked list of segments.
/// </summary>
internal new SequenceSegment Next
{
get => (SequenceSegment)base.Next;
set => base.Next = value;
}
/// <summary>
/// Assigns this (recyclable) segment a new area in memory.
/// </summary>
/// <param name="memoryOwner">The memory and a means to recycle it.</param>
internal void Assign(IMemoryOwner<T> memoryOwner)
{
this.MemoryOwner = memoryOwner;
this.Memory = memoryOwner.Memory;
}
/// <summary>
/// Assigns this (recyclable) segment a new area in memory.
/// </summary>
/// <param name="array">An array drawn from an <see cref="ArrayPool{T}"/>.</param>
internal void Assign(T[] array)
{
this.array = array;
this.Memory = array;
}
/// <summary>
/// Clears all fields in preparation to recycle this instance.
/// </summary>
internal void ResetMemory(ArrayPool<T> arrayPool)
{
this.ClearReferences(this.Start, this.End);
this.Memory = default;
this.Next = null;
this.RunningIndex = 0;
this.Start = 0;
this.End = 0;
if (this.array != null)
{
arrayPool.Return(this.array);
this.array = null;
}
else
{
this.MemoryOwner?.Dispose();
this.MemoryOwner = null;
}
}
/// <summary>
/// Adds a new segment after this one.
/// </summary>
/// <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);
}
/// <summary>
/// Commits more elements as written in this segment.
/// </summary>
/// <param name="count">The number of elements written.</param>
internal void Advance(int count)
{
Requires.Range(count >= 0 && this.End + count <= this.Memory.Length, nameof(count));
this.End += count;
}
/// <summary>
/// Removes some elements from the start of this segment.
/// </summary>
/// <param name="offset">The number of elements to ignore from the start of the underlying array.</param>
internal void AdvanceTo(int offset)
{
Debug.Assert(offset >= this.Start, "Trying to rewind.");
this.ClearReferences(this.Start, offset - this.Start);
this.Start = offset;
}
private void ClearReferences(int startIndex, int length)
{
// If we store references, clear them to allow the objects to be GC'd.
if (!IsValueTypeElement)
{
this.AvailableMemory.Span.Slice(startIndex, length).Fill(default);
}
}
}
}
internal static class Requires
{
/// <summary>
/// Throws an <see cref="ArgumentOutOfRangeException"/> if a condition does not evaluate to true.
/// </summary>
[DebuggerStepThrough]
public static void Range(bool condition, string parameterName, string message = null)
{
if (!condition)
{
FailRange(parameterName, message);
}
}
/// <summary>
/// Throws an <see cref="ArgumentOutOfRangeException"/> if a condition does not evaluate to true.
/// </summary>
/// <returns>Nothing. This method always throws.</returns>
[DebuggerStepThrough]
public static Exception FailRange(string parameterName, string message = null)
{
if (string.IsNullOrEmpty(message))
{
throw new ArgumentOutOfRangeException(parameterName);
}
else
{
throw new ArgumentOutOfRangeException(parameterName, message);
}
}
/// <summary>
/// Throws an exception if the specified parameter's value is null.
/// </summary>
/// <typeparam name="T">The type of the parameter.</typeparam>
/// <param name="value">The value of the argument.</param>
/// <param name="parameterName">The name of the parameter to include in any thrown exception.</param>
/// <returns>The value of the parameter.</returns>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="value"/> is <c>null</c>.</exception>
[DebuggerStepThrough]
public static T NotNull<T>(T value, string parameterName)
where T : class // ensures value-types aren't passed to a null checking method
{
if (value == null)
{
throw new ArgumentNullException(parameterName);
}
return value;
}
/// <summary>
/// Throws an ArgumentException if a condition does not evaluate to true.
/// </summary>
[DebuggerStepThrough]
public static void Argument(bool condition, string parameterName, string message)
{
if (!condition)
{
throw new ArgumentException(message, parameterName);
}
}
/// <summary>
/// Throws an ArgumentException if a condition does not evaluate to true.
/// </summary>
[DebuggerStepThrough]
public static void Argument(bool condition, string parameterName, string message, object arg1)
{
if (!condition)
{
throw new ArgumentException(String.Format(message, arg1), parameterName);
}
}
/// <summary>
/// Throws an ArgumentException if a condition does not evaluate to true.
/// </summary>
[DebuggerStepThrough]
public static void Argument(bool condition, string parameterName, string message, object arg1, object arg2)
{
if (!condition)
{
throw new ArgumentException(String.Format(message, arg1, arg2), parameterName);
}
}
/// <summary>
/// Throws an ArgumentException if a condition does not evaluate to true.
/// </summary>
[DebuggerStepThrough]
public static void Argument(bool condition, string parameterName, string message, params object[] args)
{
if (!condition)
{
throw new ArgumentException(String.Format(message, args), parameterName);
}
}
}
/// <summary>
/// Common runtime checks that throw exceptions upon failure.
/// </summary>
internal static partial class Verify
{
/// <summary>
/// Throws an <see cref="InvalidOperationException"/> if a condition is false.
/// </summary>
[DebuggerStepThrough]
internal static void Operation(bool condition, string message)
{
if (!condition)
{
throw new InvalidOperationException(message);
}
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 19e730b2bfc50b981bdcd41c703daab2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,246 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Runtime.CompilerServices;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack.Internal
{
/// <summary>
/// A dictionary where <see cref="Type"/> is the key, and a configurable <typeparamref name="TValue"/> type
/// that is thread-safe to read and write, allowing concurrent reads and exclusive writes.
/// </summary>
/// <typeparam name="TValue">The type of value stored in the dictionary.</typeparam>
internal class ThreadsafeTypeKeyHashTable<TValue>
{
private Entry[] buckets;
private int size; // only use in writer lock
private readonly object writerLock = new object();
private readonly float loadFactor;
// IEqualityComparer.Equals is overhead if key only Type, don't use it.
//// readonly IEqualityComparer<TKey> comparer;
public ThreadsafeTypeKeyHashTable(int capacity = 4, float loadFactor = 0.75f)
{
var tableSize = CalculateCapacity(capacity, loadFactor);
this.buckets = new Entry[tableSize];
this.loadFactor = loadFactor;
}
public bool TryAdd(Type key, TValue value)
{
return this.TryAdd(key, _ => value); // create lambda capture
}
public bool TryAdd(Type key, Func<Type, TValue> valueFactory)
{
return this.TryAddInternal(key, valueFactory, out TValue _);
}
private bool TryAddInternal(Type key, Func<Type, TValue> valueFactory, out TValue resultingValue)
{
lock (this.writerLock)
{
var nextCapacity = CalculateCapacity(this.size + 1, this.loadFactor);
if (this.buckets.Length < nextCapacity)
{
// rehash
var nextBucket = new Entry[nextCapacity];
for (int i = 0; i < this.buckets.Length; i++)
{
Entry e = this.buckets[i];
while (e != null)
{
var newEntry = new Entry { Key = e.Key, Value = e.Value, Hash = e.Hash };
this.AddToBuckets(nextBucket, key, newEntry, null, out resultingValue);
e = e.Next;
}
}
// add entry(if failed to add, only do resize)
var successAdd = this.AddToBuckets(nextBucket, key, null, valueFactory, out resultingValue);
// replace field(threadsafe for read)
VolatileWrite(ref this.buckets, nextBucket);
if (successAdd)
{
this.size++;
}
return successAdd;
}
else
{
// add entry(insert last is thread safe for read)
var successAdd = this.AddToBuckets(this.buckets, key, null, valueFactory, out resultingValue);
if (successAdd)
{
this.size++;
}
return successAdd;
}
}
}
private bool AddToBuckets(Entry[] buckets, Type newKey, Entry newEntryOrNull, Func<Type, TValue> valueFactory, out TValue resultingValue)
{
var h = (newEntryOrNull != null) ? newEntryOrNull.Hash : newKey.GetHashCode();
if (buckets[h & (buckets.Length - 1)] == null)
{
if (newEntryOrNull != null)
{
resultingValue = newEntryOrNull.Value;
VolatileWrite(ref buckets[h & (buckets.Length - 1)], newEntryOrNull);
}
else
{
resultingValue = valueFactory(newKey);
VolatileWrite(ref buckets[h & (buckets.Length - 1)], new Entry { Key = newKey, Value = resultingValue, Hash = h });
}
}
else
{
Entry searchLastEntry = buckets[h & (buckets.Length - 1)];
while (true)
{
if (searchLastEntry.Key == newKey)
{
resultingValue = searchLastEntry.Value;
return false;
}
if (searchLastEntry.Next == null)
{
if (newEntryOrNull != null)
{
resultingValue = newEntryOrNull.Value;
VolatileWrite(ref searchLastEntry.Next, newEntryOrNull);
}
else
{
resultingValue = valueFactory(newKey);
VolatileWrite(ref searchLastEntry.Next, new Entry { Key = newKey, Value = resultingValue, Hash = h });
}
break;
}
searchLastEntry = searchLastEntry.Next;
}
}
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryGetValue(Type key, out TValue value)
{
Entry[] table = this.buckets;
var hash = key.GetHashCode();
Entry entry = table[hash & table.Length - 1];
while (entry != null)
{
if (entry.Key == key)
{
value = entry.Value;
return true;
}
entry = entry.Next;
}
value = default(TValue);
return false;
}
public TValue GetOrAdd(Type key, Func<Type, TValue> valueFactory)
{
TValue v;
if (this.TryGetValue(key, out v))
{
return v;
}
this.TryAddInternal(key, valueFactory, out v);
return v;
}
private static int CalculateCapacity(int collectionSize, float loadFactor)
{
var initialCapacity = (int)(((float)collectionSize) / loadFactor);
var capacity = 1;
while (capacity < initialCapacity)
{
capacity <<= 1;
}
if (capacity < 8)
{
return 8;
}
return capacity;
}
private static void VolatileWrite(ref Entry location, Entry value)
{
#if !UNITY_2018_3_OR_NEWER
System.Threading.Volatile.Write(ref location, value);
#elif UNITY_2018_3_OR_NEWER || NET_4_6
System.Threading.Volatile.Write(ref location, value);
#else
System.Threading.Thread.MemoryBarrier();
location = value;
#endif
}
private static void VolatileWrite(ref Entry[] location, Entry[] value)
{
#if !UNITY_2018_3_OR_NEWER
System.Threading.Volatile.Write(ref location, value);
#elif UNITY_2018_3_OR_NEWER || NET_4_6
System.Threading.Volatile.Write(ref location, value);
#else
System.Threading.Thread.MemoryBarrier();
location = value;
#endif
}
private class Entry
{
#pragma warning disable SA1401 // Fields should be private
internal Type Key;
internal TValue Value;
internal int Hash;
internal Entry Next;
#pragma warning restore SA1401 // Fields should be private
// debug only
public override string ToString()
{
return this.Key + "(" + this.Count() + ")";
}
private int Count()
{
var count = 1;
Entry n = this;
while (n.Next != null)
{
count++;
n = n.Next;
}
return count;
}
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 517dd6b1707013015b06ebfbeeea1f2c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,430 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Globalization;
using System.IO;
using System.Text;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack
{
/* simple, tiny JSON reader for MessagePackSerializer.FromJson.
* this is simple, compact and enough fast but not optimized extremely. */
internal enum TinyJsonToken
{
None,
StartObject, // {
EndObject, // }
StartArray, // [
EndArray, // ]
Number, // -0~9
String, // "___"
True, // true
False, // false
Null, // null
}
internal enum ValueType : byte
{
Null,
True,
False,
Double,
Long,
ULong,
Decimal,
String,
}
public class TinyJsonException : MessagePackSerializationException
{
public TinyJsonException(string message)
: base(message)
{
}
}
internal class TinyJsonReader : IDisposable
{
private readonly TextReader reader;
private readonly bool disposeInnerReader;
private StringBuilder reusableBuilder;
public TinyJsonToken TokenType { get; private set; }
public ValueType ValueType { get; private set; }
public double DoubleValue { get; private set; }
public long LongValue { get; private set; }
public ulong ULongValue { get; private set; }
public decimal DecimalValue { get; private set; }
public string StringValue { get; private set; }
public TinyJsonReader(TextReader reader, bool disposeInnerReader = true)
{
this.reader = reader;
this.disposeInnerReader = disposeInnerReader;
}
public bool Read()
{
this.ReadNextToken();
this.ReadValue();
return this.TokenType != TinyJsonToken.None;
}
public void Dispose()
{
if (this.reader != null && this.disposeInnerReader)
{
this.reader.Dispose();
}
this.TokenType = TinyJsonToken.None;
this.ValueType = ValueType.Null;
}
private void SkipWhiteSpace()
{
var c = this.reader.Peek();
while (c != -1 && Char.IsWhiteSpace((char)c))
{
this.reader.Read();
c = this.reader.Peek();
}
}
private char ReadChar()
{
return (char)this.reader.Read();
}
private static bool IsWordBreak(char c)
{
switch (c)
{
case ' ':
case '{':
case '}':
case '[':
case ']':
case ',':
case ':':
case '\"':
return true;
default:
return false;
}
}
private void ReadNextToken()
{
this.SkipWhiteSpace();
var intChar = this.reader.Peek();
if (intChar == -1)
{
this.TokenType = TinyJsonToken.None;
return;
}
var c = (char)intChar;
switch (c)
{
case '{':
this.TokenType = TinyJsonToken.StartObject;
return;
case '}':
this.TokenType = TinyJsonToken.EndObject;
return;
case '[':
this.TokenType = TinyJsonToken.StartArray;
return;
case ']':
this.TokenType = TinyJsonToken.EndArray;
return;
case '"':
this.TokenType = TinyJsonToken.String;
return;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
this.TokenType = TinyJsonToken.Number;
return;
case 't':
this.TokenType = TinyJsonToken.True;
return;
case 'f':
this.TokenType = TinyJsonToken.False;
return;
case 'n':
this.TokenType = TinyJsonToken.Null;
return;
case ',':
case ':':
this.reader.Read();
this.ReadNextToken();
return;
default:
throw new TinyJsonException("Invalid String:" + c);
}
}
private void ReadValue()
{
this.ValueType = ValueType.Null;
switch (this.TokenType)
{
case TinyJsonToken.None:
break;
case TinyJsonToken.StartObject:
case TinyJsonToken.EndObject:
case TinyJsonToken.StartArray:
case TinyJsonToken.EndArray:
this.reader.Read();
break;
case TinyJsonToken.Number:
this.ReadNumber();
break;
case TinyJsonToken.String:
this.ReadString();
break;
case TinyJsonToken.True:
if (this.ReadChar() != 't')
{
throw new TinyJsonException("Invalid Token");
}
if (this.ReadChar() != 'r')
{
throw new TinyJsonException("Invalid Token");
}
if (this.ReadChar() != 'u')
{
throw new TinyJsonException("Invalid Token");
}
if (this.ReadChar() != 'e')
{
throw new TinyJsonException("Invalid Token");
}
this.ValueType = ValueType.True;
break;
case TinyJsonToken.False:
if (this.ReadChar() != 'f')
{
throw new TinyJsonException("Invalid Token");
}
if (this.ReadChar() != 'a')
{
throw new TinyJsonException("Invalid Token");
}
if (this.ReadChar() != 'l')
{
throw new TinyJsonException("Invalid Token");
}
if (this.ReadChar() != 's')
{
throw new TinyJsonException("Invalid Token");
}
if (this.ReadChar() != 'e')
{
throw new TinyJsonException("Invalid Token");
}
this.ValueType = ValueType.False;
break;
case TinyJsonToken.Null:
if (this.ReadChar() != 'n')
{
throw new TinyJsonException("Invalid Token");
}
if (this.ReadChar() != 'u')
{
throw new TinyJsonException("Invalid Token");
}
if (this.ReadChar() != 'l')
{
throw new TinyJsonException("Invalid Token");
}
if (this.ReadChar() != 'l')
{
throw new TinyJsonException("Invalid Token");
}
this.ValueType = ValueType.Null;
break;
default:
throw new MessagePackSerializationException("InvalidTokenState:" + this.TokenType);
}
}
private void ReadNumber()
{
StringBuilder numberWord;
if (this.reusableBuilder == null)
{
this.reusableBuilder = new StringBuilder();
numberWord = this.reusableBuilder;
}
else
{
numberWord = this.reusableBuilder;
numberWord.Length = 0; // Clear
}
var isDouble = false;
var intChar = this.reader.Peek();
while (intChar != -1 && !IsWordBreak((char)intChar))
{
var c = this.ReadChar();
numberWord.Append(c);
if (c == '.' || c == 'e' || c == 'E')
{
isDouble = true;
}
intChar = this.reader.Peek();
}
var number = numberWord.ToString();
if (isDouble)
{
double parsedDouble;
Double.TryParse(number, NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite | NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands | NumberStyles.AllowExponent, System.Globalization.CultureInfo.InvariantCulture, out parsedDouble);
this.ValueType = ValueType.Double;
this.DoubleValue = parsedDouble;
}
else
{
long parsedInt;
if (Int64.TryParse(number, NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out parsedInt))
{
this.ValueType = ValueType.Long;
this.LongValue = parsedInt;
return;
}
ulong parsedULong;
if (ulong.TryParse(number, NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out parsedULong))
{
this.ValueType = ValueType.ULong;
this.ULongValue = parsedULong;
return;
}
Decimal parsedDecimal;
if (decimal.TryParse(number, NumberStyles.Number, System.Globalization.CultureInfo.InvariantCulture, out parsedDecimal))
{
this.ValueType = ValueType.Decimal;
this.DecimalValue = parsedDecimal;
return;
}
}
}
private void ReadString()
{
this.reader.Read(); // skip ["]
StringBuilder sb;
if (this.reusableBuilder == null)
{
this.reusableBuilder = new StringBuilder();
sb = this.reusableBuilder;
}
else
{
sb = this.reusableBuilder;
sb.Length = 0; // Clear
}
while (true)
{
if (this.reader.Peek() == -1)
{
throw new TinyJsonException("Invalid Json String");
}
var c = this.ReadChar();
switch (c)
{
case '"': // endtoken
goto END;
case '\\': // escape character
if (this.reader.Peek() == -1)
{
throw new TinyJsonException("Invalid Json String");
}
c = this.ReadChar();
switch (c)
{
case '"':
case '\\':
case '/':
sb.Append(c);
break;
case 'b':
sb.Append('\b');
break;
case 'f':
sb.Append('\f');
break;
case 'n':
sb.Append('\n');
break;
case 'r':
sb.Append('\r');
break;
case 't':
sb.Append('\t');
break;
case 'u':
var hex = new char[4];
hex[0] = this.ReadChar();
hex[1] = this.ReadChar();
hex[2] = this.ReadChar();
hex[3] = this.ReadChar();
sb.Append((char)Convert.ToInt32(new string(hex), 16));
break;
}
break;
default: // string
sb.Append(c);
break;
}
}
END:
this.ValueType = ValueType.String;
this.StringValue = sb.ToString();
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: adc1157b80c30cf2d8845336b9c1cfc2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,170 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#if !UNITY_2018_3_OR_NEWER
using System;
using System.Runtime.CompilerServices;
namespace MessagePack.Internal
{
/* for string key property name write optimization. */
public static class UnsafeMemory
{
public static readonly bool Is32Bit = IntPtr.Size == 4;
}
public static partial class UnsafeMemory32
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void WriteRaw1(ref MessagePackWriter writer, ReadOnlySpan<byte> src)
{
Span<byte> dst = writer.GetSpan(src.Length);
fixed (byte* pSrc = &src[0])
fixed (byte* pDst = &dst[0])
{
*(byte*)pDst = *(byte*)pSrc;
}
writer.Advance(src.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void WriteRaw2(ref MessagePackWriter writer, ReadOnlySpan<byte> src)
{
Span<byte> dst = writer.GetSpan(src.Length);
fixed (byte* pSrc = &src[0])
fixed (byte* pDst = &dst[0])
{
*(short*)pDst = *(short*)pSrc;
}
writer.Advance(src.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void WriteRaw3(ref MessagePackWriter writer, ReadOnlySpan<byte> src)
{
Span<byte> dst = writer.GetSpan(src.Length);
fixed (byte* pSrc = &src[0])
fixed (byte* pDst = &dst[0])
{
*(byte*)pDst = *(byte*)pSrc;
*(short*)(pDst + 1) = *(short*)(pSrc + 1);
}
writer.Advance(src.Length);
}
}
public static partial class UnsafeMemory64
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void WriteRaw1(ref MessagePackWriter writer, ReadOnlySpan<byte> src)
{
Span<byte> dst = writer.GetSpan(src.Length);
fixed (byte* pSrc = &src[0])
fixed (byte* pDst = &dst[0])
{
*(byte*)pDst = *(byte*)pSrc;
}
writer.Advance(src.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void WriteRaw2(ref MessagePackWriter writer, ReadOnlySpan<byte> src)
{
Span<byte> dst = writer.GetSpan(src.Length);
fixed (byte* pSrc = &src[0])
fixed (byte* pDst = &dst[0])
{
*(short*)pDst = *(short*)pSrc;
}
writer.Advance(src.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void WriteRaw3(ref MessagePackWriter writer, ReadOnlySpan<byte> src)
{
Span<byte> dst = writer.GetSpan(src.Length);
fixed (byte* pSrc = &src[0])
fixed (byte* pDst = &dst[0])
{
*(byte*)pDst = *(byte*)pSrc;
*(short*)(pDst + 1) = *(short*)(pSrc + 1);
}
writer.Advance(src.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void WriteRaw4(ref MessagePackWriter writer, ReadOnlySpan<byte> src)
{
Span<byte> dst = writer.GetSpan(src.Length);
fixed (byte* pSrc = &src[0])
fixed (byte* pDst = &dst[0])
{
*(int*)(pDst + 0) = *(int*)(pSrc + 0);
}
writer.Advance(src.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void WriteRaw5(ref MessagePackWriter writer, ReadOnlySpan<byte> src)
{
Span<byte> dst = writer.GetSpan(src.Length);
fixed (byte* pSrc = &src[0])
fixed (byte* pDst = &dst[0])
{
*(int*)(pDst + 0) = *(int*)(pSrc + 0);
*(int*)(pDst + 1) = *(int*)(pSrc + 1);
}
writer.Advance(src.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void WriteRaw6(ref MessagePackWriter writer, ReadOnlySpan<byte> src)
{
Span<byte> dst = writer.GetSpan(src.Length);
fixed (byte* pSrc = &src[0])
fixed (byte* pDst = &dst[0])
{
*(int*)(pDst + 0) = *(int*)(pSrc + 0);
*(int*)(pDst + 2) = *(int*)(pSrc + 2);
}
writer.Advance(src.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void WriteRaw7(ref MessagePackWriter writer, ReadOnlySpan<byte> src)
{
Span<byte> dst = writer.GetSpan(src.Length);
fixed (byte* pSrc = &src[0])
fixed (byte* pDst = &dst[0])
{
*(int*)(pDst + 0) = *(int*)(pSrc + 0);
*(int*)(pDst + 3) = *(int*)(pSrc + 3);
}
writer.Advance(src.Length);
}
}
}
#endif

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 2126473180c3a7d3a8860c4fd8aa4183
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: c633d9a494df48a45b82671c008a72a1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,94 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace MessagePack.LZ4
{
internal partial class LZ4Codec
{
#if UNITY_2018_3_OR_NEWER
// use 'Safe' code for Unity because in IL2CPP gots strange behaviour.
public static int Encode(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int outputLength)
{
if (IntPtr.Size == 4)
{
return LZ4Codec.Encode32Safe(input, inputOffset, inputLength, output, outputOffset, outputLength);
}
else
{
return LZ4Codec.Encode64Safe(input, inputOffset, inputLength, output, outputOffset, outputLength);
}
}
public static int Decode(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int outputLength)
{
if (IntPtr.Size == 4)
{
return LZ4Codec.Decode32Safe(input, inputOffset, inputLength, output, outputOffset, outputLength);
}
else
{
return LZ4Codec.Decode64Safe(input, inputOffset, inputLength, output, outputOffset, outputLength);
}
}
#endif
internal static class HashTablePool
{
[ThreadStatic]
private static ushort[] ushortPool;
[ThreadStatic]
private static uint[] uintPool;
[ThreadStatic]
private static int[] intPool;
public static ushort[] GetUShortHashTablePool()
{
if (ushortPool == null)
{
ushortPool = new ushort[HASH64K_TABLESIZE];
}
else
{
Array.Clear(ushortPool, 0, ushortPool.Length);
}
return ushortPool;
}
public static uint[] GetUIntHashTablePool()
{
if (uintPool == null)
{
uintPool = new uint[HASH_TABLESIZE];
}
else
{
Array.Clear(uintPool, 0, uintPool.Length);
}
return uintPool;
}
public static int[] GetIntHashTablePool()
{
if (intPool == null)
{
intPool = new int[HASH_TABLESIZE];
}
else
{
Array.Clear(intPool, 0, intPool.Length);
}
return intPool;
}
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: f33bc878911a8855d8df41dd514c5a42
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,467 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#if UNITY_2018_3_OR_NEWER
#region license
/*
Copyright (c) 2013, Milosz Krajewski
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#endregion
using System;
using System.Diagnostics;
namespace MessagePack.LZ4
{
/// <summary>Safe LZ4 codec.</summary>
internal partial class LZ4Codec
{
#region Helper
[Conditional("DEBUG")]
private static void Assert(bool condition, string errorMessage)
{
if (!condition)
{
throw new ArgumentException(errorMessage);
}
Debug.Assert(condition, errorMessage);
}
#endregion
#region Byte manipulation
internal static void Poke2(byte[] buffer, int offset, ushort value)
{
buffer[offset] = (byte)value;
buffer[offset + 1] = (byte)(value >> 8);
}
internal static ushort Peek2(byte[] buffer, int offset)
{
// NOTE: It's faster than BitConverter.ToUInt16 (suprised? me too)
return (ushort)(((uint)buffer[offset]) | ((uint)buffer[offset + 1] << 8));
}
internal static uint Peek4(byte[] buffer, int offset)
{
// NOTE: It's faster than BitConverter.ToUInt32 (suprised? me too)
return
((uint)buffer[offset]) |
((uint)buffer[offset + 1] << 8) |
((uint)buffer[offset + 2] << 16) |
((uint)buffer[offset + 3] << 24);
}
private static uint Xor4(byte[] buffer, int offset1, int offset2)
{
// return Peek4(buffer, offset1) ^ Peek4(buffer, offset2);
var value1 =
((uint)buffer[offset1]) |
((uint)buffer[offset1 + 1] << 8) |
((uint)buffer[offset1 + 2] << 16) |
((uint)buffer[offset1 + 3] << 24);
var value2 =
((uint)buffer[offset2]) |
((uint)buffer[offset2 + 1] << 8) |
((uint)buffer[offset2 + 2] << 16) |
((uint)buffer[offset2 + 3] << 24);
return value1 ^ value2;
}
private static ulong Xor8(byte[] buffer, int offset1, int offset2)
{
// return Peek8(buffer, offset1) ^ Peek8(buffer, offset2);
var value1 =
((ulong)buffer[offset1]) |
((ulong)buffer[offset1 + 1] << 8) |
((ulong)buffer[offset1 + 2] << 16) |
((ulong)buffer[offset1 + 3] << 24) |
((ulong)buffer[offset1 + 4] << 32) |
((ulong)buffer[offset1 + 5] << 40) |
((ulong)buffer[offset1 + 6] << 48) |
((ulong)buffer[offset1 + 7] << 56);
var value2 =
((ulong)buffer[offset2]) |
((ulong)buffer[offset2 + 1] << 8) |
((ulong)buffer[offset2 + 2] << 16) |
((ulong)buffer[offset2 + 3] << 24) |
((ulong)buffer[offset2 + 4] << 32) |
((ulong)buffer[offset2 + 5] << 40) |
((ulong)buffer[offset2 + 6] << 48) |
((ulong)buffer[offset2 + 7] << 56);
return value1 ^ value2;
}
private static bool Equal2(byte[] buffer, int offset1, int offset2)
{
// return Peek2(buffer, offset1) == Peek2(buffer, offset2);
if (buffer[offset1] != buffer[offset2])
{
return false;
}
return buffer[offset1 + 1] == buffer[offset2 + 1];
}
private static bool Equal4(byte[] buffer, int offset1, int offset2)
{
// return Peek4(buffer, offset1) == Peek4(buffer, offset2);
if (buffer[offset1] != buffer[offset2])
{
return false;
}
if (buffer[offset1 + 1] != buffer[offset2 + 1])
{
return false;
}
if (buffer[offset1 + 2] != buffer[offset2 + 2])
{
return false;
}
return buffer[offset1 + 3] == buffer[offset2 + 3];
}
#endregion
#region Byte block copy
private static void Copy4(byte[] buf, int src, int dst)
{
Assert(dst > src, "Copying backwards is not implemented");
buf[dst + 3] = buf[src + 3];
buf[dst + 2] = buf[src + 2];
buf[dst + 1] = buf[src + 1];
buf[dst] = buf[src];
}
private static void Copy8(byte[] buf, int src, int dst)
{
Assert(dst > src, "Copying backwards is not implemented");
buf[dst + 7] = buf[src + 7];
buf[dst + 6] = buf[src + 6];
buf[dst + 5] = buf[src + 5];
buf[dst + 4] = buf[src + 4];
buf[dst + 3] = buf[src + 3];
buf[dst + 2] = buf[src + 2];
buf[dst + 1] = buf[src + 1];
buf[dst] = buf[src];
}
private static void BlockCopy(byte[] src, int src_0, byte[] dst, int dst_0, int len)
{
Assert(src != dst, "BlockCopy does not handle copying to the same buffer");
if (len >= BLOCK_COPY_LIMIT)
{
Buffer.BlockCopy(src, src_0, dst, dst_0, len);
}
else
{
while (len >= 8)
{
dst[dst_0] = src[src_0];
dst[dst_0 + 1] = src[src_0 + 1];
dst[dst_0 + 2] = src[src_0 + 2];
dst[dst_0 + 3] = src[src_0 + 3];
dst[dst_0 + 4] = src[src_0 + 4];
dst[dst_0 + 5] = src[src_0 + 5];
dst[dst_0 + 6] = src[src_0 + 6];
dst[dst_0 + 7] = src[src_0 + 7];
len -= 8;
src_0 += 8;
dst_0 += 8;
}
while (len >= 4)
{
dst[dst_0] = src[src_0];
dst[dst_0 + 1] = src[src_0 + 1];
dst[dst_0 + 2] = src[src_0 + 2];
dst[dst_0 + 3] = src[src_0 + 3];
len -= 4;
src_0 += 4;
dst_0 += 4;
}
while (len-- > 0)
{
dst[dst_0++] = src[src_0++];
}
}
}
private static int WildCopy(byte[] src, int src_0, byte[] dst, int dst_0, int dst_end)
{
var len = dst_end - dst_0;
Assert(src != dst, "BlockCopy does not handle copying to the same buffer");
Assert(len > 0, "Length have to be greater than 0");
if (len >= BLOCK_COPY_LIMIT)
{
Buffer.BlockCopy(src, src_0, dst, dst_0, len);
}
else
{
// apparently (tested) this is an overkill
// it seems to be faster without this 8-byte loop
////while (len >= 8)
////{
//// dst[dst_0] = src[src_0];
//// dst[dst_0 + 1] = src[src_0 + 1];
//// dst[dst_0 + 2] = src[src_0 + 2];
//// dst[dst_0 + 3] = src[src_0 + 3];
//// dst[dst_0 + 4] = src[src_0 + 4];
//// dst[dst_0 + 5] = src[src_0 + 5];
//// dst[dst_0 + 6] = src[src_0 + 6];
//// dst[dst_0 + 7] = src[src_0 + 7];
//// len -= 8; src_0 += 8; dst_0 += 8;
////}
while (len >= 4)
{
dst[dst_0] = src[src_0];
dst[dst_0 + 1] = src[src_0 + 1];
dst[dst_0 + 2] = src[src_0 + 2];
dst[dst_0 + 3] = src[src_0 + 3];
len -= 4;
src_0 += 4;
dst_0 += 4;
}
while (len-- > 0)
{
dst[dst_0++] = src[src_0++];
}
}
return len;
}
private static int SecureCopy(byte[] buffer, int src, int dst, int dst_end)
{
var diff = dst - src;
var length = dst_end - dst;
var len = length;
Assert(diff >= 4, "Target must be at least 4 bytes further than source");
Assert(BLOCK_COPY_LIMIT > 4, "This method requires BLOCK_COPY_LIMIT > 4");
Assert(len > 0, "Length have to be greater than 0");
if (diff >= BLOCK_COPY_LIMIT)
{
if (diff >= length)
{
Buffer.BlockCopy(buffer, src, buffer, dst, length);
return length; // done
}
do
{
Buffer.BlockCopy(buffer, src, buffer, dst, diff);
src += diff;
dst += diff;
len -= diff;
}
while (len >= diff);
}
// apparently (tested) this is an overkill
// it seems to be faster without this 8-byte loop
////while (len >= 8)
////{
//// buffer[dst] = buffer[src];
//// buffer[dst + 1] = buffer[src + 1];
//// buffer[dst + 2] = buffer[src + 2];
//// buffer[dst + 3] = buffer[src + 3];
//// buffer[dst + 4] = buffer[src + 4];
//// buffer[dst + 5] = buffer[src + 5];
//// buffer[dst + 6] = buffer[src + 6];
//// buffer[dst + 7] = buffer[src + 7];
//// dst += 8; src += 8; len -= 8;
////}
while (len >= 4)
{
buffer[dst] = buffer[src];
buffer[dst + 1] = buffer[src + 1];
buffer[dst + 2] = buffer[src + 2];
buffer[dst + 3] = buffer[src + 3];
dst += 4;
src += 4;
len -= 4;
}
while (len-- > 0)
{
buffer[dst++] = buffer[src++];
}
return length; // done
}
#endregion
/// <summary>Encodes the specified input.</summary>
/// <param name="input">The input.</param>
/// <param name="inputOffset">The input offset.</param>
/// <param name="inputLength">Length of the input.</param>
/// <param name="output">The output.</param>
/// <param name="outputOffset">The output offset.</param>
/// <param name="outputLength">Length of the output.</param>
/// <returns>Number of bytes written.</returns>
public static int Encode32Safe(
byte[] input,
int inputOffset,
int inputLength,
byte[] output,
int outputOffset,
int outputLength)
{
CheckArguments(input, inputOffset, inputLength, output, outputOffset, outputLength);
if (outputLength == 0)
{
return 0;
}
if (inputLength < LZ4_64KLIMIT)
{
var hashTable = HashTablePool.GetUShortHashTablePool();
return LZ4_compress64kCtx_safe32(hashTable, input, output, inputOffset, outputOffset, inputLength, outputLength);
}
else
{
var hashTable = HashTablePool.GetIntHashTablePool();
return LZ4_compressCtx_safe32(hashTable, input, output, inputOffset, outputOffset, inputLength, outputLength);
}
}
/// <summary>Encodes the specified input.</summary>
/// <param name="input">The input.</param>
/// <param name="inputOffset">The input offset.</param>
/// <param name="inputLength">Length of the input.</param>
/// <param name="output">The output.</param>
/// <param name="outputOffset">The output offset.</param>
/// <param name="outputLength">Length of the output.</param>
/// <returns>Number of bytes written.</returns>
public static int Encode64Safe(
byte[] input,
int inputOffset,
int inputLength,
byte[] output,
int outputOffset,
int outputLength)
{
CheckArguments(input, inputOffset, inputLength, output, outputOffset, outputLength);
if (outputLength == 0)
{
return 0;
}
if (inputLength < LZ4_64KLIMIT)
{
var hashTable = HashTablePool.GetUShortHashTablePool();
return LZ4_compress64kCtx_safe64(hashTable, input, output, inputOffset, outputOffset, inputLength, outputLength);
}
else
{
var hashTable = HashTablePool.GetIntHashTablePool();
return LZ4_compressCtx_safe64(hashTable, input, output, inputOffset, outputOffset, inputLength, outputLength);
}
}
/// <summary>Decodes the specified input.</summary>
/// <param name="input">The input.</param>
/// <param name="inputOffset">The input offset.</param>
/// <param name="inputLength">Length of the input.</param>
/// <param name="output">The output.</param>
/// <param name="outputOffset">The output offset.</param>
/// <param name="outputLength">Length of the output.</param>
/// <returns>Number of bytes written.</returns>
public static int Decode32Safe(
byte[] input,
int inputOffset,
int inputLength,
byte[] output,
int outputOffset,
int outputLength)
{
CheckArguments(input, inputOffset, inputLength, output, outputOffset, outputLength);
if (outputLength == 0)
{
return 0;
}
var length = LZ4_uncompress_safe32(input, output, inputOffset, outputOffset, outputLength);
if (length != inputLength)
{
throw new MessagePackSerializationException("LZ4 block is corrupted, or invalid length has been given.");
}
return outputLength;
}
/// <summary>Decodes the specified input.</summary>
/// <param name="input">The input.</param>
/// <param name="inputOffset">The input offset.</param>
/// <param name="inputLength">Length of the input.</param>
/// <param name="output">The output.</param>
/// <param name="outputOffset">The output offset.</param>
/// <param name="outputLength">Length of the output.</param>
/// <returns>Number of bytes written.</returns>
public static int Decode64Safe(
byte[] input,
int inputOffset,
int inputLength,
byte[] output,
int outputOffset,
int outputLength)
{
CheckArguments(input, inputOffset, inputLength, output, outputOffset, outputLength);
if (outputLength == 0)
{
return 0;
}
var length = LZ4_uncompress_safe64(input, output, inputOffset, outputOffset, outputLength);
if (length != inputLength)
{
throw new MessagePackSerializationException("LZ4 block is corrupted, or invalid length has been given.");
}
return outputLength;
}
}
}
#endif

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 5fe9256cf4f62c6df8c144caef0ebc6a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,753 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#if UNITY_2018_3_OR_NEWER
#region LZ4 original
/*
LZ4 - Fast LZ compression algorithm
Copyright (C) 2011-2012, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
- LZ4 source repository : http://code.google.com/p/lz4/
*/
#endregion
#region LZ4 port
/*
Copyright (c) 2013, Milosz Krajewski
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#endregion
#pragma warning disable SA1312 // Variable names should begin with lower-case letter
namespace MessagePack.LZ4
{
internal partial class LZ4Codec
{
#region LZ4_compressCtx
private static int LZ4_compressCtx_safe32(
int[] hash_table,
byte[] src,
byte[] dst,
int src_0,
int dst_0,
int src_len,
int dst_maxlen)
{
unchecked
{
var debruijn32 = DEBRUIJN_TABLE_32;
int _i;
// ---- preprocessed source start here ----
// r93
var src_p = src_0;
var src_base = src_0;
var src_anchor = src_p;
var src_end = src_p + src_len;
var src_mflimit = src_end - MFLIMIT;
var dst_p = dst_0;
var dst_end = dst_p + dst_maxlen;
var src_LASTLITERALS = src_end - LASTLITERALS;
var src_LASTLITERALS_1 = src_LASTLITERALS - 1;
var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_32 - 1);
var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS);
var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS);
int length;
uint h, h_fwd;
// Init
if (src_len < MINLENGTH)
{
goto _last_literals;
}
// First Byte
hash_table[(Peek4(src, src_p) * 2654435761u) >> HASH_ADJUST] = src_p - src_base;
src_p++;
h_fwd = (Peek4(src, src_p) * 2654435761u) >> HASH_ADJUST;
// Main Loop
while (true)
{
var findMatchAttempts = (1 << SKIPSTRENGTH) + 3;
var src_p_fwd = src_p;
int src_ref;
int dst_token;
// Find a match
do
{
h = h_fwd;
var step = findMatchAttempts++ >> SKIPSTRENGTH;
src_p = src_p_fwd;
src_p_fwd = src_p + step;
if (src_p_fwd > src_mflimit)
{
goto _last_literals;
}
h_fwd = (Peek4(src, src_p_fwd) * 2654435761u) >> HASH_ADJUST;
src_ref = src_base + hash_table[h];
hash_table[h] = src_p - src_base;
}
while ((src_ref < src_p - MAX_DISTANCE) || (!Equal4(src, src_ref, src_p)));
// Catch up
while ((src_p > src_anchor) && (src_ref > src_0) && (src[src_p - 1] == src[src_ref - 1]))
{
src_p--;
src_ref--;
}
// Encode Literal length
length = src_p - src_anchor;
dst_token = dst_p++;
if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3)
{
return 0; // Check output limit
}
if (length >= RUN_MASK)
{
var len = length - RUN_MASK;
dst[dst_token] = RUN_MASK << ML_BITS;
if (len > 254)
{
do
{
dst[dst_p++] = 255;
len -= 255;
}
while (len > 254);
dst[dst_p++] = (byte)len;
BlockCopy(src, src_anchor, dst, dst_p, length);
dst_p += length;
goto _next_match;
}
else
{
dst[dst_p++] = (byte)len;
}
}
else
{
dst[dst_token] = (byte)(length << ML_BITS);
}
// Copy Literals
if (length > 0)
{
_i = dst_p + length;
WildCopy(src, src_anchor, dst, dst_p, _i);
dst_p = _i;
}
_next_match:
// Encode Offset
Poke2(dst, dst_p, (ushort)(src_p - src_ref));
dst_p += 2;
// Start Counting
src_p += MINMATCH;
src_ref += MINMATCH; // MinMatch already verified
src_anchor = src_p;
while (src_p < src_LASTLITERALS_STEPSIZE_1)
{
var diff = (int)Xor4(src, src_ref, src_p);
if (diff == 0)
{
src_p += STEPSIZE_32;
src_ref += STEPSIZE_32;
continue;
}
src_p += debruijn32[((uint)(diff & -diff) * 0x077CB531u) >> 27];
goto _endCount;
}
if ((src_p < src_LASTLITERALS_1) && Equal2(src, src_ref, src_p))
{
src_p += 2;
src_ref += 2;
}
if ((src_p < src_LASTLITERALS) && (src[src_ref] == src[src_p]))
{
src_p++;
}
_endCount:
// Encode MatchLength
length = src_p - src_anchor;
if (dst_p + (length >> 8) > dst_LASTLITERALS_1)
{
return 0; // Check output limit
}
if (length >= ML_MASK)
{
dst[dst_token] += ML_MASK;
length -= ML_MASK;
for (; length > 509; length -= 510)
{
dst[dst_p++] = 255;
dst[dst_p++] = 255;
}
if (length > 254)
{
length -= 255;
dst[dst_p++] = 255;
}
dst[dst_p++] = (byte)length;
}
else
{
dst[dst_token] += (byte)length;
}
// Test end of chunk
if (src_p > src_mflimit)
{
src_anchor = src_p;
break;
}
// Fill table
hash_table[(Peek4(src, src_p - 2) * 2654435761u) >> HASH_ADJUST] = src_p - 2 - src_base;
// Test next position
h = (Peek4(src, src_p) * 2654435761u) >> HASH_ADJUST;
src_ref = src_base + hash_table[h];
hash_table[h] = src_p - src_base;
if ((src_ref > src_p - (MAX_DISTANCE + 1)) && Equal4(src, src_ref, src_p))
{
dst_token = dst_p++;
dst[dst_token] = 0;
goto _next_match;
}
// Prepare next loop
src_anchor = src_p++;
h_fwd = (Peek4(src, src_p) * 2654435761u) >> HASH_ADJUST;
}
_last_literals:
// Encode Last Literals
{
var lastRun = src_end - src_anchor;
if (dst_p + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > dst_end)
{
return 0;
}
if (lastRun >= RUN_MASK)
{
dst[dst_p++] = RUN_MASK << ML_BITS;
lastRun -= RUN_MASK;
for (; lastRun > 254; lastRun -= 255)
{
dst[dst_p++] = 255;
}
dst[dst_p++] = (byte)lastRun;
}
else
{
dst[dst_p++] = (byte)(lastRun << ML_BITS);
}
BlockCopy(src, src_anchor, dst, dst_p, src_end - src_anchor);
dst_p += src_end - src_anchor;
}
// End
return dst_p - dst_0;
}
}
#endregion
#region LZ4_compress64kCtx
private static int LZ4_compress64kCtx_safe32(
ushort[] hash_table,
byte[] src,
byte[] dst,
int src_0,
int dst_0,
int src_len,
int dst_maxlen)
{
unchecked
{
var debruijn32 = DEBRUIJN_TABLE_32;
int _i;
// ---- preprocessed source start here ----
// r93
var src_p = src_0;
var src_anchor = src_p;
var src_base = src_p;
var src_end = src_p + src_len;
var src_mflimit = src_end - MFLIMIT;
var dst_p = dst_0;
var dst_end = dst_p + dst_maxlen;
var src_LASTLITERALS = src_end - LASTLITERALS;
var src_LASTLITERALS_1 = src_LASTLITERALS - 1;
var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_32 - 1);
var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS);
var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS);
int len, length;
uint h, h_fwd;
// Init
if (src_len < MINLENGTH)
{
goto _last_literals;
}
// First Byte
src_p++;
h_fwd = (Peek4(src, src_p) * 2654435761u) >> HASH64K_ADJUST;
// Main Loop
while (true)
{
var findMatchAttempts = (1 << SKIPSTRENGTH) + 3;
var src_p_fwd = src_p;
int src_ref;
int dst_token;
// Find a match
do
{
h = h_fwd;
var step = findMatchAttempts++ >> SKIPSTRENGTH;
src_p = src_p_fwd;
src_p_fwd = src_p + step;
if (src_p_fwd > src_mflimit)
{
goto _last_literals;
}
h_fwd = (Peek4(src, src_p_fwd) * 2654435761u) >> HASH64K_ADJUST;
src_ref = src_base + hash_table[h];
hash_table[h] = (ushort)(src_p - src_base);
}
while (!Equal4(src, src_ref, src_p));
// Catch up
while ((src_p > src_anchor) && (src_ref > src_0) && (src[src_p - 1] == src[src_ref - 1]))
{
src_p--;
src_ref--;
}
// Encode Literal length
length = src_p - src_anchor;
dst_token = dst_p++;
if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3)
{
return 0; // Check output limit
}
if (length >= RUN_MASK)
{
len = length - RUN_MASK;
dst[dst_token] = RUN_MASK << ML_BITS;
if (len > 254)
{
do
{
dst[dst_p++] = 255;
len -= 255;
}
while (len > 254);
dst[dst_p++] = (byte)len;
BlockCopy(src, src_anchor, dst, dst_p, length);
dst_p += length;
goto _next_match;
}
else
{
dst[dst_p++] = (byte)len;
}
}
else
{
dst[dst_token] = (byte)(length << ML_BITS);
}
// Copy Literals
if (length > 0)
{
_i = dst_p + length;
WildCopy(src, src_anchor, dst, dst_p, _i);
dst_p = _i;
}
_next_match:
// Encode Offset
Poke2(dst, dst_p, (ushort)(src_p - src_ref));
dst_p += 2;
// Start Counting
src_p += MINMATCH;
src_ref += MINMATCH; // MinMatch verified
src_anchor = src_p;
while (src_p < src_LASTLITERALS_STEPSIZE_1)
{
var diff = (int)Xor4(src, src_ref, src_p);
if (diff == 0)
{
src_p += STEPSIZE_32;
src_ref += STEPSIZE_32;
continue;
}
src_p += debruijn32[((uint)(diff & -diff) * 0x077CB531u) >> 27];
goto _endCount;
}
if ((src_p < src_LASTLITERALS_1) && Equal2(src, src_ref, src_p))
{
src_p += 2;
src_ref += 2;
}
if ((src_p < src_LASTLITERALS) && (src[src_ref] == src[src_p]))
{
src_p++;
}
_endCount:
// Encode MatchLength
len = src_p - src_anchor;
if (dst_p + (len >> 8) > dst_LASTLITERALS_1)
{
return 0; // Check output limit
}
if (len >= ML_MASK)
{
dst[dst_token] += ML_MASK;
len -= ML_MASK;
for (; len > 509; len -= 510)
{
dst[dst_p++] = 255;
dst[dst_p++] = 255;
}
if (len > 254)
{
len -= 255;
dst[dst_p++] = 255;
}
dst[dst_p++] = (byte)len;
}
else
{
dst[dst_token] += (byte)len;
}
// Test end of chunk
if (src_p > src_mflimit)
{
src_anchor = src_p;
break;
}
// Fill table
hash_table[(Peek4(src, src_p - 2) * 2654435761u) >> HASH64K_ADJUST] = (ushort)(src_p - 2 - src_base);
// Test next position
h = (Peek4(src, src_p) * 2654435761u) >> HASH64K_ADJUST;
src_ref = src_base + hash_table[h];
hash_table[h] = (ushort)(src_p - src_base);
if (Equal4(src, src_ref, src_p))
{
dst_token = dst_p++;
dst[dst_token] = 0;
goto _next_match;
}
// Prepare next loop
src_anchor = src_p++;
h_fwd = (Peek4(src, src_p) * 2654435761u) >> HASH64K_ADJUST;
}
_last_literals:
// Encode Last Literals
var lastRun = src_end - src_anchor;
if (dst_p + lastRun + 1 + ((lastRun - RUN_MASK + 255) / 255) > dst_end)
{
return 0;
}
if (lastRun >= RUN_MASK)
{
dst[dst_p++] = RUN_MASK << ML_BITS;
lastRun -= RUN_MASK;
for (; lastRun > 254; lastRun -= 255)
{
dst[dst_p++] = 255;
}
dst[dst_p++] = (byte)lastRun;
}
else
{
dst[dst_p++] = (byte)(lastRun << ML_BITS);
}
BlockCopy(src, src_anchor, dst, dst_p, src_end - src_anchor);
dst_p += src_end - src_anchor;
// End
return dst_p - dst_0;
}
}
#endregion
#region LZ4_uncompress
private static int LZ4_uncompress_safe32(
byte[] src,
byte[] dst,
int src_0,
int dst_0,
int dst_len)
{
unchecked
{
var dec32table = DECODER_TABLE_32;
int _i;
// ---- preprocessed source start here ----
// r93
var src_p = src_0;
int dst_ref;
var dst_p = dst_0;
var dst_end = dst_p + dst_len;
int dst_cpy;
var dst_LASTLITERALS = dst_end - LASTLITERALS;
var dst_COPYLENGTH = dst_end - COPYLENGTH;
var dst_COPYLENGTH_STEPSIZE_4 = dst_end - COPYLENGTH - (STEPSIZE_32 - 4);
byte token;
// Main Loop
while (true)
{
int length;
// get runlength
token = src[src_p++];
if ((length = token >> ML_BITS) == RUN_MASK)
{
int len;
for (; (len = src[src_p++]) == 255; length += 255)
{
/* do nothing */
}
length += len;
}
// copy literals
dst_cpy = dst_p + length;
if (dst_cpy > dst_COPYLENGTH)
{
if (dst_cpy != dst_end)
{
goto _output_error; // Error : not enough place for another match (min 4) + 5 literals
}
BlockCopy(src, src_p, dst, dst_p, length);
src_p += length;
break; // EOF
}
if (dst_p < dst_cpy)
{
_i = WildCopy(src, src_p, dst, dst_p, dst_cpy);
src_p += _i;
dst_p += _i;
}
src_p -= dst_p - dst_cpy;
dst_p = dst_cpy;
// get offset
dst_ref = dst_cpy - Peek2(src, src_p);
src_p += 2;
if (dst_ref < dst_0)
{
goto _output_error; // Error : offset outside destination buffer
}
// get matchlength
if ((length = token & ML_MASK) == ML_MASK)
{
for (; src[src_p] == 255; length += 255)
{
src_p++;
}
length += src[src_p++];
}
// copy repeated sequence
if ((dst_p - dst_ref) < STEPSIZE_32)
{
const int dec64 = 0;
dst[dst_p + 0] = dst[dst_ref + 0];
dst[dst_p + 1] = dst[dst_ref + 1];
dst[dst_p + 2] = dst[dst_ref + 2];
dst[dst_p + 3] = dst[dst_ref + 3];
dst_p += 4;
dst_ref += 4;
dst_ref -= dec32table[dst_p - dst_ref];
Copy4(dst, dst_ref, dst_p);
dst_p += STEPSIZE_32 - 4;
dst_ref -= dec64;
}
else
{
Copy4(dst, dst_ref, dst_p);
dst_p += 4;
dst_ref += 4;
}
dst_cpy = dst_p + length - (STEPSIZE_32 - 4);
if (dst_cpy > dst_COPYLENGTH_STEPSIZE_4)
{
if (dst_cpy > dst_LASTLITERALS)
{
goto _output_error; // Error : last 5 bytes must be literals
}
if (dst_p < dst_COPYLENGTH)
{
_i = SecureCopy(dst, dst_ref, dst_p, dst_COPYLENGTH);
dst_ref += _i;
dst_p += _i;
}
while (dst_p < dst_cpy)
{
dst[dst_p++] = dst[dst_ref++];
}
dst_p = dst_cpy;
continue;
}
if (dst_p < dst_cpy)
{
SecureCopy(dst, dst_ref, dst_p, dst_cpy);
}
dst_p = dst_cpy; // correction
}
// end of decoding
return src_p - src_0;
// write overflow error detected
_output_error:
return -(src_p - src_0);
}
}
#endregion
}
}
#endif

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 4e76c34fb36d14138b0196dbb3bdc544
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,774 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#if UNITY_2018_3_OR_NEWER
#region LZ4 original
/*
LZ4 - Fast LZ compression algorithm
Copyright (C) 2011-2012, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
- LZ4 source repository : http://code.google.com/p/lz4/
*/
#endregion
#region LZ4 port
/*
Copyright (c) 2013, Milosz Krajewski
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#endregion
#pragma warning disable SA1312 // Variable names should begin with lower-case letter
namespace MessagePack.LZ4
{
internal partial class LZ4Codec
{
#region LZ4_compressCtx
private static int LZ4_compressCtx_safe64(
int[] hash_table,
byte[] src,
byte[] dst,
int src_0,
int dst_0,
int src_len,
int dst_maxlen)
{
unchecked
{
var debruijn64 = DEBRUIJN_TABLE_64;
int _i;
// ---- preprocessed source start here ----
// r93
var src_p = src_0;
var src_base = src_0;
var src_anchor = src_p;
var src_end = src_p + src_len;
var src_mflimit = src_end - MFLIMIT;
var dst_p = dst_0;
var dst_end = dst_p + dst_maxlen;
var src_LASTLITERALS = src_end - LASTLITERALS;
var src_LASTLITERALS_1 = src_LASTLITERALS - 1;
var src_LASTLITERALS_3 = src_LASTLITERALS - 3;
var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_64 - 1);
var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS);
var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS);
int length;
uint h, h_fwd;
// Init
if (src_len < MINLENGTH)
{
goto _last_literals;
}
// First Byte
hash_table[(Peek4(src, src_p) * 2654435761u) >> HASH_ADJUST] = src_p - src_base;
src_p++;
h_fwd = (Peek4(src, src_p) * 2654435761u) >> HASH_ADJUST;
// Main Loop
while (true)
{
var findMatchAttempts = (1 << SKIPSTRENGTH) + 3;
var src_p_fwd = src_p;
int src_ref;
int dst_token;
// Find a match
do
{
h = h_fwd;
var step = findMatchAttempts++ >> SKIPSTRENGTH;
src_p = src_p_fwd;
src_p_fwd = src_p + step;
if (src_p_fwd > src_mflimit)
{
goto _last_literals;
}
h_fwd = (Peek4(src, src_p_fwd) * 2654435761u) >> HASH_ADJUST;
src_ref = src_base + hash_table[h];
hash_table[h] = src_p - src_base;
}
while ((src_ref < src_p - MAX_DISTANCE) || (!Equal4(src, src_ref, src_p)));
// Catch up
while ((src_p > src_anchor) && (src_ref > src_0) && (src[src_p - 1] == src[src_ref - 1]))
{
src_p--;
src_ref--;
}
// Encode Literal length
length = src_p - src_anchor;
dst_token = dst_p++;
if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3)
{
return 0; // Check output limit
}
if (length >= RUN_MASK)
{
var len = length - RUN_MASK;
dst[dst_token] = RUN_MASK << ML_BITS;
if (len > 254)
{
do
{
dst[dst_p++] = 255;
len -= 255;
}
while (len > 254);
dst[dst_p++] = (byte)len;
BlockCopy(src, src_anchor, dst, dst_p, length);
dst_p += length;
goto _next_match;
}
else
{
dst[dst_p++] = (byte)len;
}
}
else
{
dst[dst_token] = (byte)(length << ML_BITS);
}
// Copy Literals
if (length > 0)
{
_i = dst_p + length;
WildCopy(src, src_anchor, dst, dst_p, _i);
dst_p = _i;
}
_next_match:
// Encode Offset
Poke2(dst, dst_p, (ushort)(src_p - src_ref));
dst_p += 2;
// Start Counting
src_p += MINMATCH;
src_ref += MINMATCH; // MinMatch already verified
src_anchor = src_p;
while (src_p < src_LASTLITERALS_STEPSIZE_1)
{
var diff = (long)Xor8(src, src_ref, src_p);
if (diff == 0)
{
src_p += STEPSIZE_64;
src_ref += STEPSIZE_64;
continue;
}
src_p += debruijn64[((ulong)(diff & -diff) * 0x0218A392CDABBD3FL) >> 58];
goto _endCount;
}
if ((src_p < src_LASTLITERALS_3) && Equal4(src, src_ref, src_p))
{
src_p += 4;
src_ref += 4;
}
if ((src_p < src_LASTLITERALS_1) && Equal2(src, src_ref, src_p))
{
src_p += 2;
src_ref += 2;
}
if ((src_p < src_LASTLITERALS) && (src[src_ref] == src[src_p]))
{
src_p++;
}
_endCount:
// Encode MatchLength
length = src_p - src_anchor;
if (dst_p + (length >> 8) > dst_LASTLITERALS_1)
{
return 0; // Check output limit
}
if (length >= ML_MASK)
{
dst[dst_token] += ML_MASK;
length -= ML_MASK;
for (; length > 509; length -= 510)
{
dst[dst_p++] = 255;
dst[dst_p++] = 255;
}
if (length > 254)
{
length -= 255;
dst[dst_p++] = 255;
}
dst[dst_p++] = (byte)length;
}
else
{
dst[dst_token] += (byte)length;
}
// Test end of chunk
if (src_p > src_mflimit)
{
src_anchor = src_p;
break;
}
// Fill table
hash_table[(Peek4(src, src_p - 2) * 2654435761u) >> HASH_ADJUST] = src_p - 2 - src_base;
// Test next position
h = (Peek4(src, src_p) * 2654435761u) >> HASH_ADJUST;
src_ref = src_base + hash_table[h];
hash_table[h] = src_p - src_base;
if ((src_ref > src_p - (MAX_DISTANCE + 1)) && Equal4(src, src_ref, src_p))
{
dst_token = dst_p++;
dst[dst_token] = 0;
goto _next_match;
}
// Prepare next loop
src_anchor = src_p++;
h_fwd = (Peek4(src, src_p) * 2654435761u) >> HASH_ADJUST;
}
_last_literals:
// Encode Last Literals
{
var lastRun = src_end - src_anchor;
if (dst_p + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > dst_end)
{
return 0;
}
if (lastRun >= RUN_MASK)
{
dst[dst_p++] = RUN_MASK << ML_BITS;
lastRun -= RUN_MASK;
for (; lastRun > 254; lastRun -= 255)
{
dst[dst_p++] = 255;
}
dst[dst_p++] = (byte)lastRun;
}
else
{
dst[dst_p++] = (byte)(lastRun << ML_BITS);
}
BlockCopy(src, src_anchor, dst, dst_p, src_end - src_anchor);
dst_p += src_end - src_anchor;
}
// End
return dst_p - dst_0;
}
}
#endregion
#region LZ4_compress64kCtx
private static int LZ4_compress64kCtx_safe64(
ushort[] hash_table,
byte[] src,
byte[] dst,
int src_0,
int dst_0,
int src_len,
int dst_maxlen)
{
unchecked
{
var debruijn64 = DEBRUIJN_TABLE_64;
int _i;
// ---- preprocessed source start here ----
// r93
var src_p = src_0;
var src_anchor = src_p;
var src_base = src_p;
var src_end = src_p + src_len;
var src_mflimit = src_end - MFLIMIT;
var dst_p = dst_0;
var dst_end = dst_p + dst_maxlen;
var src_LASTLITERALS = src_end - LASTLITERALS;
var src_LASTLITERALS_1 = src_LASTLITERALS - 1;
var src_LASTLITERALS_3 = src_LASTLITERALS - 3;
var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_64 - 1);
var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS);
var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS);
int len, length;
uint h, h_fwd;
// Init
if (src_len < MINLENGTH)
{
goto _last_literals;
}
// First Byte
src_p++;
h_fwd = (Peek4(src, src_p) * 2654435761u) >> HASH64K_ADJUST;
// Main Loop
while (true)
{
var findMatchAttempts = (1 << SKIPSTRENGTH) + 3;
var src_p_fwd = src_p;
int src_ref;
int dst_token;
// Find a match
do
{
h = h_fwd;
var step = findMatchAttempts++ >> SKIPSTRENGTH;
src_p = src_p_fwd;
src_p_fwd = src_p + step;
if (src_p_fwd > src_mflimit)
{
goto _last_literals;
}
h_fwd = (Peek4(src, src_p_fwd) * 2654435761u) >> HASH64K_ADJUST;
src_ref = src_base + hash_table[h];
hash_table[h] = (ushort)(src_p - src_base);
}
while (!Equal4(src, src_ref, src_p));
// Catch up
while ((src_p > src_anchor) && (src_ref > src_0) && (src[src_p - 1] == src[src_ref - 1]))
{
src_p--;
src_ref--;
}
// Encode Literal length
length = src_p - src_anchor;
dst_token = dst_p++;
if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3)
{
return 0; // Check output limit
}
if (length >= RUN_MASK)
{
len = length - RUN_MASK;
dst[dst_token] = RUN_MASK << ML_BITS;
if (len > 254)
{
do
{
dst[dst_p++] = 255;
len -= 255;
}
while (len > 254);
dst[dst_p++] = (byte)len;
BlockCopy(src, src_anchor, dst, dst_p, length);
dst_p += length;
goto _next_match;
}
else
{
dst[dst_p++] = (byte)len;
}
}
else
{
dst[dst_token] = (byte)(length << ML_BITS);
}
// Copy Literals
if (length > 0)
{
_i = dst_p + length;
WildCopy(src, src_anchor, dst, dst_p, _i);
dst_p = _i;
}
_next_match:
// Encode Offset
Poke2(dst, dst_p, (ushort)(src_p - src_ref));
dst_p += 2;
// Start Counting
src_p += MINMATCH;
src_ref += MINMATCH; // MinMatch verified
src_anchor = src_p;
while (src_p < src_LASTLITERALS_STEPSIZE_1)
{
var diff = (long)Xor8(src, src_ref, src_p);
if (diff == 0)
{
src_p += STEPSIZE_64;
src_ref += STEPSIZE_64;
continue;
}
src_p += debruijn64[((ulong)(diff & -diff) * 0x0218A392CDABBD3FL) >> 58];
goto _endCount;
}
if ((src_p < src_LASTLITERALS_3) && Equal4(src, src_ref, src_p))
{
src_p += 4;
src_ref += 4;
}
if ((src_p < src_LASTLITERALS_1) && Equal2(src, src_ref, src_p))
{
src_p += 2;
src_ref += 2;
}
if ((src_p < src_LASTLITERALS) && (src[src_ref] == src[src_p]))
{
src_p++;
}
_endCount:
// Encode MatchLength
len = src_p - src_anchor;
if (dst_p + (len >> 8) > dst_LASTLITERALS_1)
{
return 0; // Check output limit
}
if (len >= ML_MASK)
{
dst[dst_token] += ML_MASK;
len -= ML_MASK;
for (; len > 509; len -= 510)
{
dst[dst_p++] = 255;
dst[dst_p++] = 255;
}
if (len > 254)
{
len -= 255;
dst[dst_p++] = 255;
}
dst[dst_p++] = (byte)len;
}
else
{
dst[dst_token] += (byte)len;
}
// Test end of chunk
if (src_p > src_mflimit)
{
src_anchor = src_p;
break;
}
// Fill table
hash_table[(Peek4(src, src_p - 2) * 2654435761u) >> HASH64K_ADJUST] = (ushort)(src_p - 2 - src_base);
// Test next position
h = (Peek4(src, src_p) * 2654435761u) >> HASH64K_ADJUST;
src_ref = src_base + hash_table[h];
hash_table[h] = (ushort)(src_p - src_base);
if (Equal4(src, src_ref, src_p))
{
dst_token = dst_p++;
dst[dst_token] = 0;
goto _next_match;
}
// Prepare next loop
src_anchor = src_p++;
h_fwd = (Peek4(src, src_p) * 2654435761u) >> HASH64K_ADJUST;
}
_last_literals:
// Encode Last Literals
{
var lastRun = src_end - src_anchor;
if (dst_p + lastRun + 1 + ((lastRun - RUN_MASK + 255) / 255) > dst_end)
{
return 0;
}
if (lastRun >= RUN_MASK)
{
dst[dst_p++] = RUN_MASK << ML_BITS;
lastRun -= RUN_MASK;
for (; lastRun > 254; lastRun -= 255)
{
dst[dst_p++] = 255;
}
dst[dst_p++] = (byte)lastRun;
}
else
{
dst[dst_p++] = (byte)(lastRun << ML_BITS);
}
BlockCopy(src, src_anchor, dst, dst_p, src_end - src_anchor);
dst_p += src_end - src_anchor;
}
// End
return dst_p - dst_0;
}
}
#endregion
#region LZ4_uncompress
private static int LZ4_uncompress_safe64(
byte[] src,
byte[] dst,
int src_0,
int dst_0,
int dst_len)
{
unchecked
{
var dec32table = DECODER_TABLE_32;
var dec64table = DECODER_TABLE_64;
int _i;
// ---- preprocessed source start here ----
// r93
var src_p = src_0;
int dst_ref;
var dst_p = dst_0;
var dst_end = dst_p + dst_len;
int dst_cpy;
var dst_LASTLITERALS = dst_end - LASTLITERALS;
var dst_COPYLENGTH = dst_end - COPYLENGTH;
var dst_COPYLENGTH_STEPSIZE_4 = dst_end - COPYLENGTH - (STEPSIZE_64 - 4);
uint token;
// Main Loop
while (true)
{
int length;
// get runlength
token = src[src_p++];
if ((length = (byte)(token >> ML_BITS)) == RUN_MASK)
{
int len;
for (; (len = src[src_p++]) == 255; length += 255)
{
/* do nothing */
}
length += len;
}
// copy literals
dst_cpy = dst_p + length;
if (dst_cpy > dst_COPYLENGTH)
{
if (dst_cpy != dst_end)
{
goto _output_error; // Error : not enough place for another match (min 4) + 5 literals
}
BlockCopy(src, src_p, dst, dst_p, length);
src_p += length;
break; // EOF
}
if (dst_p < dst_cpy)
{
_i = WildCopy(src, src_p, dst, dst_p, dst_cpy);
src_p += _i;
dst_p += _i;
}
src_p -= dst_p - dst_cpy;
dst_p = dst_cpy;
// get offset
dst_ref = dst_cpy - Peek2(src, src_p);
src_p += 2;
if (dst_ref < dst_0)
{
goto _output_error; // Error : offset outside destination buffer
}
// get matchlength
if ((length = (byte)(token & ML_MASK)) == ML_MASK)
{
for (; src[src_p] == 255; length += 255)
{
src_p++;
}
length += src[src_p++];
}
// copy repeated sequence
if ((dst_p - dst_ref) < STEPSIZE_64)
{
var dec64 = dec64table[dst_p - dst_ref];
dst[dst_p + 0] = dst[dst_ref + 0];
dst[dst_p + 1] = dst[dst_ref + 1];
dst[dst_p + 2] = dst[dst_ref + 2];
dst[dst_p + 3] = dst[dst_ref + 3];
dst_p += 4;
dst_ref += 4;
dst_ref -= dec32table[dst_p - dst_ref];
Copy4(dst, dst_ref, dst_p);
dst_p += STEPSIZE_64 - 4;
dst_ref -= dec64;
}
else
{
Copy8(dst, dst_ref, dst_p);
dst_p += 8;
dst_ref += 8;
}
dst_cpy = dst_p + length - (STEPSIZE_64 - 4);
if (dst_cpy > dst_COPYLENGTH_STEPSIZE_4)
{
if (dst_cpy > dst_LASTLITERALS)
{
goto _output_error; // Error : last 5 bytes must be literals
}
if (dst_p < dst_COPYLENGTH)
{
_i = SecureCopy(dst, dst_ref, dst_p, dst_COPYLENGTH);
dst_ref += _i;
dst_p += _i;
}
while (dst_p < dst_cpy)
{
dst[dst_p++] = dst[dst_ref++];
}
dst_p = dst_cpy;
continue;
}
if (dst_p < dst_cpy)
{
SecureCopy(dst, dst_ref, dst_p, dst_cpy);
}
dst_p = dst_cpy; // correction
}
// end of decoding
return src_p - src_0;
_output_error:
// write overflow error detected
return -(src_p - src_0);
}
}
#endregion
}
}
#endif

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 31798435f43678c67b458999c71cfbb3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,118 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#region license
/*
Copyright (c) 2013, Milosz Krajewski
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#endregion
using System;
namespace MessagePack.LZ4
{
/// <summary>Unsafe LZ4 codec.</summary>
internal partial class LZ4Codec
{
/// <summary>Encodes the specified input.</summary>
/// <param name="input">The input.</param>
/// <param name="output">The output.</param>
/// <returns>Number of bytes written.</returns>
public static unsafe int Encode(ReadOnlySpan<byte> input, Span<byte> output)
{
if (output.Length == 0)
{
throw new MessagePackSerializationException("Output is empty.");
}
fixed (byte* inputPtr = input)
fixed (byte* outputPtr = output)
{
if (input.Length < LZ4_64KLIMIT)
{
var uHashTable = HashTablePool.GetUShortHashTablePool();
fixed (ushort* hash1 = &uHashTable[0])
{
if (IntPtr.Size == 4)
{
return LZ4_compress64kCtx_32(hash1, inputPtr, outputPtr, input.Length, output.Length);
}
else
{
return LZ4_compress64kCtx_64(hash1, inputPtr, outputPtr, input.Length, output.Length);
}
}
}
else
{
var bHashTable = HashTablePool.GetUIntHashTablePool();
fixed (uint* hash2 = &bHashTable[0])
{
if (IntPtr.Size == 4)
{
return LZ4_compressCtx_32(hash2, inputPtr, outputPtr, input.Length, output.Length);
}
else
{
return LZ4_compressCtx_64(hash2, inputPtr, outputPtr, input.Length, output.Length);
}
}
}
}
}
/// <summary>Decodes the specified input.</summary>
/// <param name="input">The input.</param>
/// <param name="output">The output.</param>
/// <returns>Number of bytes written.</returns>
public static unsafe int Decode(ReadOnlySpan<byte> input, Span<byte> output)
{
if (output.Length == 0)
{
throw new MessagePackSerializationException("Output is empty.");
}
fixed (byte* inputPtr = input)
fixed (byte* outputPtr = output)
{
int length;
if (IntPtr.Size == 4)
{
length = LZ4_uncompress_32(inputPtr, outputPtr, output.Length);
}
else
{
length = LZ4_uncompress_64(inputPtr, outputPtr, output.Length);
}
if (length != input.Length)
{
throw new MessagePackSerializationException("LZ4 block is corrupted, or invalid length has been given.");
}
return output.Length;
}
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 719385c28cab29b71a262f02263f385e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,796 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#region LZ4 original
/*
LZ4 - Fast LZ compression algorithm
Copyright (C) 2011-2012, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
- LZ4 source repository : http://code.google.com/p/lz4/
*/
#endregion
#region LZ4 port
/*
Copyright (c) 2013, Milosz Krajewski
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#endregion
#pragma warning disable SA1312 // Variable names should begin with lower-case letter
namespace MessagePack.LZ4
{
internal partial class LZ4Codec
{
#region LZ4_compressCtx_32
private static unsafe int LZ4_compressCtx_32(
uint* hash_table,
byte* src,
byte* dst,
int src_len,
int dst_maxlen)
{
unchecked
{
byte* _p;
fixed (int* debruijn32 = &DEBRUIJN_TABLE_32[0])
{
// r93
var src_p = src;
var src_base = src_p;
var src_anchor = src_p;
var src_end = src_p + src_len;
var src_mflimit = src_end - MFLIMIT;
var dst_p = dst;
var dst_end = dst_p + dst_maxlen;
var src_LASTLITERALS = src_end - LASTLITERALS;
var src_LASTLITERALS_1 = src_LASTLITERALS - 1;
var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_32 - 1);
var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS);
var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS);
int length;
uint h, h_fwd;
// Init
if (src_len < MINLENGTH)
{
goto _last_literals;
}
// First Byte
hash_table[(*(uint*)src_p * 2654435761u) >> HASH_ADJUST] = (uint)(src_p - src_base);
src_p++;
h_fwd = (*(uint*)src_p * 2654435761u) >> HASH_ADJUST;
// Main Loop
while (true)
{
var findMatchAttempts = (1 << SKIPSTRENGTH) + 3;
var src_p_fwd = src_p;
byte* xxx_ref;
byte* xxx_token;
// Find a match
do
{
h = h_fwd;
var step = findMatchAttempts++ >> SKIPSTRENGTH;
src_p = src_p_fwd;
src_p_fwd = src_p + step;
if (src_p_fwd > src_mflimit)
{
goto _last_literals;
}
h_fwd = (*(uint*)src_p_fwd * 2654435761u) >> HASH_ADJUST;
xxx_ref = src_base + hash_table[h];
hash_table[h] = (uint)(src_p - src_base);
}
while ((xxx_ref < src_p - MAX_DISTANCE) || ((*(uint*)xxx_ref) != (*(uint*)src_p)));
// Catch up
while ((src_p > src_anchor) && (xxx_ref > src) && (src_p[-1] == xxx_ref[-1]))
{
src_p--;
xxx_ref--;
}
// Encode Literal length
length = (int)(src_p - src_anchor);
xxx_token = dst_p++;
if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3)
{
return 0; // Check output limit
}
if (length >= RUN_MASK)
{
var len = length - RUN_MASK;
*xxx_token = RUN_MASK << ML_BITS;
if (len > 254)
{
do
{
*dst_p++ = 255;
len -= 255;
}
while (len > 254);
*dst_p++ = (byte)len;
BlockCopy32(src_anchor, dst_p, length);
dst_p += length;
goto _next_match;
}
*dst_p++ = (byte)len;
}
else
{
*xxx_token = (byte)(length << ML_BITS);
}
// Copy Literals
_p = dst_p + length;
do
{
*(uint*)dst_p = *(uint*)src_anchor;
dst_p += 4;
src_anchor += 4;
*(uint*)dst_p = *(uint*)src_anchor;
dst_p += 4;
src_anchor += 4;
}
while (dst_p < _p);
dst_p = _p;
_next_match:
// Encode Offset
*(ushort*)dst_p = (ushort)(src_p - xxx_ref);
dst_p += 2;
// Start Counting
src_p += MINMATCH;
xxx_ref += MINMATCH; // MinMatch already verified
src_anchor = src_p;
while (src_p < src_LASTLITERALS_STEPSIZE_1)
{
var diff = (*(int*)xxx_ref) ^ (*(int*)src_p);
if (diff == 0)
{
src_p += STEPSIZE_32;
xxx_ref += STEPSIZE_32;
continue;
}
src_p += debruijn32[((uint)(diff & -diff) * 0x077CB531u) >> 27];
goto _endCount;
}
if ((src_p < src_LASTLITERALS_1) && ((*(ushort*)xxx_ref) == (*(ushort*)src_p)))
{
src_p += 2;
xxx_ref += 2;
}
if ((src_p < src_LASTLITERALS) && (*xxx_ref == *src_p))
{
src_p++;
}
_endCount:
// Encode MatchLength
length = (int)(src_p - src_anchor);
if (dst_p + (length >> 8) > dst_LASTLITERALS_1)
{
return 0; // Check output limit
}
if (length >= ML_MASK)
{
*xxx_token += ML_MASK;
length -= ML_MASK;
for (; length > 509; length -= 510)
{
*dst_p++ = 255;
*dst_p++ = 255;
}
if (length > 254)
{
length -= 255;
*dst_p++ = 255;
}
*dst_p++ = (byte)length;
}
else
{
*xxx_token += (byte)length;
}
// Test end of chunk
if (src_p > src_mflimit)
{
src_anchor = src_p;
break;
}
// Fill table
hash_table[(*(uint*)(src_p - 2) * 2654435761u) >> HASH_ADJUST] = (uint)(src_p - 2 - src_base);
// Test next position
h = (*(uint*)src_p * 2654435761u) >> HASH_ADJUST;
xxx_ref = src_base + hash_table[h];
hash_table[h] = (uint)(src_p - src_base);
if ((xxx_ref > src_p - (MAX_DISTANCE + 1)) && ((*(uint*)xxx_ref) == (*(uint*)src_p)))
{
xxx_token = dst_p++;
*xxx_token = 0;
goto _next_match;
}
// Prepare next loop
src_anchor = src_p++;
h_fwd = (*(uint*)src_p * 2654435761u) >> HASH_ADJUST;
}
_last_literals:
// Encode Last Literals
{
var lastRun = (int)(src_end - src_anchor);
if (dst_p + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > dst_end)
{
return 0;
}
if (lastRun >= RUN_MASK)
{
*dst_p++ = RUN_MASK << ML_BITS;
lastRun -= RUN_MASK;
for (; lastRun > 254; lastRun -= 255)
{
*dst_p++ = 255;
}
*dst_p++ = (byte)lastRun;
}
else
{
*dst_p++ = (byte)(lastRun << ML_BITS);
}
BlockCopy32(src_anchor, dst_p, (int)(src_end - src_anchor));
dst_p += src_end - src_anchor;
}
// End
return (int)(dst_p - dst);
}
}
}
#endregion
#region LZ4_compress64kCtx_32
private static unsafe int LZ4_compress64kCtx_32(
ushort* hash_table,
byte* src,
byte* dst,
int src_len,
int dst_maxlen)
{
unchecked
{
byte* _p;
fixed (int* debruijn32 = &DEBRUIJN_TABLE_32[0])
{
// r93
var src_p = src;
var src_anchor = src_p;
var src_base = src_p;
var src_end = src_p + src_len;
var src_mflimit = src_end - MFLIMIT;
var dst_p = dst;
var dst_end = dst_p + dst_maxlen;
var src_LASTLITERALS = src_end - LASTLITERALS;
var src_LASTLITERALS_1 = src_LASTLITERALS - 1;
var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_32 - 1);
var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS);
var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS);
int len, length;
uint h, h_fwd;
// Init
if (src_len < MINLENGTH)
{
goto _last_literals;
}
// First Byte
src_p++;
h_fwd = (*(uint*)src_p * 2654435761u) >> HASH64K_ADJUST;
// Main Loop
while (true)
{
var findMatchAttempts = (1 << SKIPSTRENGTH) + 3;
var src_p_fwd = src_p;
byte* xxx_ref;
byte* xxx_token;
// Find a match
do
{
h = h_fwd;
var step = findMatchAttempts++ >> SKIPSTRENGTH;
src_p = src_p_fwd;
src_p_fwd = src_p + step;
if (src_p_fwd > src_mflimit)
{
goto _last_literals;
}
h_fwd = (*(uint*)src_p_fwd * 2654435761u) >> HASH64K_ADJUST;
xxx_ref = src_base + hash_table[h];
hash_table[h] = (ushort)(src_p - src_base);
}
while ((*(uint*)xxx_ref) != (*(uint*)src_p));
// Catch up
while ((src_p > src_anchor) && (xxx_ref > src) && (src_p[-1] == xxx_ref[-1]))
{
src_p--;
xxx_ref--;
}
// Encode Literal length
length = (int)(src_p - src_anchor);
xxx_token = dst_p++;
if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3)
{
return 0; // Check output limit
}
if (length >= RUN_MASK)
{
len = length - RUN_MASK;
*xxx_token = RUN_MASK << ML_BITS;
if (len > 254)
{
do
{
*dst_p++ = 255;
len -= 255;
}
while (len > 254);
*dst_p++ = (byte)len;
BlockCopy32(src_anchor, dst_p, length);
dst_p += length;
goto _next_match;
}
*dst_p++ = (byte)len;
}
else
{
*xxx_token = (byte)(length << ML_BITS);
}
// Copy Literals
_p = dst_p + length;
do
{
*(uint*)dst_p = *(uint*)src_anchor;
dst_p += 4;
src_anchor += 4;
*(uint*)dst_p = *(uint*)src_anchor;
dst_p += 4;
src_anchor += 4;
}
while (dst_p < _p);
dst_p = _p;
_next_match:
// Encode Offset
*(ushort*)dst_p = (ushort)(src_p - xxx_ref);
dst_p += 2;
// Start Counting
src_p += MINMATCH;
xxx_ref += MINMATCH; // MinMatch verified
src_anchor = src_p;
while (src_p < src_LASTLITERALS_STEPSIZE_1)
{
var diff = (*(int*)xxx_ref) ^ (*(int*)src_p);
if (diff == 0)
{
src_p += STEPSIZE_32;
xxx_ref += STEPSIZE_32;
continue;
}
src_p += debruijn32[((uint)(diff & -diff) * 0x077CB531u) >> 27];
goto _endCount;
}
if ((src_p < src_LASTLITERALS_1) && ((*(ushort*)xxx_ref) == (*(ushort*)src_p)))
{
src_p += 2;
xxx_ref += 2;
}
if ((src_p < src_LASTLITERALS) && (*xxx_ref == *src_p))
{
src_p++;
}
_endCount:
// Encode MatchLength
len = (int)(src_p - src_anchor);
if (dst_p + (len >> 8) > dst_LASTLITERALS_1)
{
return 0; // Check output limit
}
if (len >= ML_MASK)
{
*xxx_token += ML_MASK;
len -= ML_MASK;
for (; len > 509; len -= 510)
{
*dst_p++ = 255;
*dst_p++ = 255;
}
if (len > 254)
{
len -= 255;
*dst_p++ = 255;
}
*dst_p++ = (byte)len;
}
else
{
*xxx_token += (byte)len;
}
// Test end of chunk
if (src_p > src_mflimit)
{
src_anchor = src_p;
break;
}
// Fill table
hash_table[(*(uint*)(src_p - 2) * 2654435761u) >> HASH64K_ADJUST] = (ushort)(src_p - 2 - src_base);
// Test next position
h = (*(uint*)src_p * 2654435761u) >> HASH64K_ADJUST;
xxx_ref = src_base + hash_table[h];
hash_table[h] = (ushort)(src_p - src_base);
if ((*(uint*)xxx_ref) == (*(uint*)src_p))
{
xxx_token = dst_p++;
*xxx_token = 0;
goto _next_match;
}
// Prepare next loop
src_anchor = src_p++;
h_fwd = (*(uint*)src_p * 2654435761u) >> HASH64K_ADJUST;
}
_last_literals:
// Encode Last Literals
{
var lastRun = (int)(src_end - src_anchor);
if (dst_p + lastRun + 1 + ((lastRun - RUN_MASK + 255) / 255) > dst_end)
{
return 0;
}
if (lastRun >= RUN_MASK)
{
*dst_p++ = RUN_MASK << ML_BITS;
lastRun -= RUN_MASK;
for (; lastRun > 254; lastRun -= 255)
{
*dst_p++ = 255;
}
*dst_p++ = (byte)lastRun;
}
else
{
*dst_p++ = (byte)(lastRun << ML_BITS);
}
BlockCopy32(src_anchor, dst_p, (int)(src_end - src_anchor));
dst_p += src_end - src_anchor;
}
// End
return (int)(dst_p - dst);
}
}
}
#endregion
#region LZ4_uncompress_32
private static unsafe int LZ4_uncompress_32(
byte* src,
byte* dst,
int dst_len)
{
unchecked
{
fixed (int* dec32table = &DECODER_TABLE_32[0])
{
// r93
var src_p = src;
byte* xxx_ref;
var dst_p = dst;
var dst_end = dst_p + dst_len;
byte* dst_cpy;
var dst_LASTLITERALS = dst_end - LASTLITERALS;
var dst_COPYLENGTH = dst_end - COPYLENGTH;
var dst_COPYLENGTH_STEPSIZE_4 = dst_end - COPYLENGTH - (STEPSIZE_32 - 4);
uint xxx_token;
// Main Loop
while (true)
{
int length;
// get runlength
xxx_token = *src_p++;
if ((length = (int)(xxx_token >> ML_BITS)) == RUN_MASK)
{
int len;
for (; (len = *src_p++) == 255; length += 255)
{
/* do nothing */
}
length += len;
}
// copy literals
dst_cpy = dst_p + length;
if (dst_cpy > dst_COPYLENGTH)
{
if (dst_cpy != dst_end)
{
goto _output_error; // Error : not enough place for another match (min 4) + 5 literals
}
BlockCopy32(src_p, dst_p, length);
src_p += length;
break; // EOF
}
do
{
*(uint*)dst_p = *(uint*)src_p;
dst_p += 4;
src_p += 4;
*(uint*)dst_p = *(uint*)src_p;
dst_p += 4;
src_p += 4;
}
while (dst_p < dst_cpy);
src_p -= dst_p - dst_cpy;
dst_p = dst_cpy;
// get offset
xxx_ref = dst_cpy - (*(ushort*)src_p);
src_p += 2;
if (xxx_ref < dst)
{
goto _output_error; // Error : offset outside destination buffer
}
// get matchlength
if ((length = (int)(xxx_token & ML_MASK)) == ML_MASK)
{
for (; *src_p == 255; length += 255)
{
src_p++;
}
length += *src_p++;
}
// copy repeated sequence
if ((dst_p - xxx_ref) < STEPSIZE_32)
{
const int dec64 = 0;
dst_p[0] = xxx_ref[0];
dst_p[1] = xxx_ref[1];
dst_p[2] = xxx_ref[2];
dst_p[3] = xxx_ref[3];
dst_p += 4;
xxx_ref += 4;
xxx_ref -= dec32table[dst_p - xxx_ref];
*(uint*)dst_p = *(uint*)xxx_ref;
dst_p += STEPSIZE_32 - 4;
xxx_ref -= dec64;
}
else
{
*(uint*)dst_p = *(uint*)xxx_ref;
dst_p += 4;
xxx_ref += 4;
}
dst_cpy = dst_p + length - (STEPSIZE_32 - 4);
if (dst_cpy > dst_COPYLENGTH_STEPSIZE_4)
{
if (dst_cpy > dst_LASTLITERALS)
{
goto _output_error; // Error : last 5 bytes must be literals
}
{
do
{
*(uint*)dst_p = *(uint*)xxx_ref;
dst_p += 4;
xxx_ref += 4;
*(uint*)dst_p = *(uint*)xxx_ref;
dst_p += 4;
xxx_ref += 4;
}
while (dst_p < dst_COPYLENGTH);
}
while (dst_p < dst_cpy)
{
*dst_p++ = *xxx_ref++;
}
dst_p = dst_cpy;
continue;
}
do
{
*(uint*)dst_p = *(uint*)xxx_ref;
dst_p += 4;
xxx_ref += 4;
*(uint*)dst_p = *(uint*)xxx_ref;
dst_p += 4;
xxx_ref += 4;
}
while (dst_p < dst_cpy);
dst_p = dst_cpy; // correction
}
// end of decoding
return (int)(src_p - src);
// write overflow error detected
_output_error:
return (int)-(src_p - src);
}
}
}
#endregion
/// <summary>Copies block of memory.</summary>
/// <param name="src">The source.</param>
/// <param name="dst">The destination.</param>
/// <param name="len">The length (in bytes).</param>
private static unsafe void BlockCopy32(byte* src, byte* dst, int len)
{
while (len >= 4)
{
*(uint*)dst = *(uint*)src;
dst += 4;
src += 4;
len -= 4;
}
if (len >= 2)
{
*(ushort*)dst = *(ushort*)src;
dst += 2;
src += 2;
len -= 2;
}
if (len >= 1)
{
*dst = *src; /* d++; s++; l--; */
}
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 44efef809614456e8a4d40559c526efa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,808 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#region LZ4 original
/*
LZ4 - Fast LZ compression algorithm
Copyright (C) 2011-2012, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
- LZ4 source repository : http://code.google.com/p/lz4/
*/
#endregion
#region LZ4 port
/*
Copyright (c) 2013, Milosz Krajewski
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#endregion
#pragma warning disable SA1312 // Variable names should begin with lower-case letter
namespace MessagePack.LZ4
{
internal partial class LZ4Codec
{
#region LZ4_compressCtx_64
private static unsafe int LZ4_compressCtx_64(
uint* hash_table,
byte* src,
byte* dst,
int src_len,
int dst_maxlen)
{
unchecked
{
byte* _p;
fixed (int* debruijn64 = &DEBRUIJN_TABLE_64[0])
{
// r93
var src_p = src;
var src_base = src_p;
var src_anchor = src_p;
var src_end = src_p + src_len;
var src_mflimit = src_end - MFLIMIT;
var dst_p = dst;
var dst_end = dst_p + dst_maxlen;
var src_LASTLITERALS = src_end - LASTLITERALS;
var src_LASTLITERALS_1 = src_LASTLITERALS - 1;
var src_LASTLITERALS_3 = src_LASTLITERALS - 3;
var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_64 - 1);
var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS);
var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS);
int length;
uint h, h_fwd;
// Init
if (src_len < MINLENGTH)
{
goto _last_literals;
}
// First Byte
hash_table[(*(uint*)src_p * 2654435761u) >> HASH_ADJUST] = (uint)(src_p - src_base);
src_p++;
h_fwd = (*(uint*)src_p * 2654435761u) >> HASH_ADJUST;
// Main Loop
while (true)
{
var findMatchAttempts = (1 << SKIPSTRENGTH) + 3;
var src_p_fwd = src_p;
byte* src_ref;
byte* dst_token;
// Find a match
do
{
h = h_fwd;
var step = findMatchAttempts++ >> SKIPSTRENGTH;
src_p = src_p_fwd;
src_p_fwd = src_p + step;
if (src_p_fwd > src_mflimit)
{
goto _last_literals;
}
h_fwd = (*(uint*)src_p_fwd * 2654435761u) >> HASH_ADJUST;
src_ref = src_base + hash_table[h];
hash_table[h] = (uint)(src_p - src_base);
}
while ((src_ref < src_p - MAX_DISTANCE) || ((*(uint*)src_ref) != (*(uint*)src_p)));
// Catch up
while ((src_p > src_anchor) && (src_ref > src) && (src_p[-1] == src_ref[-1]))
{
src_p--;
src_ref--;
}
// Encode Literal length
length = (int)(src_p - src_anchor);
dst_token = dst_p++;
if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3)
{
return 0; // Check output limit
}
if (length >= RUN_MASK)
{
var len = length - RUN_MASK;
*dst_token = RUN_MASK << ML_BITS;
if (len > 254)
{
do
{
*dst_p++ = 255;
len -= 255;
}
while (len > 254);
*dst_p++ = (byte)len;
BlockCopy64(src_anchor, dst_p, length);
dst_p += length;
goto _next_match;
}
*dst_p++ = (byte)len;
}
else
{
*dst_token = (byte)(length << ML_BITS);
}
// Copy Literals
_p = dst_p + length;
{
do
{
*(ulong*)dst_p = *(ulong*)src_anchor;
dst_p += 8;
src_anchor += 8;
}
while (dst_p < _p);
}
dst_p = _p;
_next_match:
// Encode Offset
*(ushort*)dst_p = (ushort)(src_p - src_ref);
dst_p += 2;
// Start Counting
src_p += MINMATCH;
src_ref += MINMATCH; // MinMatch already verified
src_anchor = src_p;
while (src_p < src_LASTLITERALS_STEPSIZE_1)
{
var diff = (*(long*)src_ref) ^ (*(long*)src_p);
if (diff == 0)
{
src_p += STEPSIZE_64;
src_ref += STEPSIZE_64;
continue;
}
src_p += debruijn64[((ulong)(diff & -diff) * 0x0218A392CDABBD3FL) >> 58];
goto _endCount;
}
if ((src_p < src_LASTLITERALS_3) && ((*(uint*)src_ref) == (*(uint*)src_p)))
{
src_p += 4;
src_ref += 4;
}
if ((src_p < src_LASTLITERALS_1) && ((*(ushort*)src_ref) == (*(ushort*)src_p)))
{
src_p += 2;
src_ref += 2;
}
if ((src_p < src_LASTLITERALS) && (*src_ref == *src_p))
{
src_p++;
}
_endCount:
// Encode MatchLength
length = (int)(src_p - src_anchor);
if (dst_p + (length >> 8) > dst_LASTLITERALS_1)
{
return 0; // Check output limit
}
if (length >= ML_MASK)
{
*dst_token += ML_MASK;
length -= ML_MASK;
for (; length > 509; length -= 510)
{
*dst_p++ = 255;
*dst_p++ = 255;
}
if (length > 254)
{
length -= 255;
*dst_p++ = 255;
}
*dst_p++ = (byte)length;
}
else
{
*dst_token += (byte)length;
}
// Test end of chunk
if (src_p > src_mflimit)
{
src_anchor = src_p;
break;
}
// Fill table
hash_table[(*(uint*)(src_p - 2) * 2654435761u) >> HASH_ADJUST] = (uint)(src_p - 2 - src_base);
// Test next position
h = (*(uint*)src_p * 2654435761u) >> HASH_ADJUST;
src_ref = src_base + hash_table[h];
hash_table[h] = (uint)(src_p - src_base);
if ((src_ref > src_p - (MAX_DISTANCE + 1)) && ((*(uint*)src_ref) == (*(uint*)src_p)))
{
dst_token = dst_p++;
*dst_token = 0;
goto _next_match;
}
// Prepare next loop
src_anchor = src_p++;
h_fwd = (*(uint*)src_p * 2654435761u) >> HASH_ADJUST;
}
_last_literals:
// Encode Last Literals
var lastRun = (int)(src_end - src_anchor);
if (dst_p + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > dst_end)
{
return 0;
}
if (lastRun >= RUN_MASK)
{
*dst_p++ = RUN_MASK << ML_BITS;
lastRun -= RUN_MASK;
for (; lastRun > 254; lastRun -= 255)
{
*dst_p++ = 255;
}
*dst_p++ = (byte)lastRun;
}
else
{
*dst_p++ = (byte)(lastRun << ML_BITS);
}
BlockCopy64(src_anchor, dst_p, (int)(src_end - src_anchor));
dst_p += src_end - src_anchor;
// End
return (int)(dst_p - dst);
}
}
}
#endregion
#region LZ4_compress64kCtx_64
private static unsafe int LZ4_compress64kCtx_64(
ushort* hash_table,
byte* src,
byte* dst,
int src_len,
int dst_maxlen)
{
unchecked
{
byte* _p;
fixed (int* debruijn64 = &DEBRUIJN_TABLE_64[0])
{
// r93
var src_p = src;
var src_anchor = src_p;
var src_base = src_p;
var src_end = src_p + src_len;
var src_mflimit = src_end - MFLIMIT;
var dst_p = dst;
var dst_end = dst_p + dst_maxlen;
var src_LASTLITERALS = src_end - LASTLITERALS;
var src_LASTLITERALS_1 = src_LASTLITERALS - 1;
var src_LASTLITERALS_3 = src_LASTLITERALS - 3;
var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_64 - 1);
var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS);
var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS);
int len, length;
uint h, h_fwd;
// Init
if (src_len < MINLENGTH)
{
goto _last_literals;
}
// First Byte
src_p++;
h_fwd = (*(uint*)src_p * 2654435761u) >> HASH64K_ADJUST;
// Main Loop
while (true)
{
var findMatchAttempts = (1 << SKIPSTRENGTH) + 3;
var src_p_fwd = src_p;
byte* src_ref;
byte* dst_token;
// Find a match
do
{
h = h_fwd;
var step = findMatchAttempts++ >> SKIPSTRENGTH;
src_p = src_p_fwd;
src_p_fwd = src_p + step;
if (src_p_fwd > src_mflimit)
{
goto _last_literals;
}
h_fwd = (*(uint*)src_p_fwd * 2654435761u) >> HASH64K_ADJUST;
src_ref = src_base + hash_table[h];
hash_table[h] = (ushort)(src_p - src_base);
}
while ((*(uint*)src_ref) != (*(uint*)src_p));
// Catch up
while ((src_p > src_anchor) && (src_ref > src) && (src_p[-1] == src_ref[-1]))
{
src_p--;
src_ref--;
}
// Encode Literal length
length = (int)(src_p - src_anchor);
dst_token = dst_p++;
if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3)
{
return 0; // Check output limit
}
if (length >= RUN_MASK)
{
len = length - RUN_MASK;
*dst_token = RUN_MASK << ML_BITS;
if (len > 254)
{
do
{
*dst_p++ = 255;
len -= 255;
}
while (len > 254);
*dst_p++ = (byte)len;
BlockCopy64(src_anchor, dst_p, length);
dst_p += length;
goto _next_match;
}
*dst_p++ = (byte)len;
}
else
{
*dst_token = (byte)(length << ML_BITS);
}
// Copy Literals
{
_p = dst_p + length;
{
do
{
*(ulong*)dst_p = *(ulong*)src_anchor;
dst_p += 8;
src_anchor += 8;
}
while (dst_p < _p);
}
dst_p = _p;
}
_next_match:
// Encode Offset
*(ushort*)dst_p = (ushort)(src_p - src_ref);
dst_p += 2;
// Start Counting
src_p += MINMATCH;
src_ref += MINMATCH; // MinMatch verified
src_anchor = src_p;
while (src_p < src_LASTLITERALS_STEPSIZE_1)
{
var diff = (*(long*)src_ref) ^ (*(long*)src_p);
if (diff == 0)
{
src_p += STEPSIZE_64;
src_ref += STEPSIZE_64;
continue;
}
src_p += debruijn64[((ulong)(diff & -diff) * 0x0218A392CDABBD3FL) >> 58];
goto _endCount;
}
if ((src_p < src_LASTLITERALS_3) && ((*(uint*)src_ref) == (*(uint*)src_p)))
{
src_p += 4;
src_ref += 4;
}
if ((src_p < src_LASTLITERALS_1) && ((*(ushort*)src_ref) == (*(ushort*)src_p)))
{
src_p += 2;
src_ref += 2;
}
if ((src_p < src_LASTLITERALS) && (*src_ref == *src_p))
{
src_p++;
}
_endCount:
// Encode MatchLength
len = (int)(src_p - src_anchor);
if (dst_p + (len >> 8) > dst_LASTLITERALS_1)
{
return 0; // Check output limit
}
if (len >= ML_MASK)
{
*dst_token += ML_MASK;
len -= ML_MASK;
for (; len > 509; len -= 510)
{
*dst_p++ = 255;
*dst_p++ = 255;
}
if (len > 254)
{
len -= 255;
*dst_p++ = 255;
}
*dst_p++ = (byte)len;
}
else
{
*dst_token += (byte)len;
}
// Test end of chunk
if (src_p > src_mflimit)
{
src_anchor = src_p;
break;
}
// Fill table
hash_table[(*(uint*)(src_p - 2) * 2654435761u) >> HASH64K_ADJUST] = (ushort)(src_p - 2 - src_base);
// Test next position
h = (*(uint*)src_p * 2654435761u) >> HASH64K_ADJUST;
src_ref = src_base + hash_table[h];
hash_table[h] = (ushort)(src_p - src_base);
if ((*(uint*)src_ref) == (*(uint*)src_p))
{
dst_token = dst_p++;
*dst_token = 0;
goto _next_match;
}
// Prepare next loop
src_anchor = src_p++;
h_fwd = (*(uint*)src_p * 2654435761u) >> HASH64K_ADJUST;
}
_last_literals:
// Encode Last Literals
var lastRun = (int)(src_end - src_anchor);
if (dst_p + lastRun + 1 + ((lastRun - RUN_MASK + 255) / 255) > dst_end)
{
return 0;
}
if (lastRun >= RUN_MASK)
{
*dst_p++ = RUN_MASK << ML_BITS;
lastRun -= RUN_MASK;
for (; lastRun > 254; lastRun -= 255)
{
*dst_p++ = 255;
}
*dst_p++ = (byte)lastRun;
}
else
{
*dst_p++ = (byte)(lastRun << ML_BITS);
}
BlockCopy64(src_anchor, dst_p, (int)(src_end - src_anchor));
dst_p += src_end - src_anchor;
// End
return (int)(dst_p - dst);
}
}
}
#endregion
#region LZ4_uncompress_64
private static unsafe int LZ4_uncompress_64(
byte* src,
byte* dst,
int dst_len)
{
unchecked
{
fixed (int* dec32table = &DECODER_TABLE_32[0])
fixed (int* dec64table = &DECODER_TABLE_64[0])
{
// r93
var src_p = src;
byte* dst_ref;
var dst_p = dst;
var dst_end = dst_p + dst_len;
byte* dst_cpy;
var dst_LASTLITERALS = dst_end - LASTLITERALS;
var dst_COPYLENGTH = dst_end - COPYLENGTH;
var dst_COPYLENGTH_STEPSIZE_4 = dst_end - COPYLENGTH - (STEPSIZE_64 - 4);
byte token;
// Main Loop
while (true)
{
int length;
// get runlength
token = *src_p++;
if ((length = token >> ML_BITS) == RUN_MASK)
{
int len;
for (; (len = *src_p++) == 255; length += 255)
{
/* do nothing */
}
length += len;
}
// copy literals
dst_cpy = dst_p + length;
if (dst_cpy > dst_COPYLENGTH)
{
if (dst_cpy != dst_end)
{
goto _output_error; // Error : not enough place for another match (min 4) + 5 literals
}
BlockCopy64(src_p, dst_p, length);
src_p += length;
break; // EOF
}
do
{
*(ulong*)dst_p = *(ulong*)src_p;
dst_p += 8;
src_p += 8;
}
while (dst_p < dst_cpy);
src_p -= dst_p - dst_cpy;
dst_p = dst_cpy;
// get offset
dst_ref = dst_cpy - (*(ushort*)src_p);
src_p += 2;
if (dst_ref < dst)
{
goto _output_error; // Error : offset outside destination buffer
}
// get matchlength
if ((length = token & ML_MASK) == ML_MASK)
{
for (; *src_p == 255; length += 255)
{
src_p++;
}
length += *src_p++;
}
// copy repeated sequence
if ((dst_p - dst_ref) < STEPSIZE_64)
{
var dec64 = dec64table[dst_p - dst_ref];
dst_p[0] = dst_ref[0];
dst_p[1] = dst_ref[1];
dst_p[2] = dst_ref[2];
dst_p[3] = dst_ref[3];
dst_p += 4;
dst_ref += 4;
dst_ref -= dec32table[dst_p - dst_ref];
*(uint*)dst_p = *(uint*)dst_ref;
dst_p += STEPSIZE_64 - 4;
dst_ref -= dec64;
}
else
{
*(ulong*)dst_p = *(ulong*)dst_ref;
dst_p += 8;
dst_ref += 8;
}
dst_cpy = dst_p + length - (STEPSIZE_64 - 4);
if (dst_cpy > dst_COPYLENGTH_STEPSIZE_4)
{
if (dst_cpy > dst_LASTLITERALS)
{
goto _output_error; // Error : last 5 bytes must be literals
}
while (dst_p < dst_COPYLENGTH)
{
*(ulong*)dst_p = *(ulong*)dst_ref;
dst_p += 8;
dst_ref += 8;
}
while (dst_p < dst_cpy)
{
*dst_p++ = *dst_ref++;
}
dst_p = dst_cpy;
continue;
}
{
do
{
*(ulong*)dst_p = *(ulong*)dst_ref;
dst_p += 8;
dst_ref += 8;
}
while (dst_p < dst_cpy);
}
dst_p = dst_cpy; // correction
}
// end of decoding
return (int)(src_p - src);
// write overflow error detected
_output_error:
return (int)-(src_p - src);
}
}
}
#endregion
/// <summary>Copies block of memory.</summary>
/// <param name="src">The source.</param>
/// <param name="dst">The destination.</param>
/// <param name="len">The length (in bytes).</param>
private static unsafe void BlockCopy64(byte* src, byte* dst, int len)
{
while (len >= 8)
{
*(ulong*)dst = *(ulong*)src;
dst += 8;
src += 8;
len -= 8;
}
if (len >= 4)
{
*(uint*)dst = *(uint*)src;
dst += 4;
src += 4;
len -= 4;
}
if (len >= 2)
{
*(ushort*)dst = *(ushort*)src;
dst += 2;
src += 2;
len -= 2;
}
if (len >= 1)
{
*dst = *src; /* d++; s++; l--; */
}
}
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: fa2e5105dcebe0410bb8ed76f622889f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,178 +0,0 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#region license
/*
Copyright (c) 2013, Milosz Krajewski
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#endregion
using System;
#pragma warning disable SA1310 // Field names should not contain underscore
namespace MessagePack.LZ4
{
internal static partial class LZ4Codec
{
#region configuration
/// <summary>
/// Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
/// Increasing memory usage improves compression ratio
/// Reduced memory usage can improve speed, due to cache effect
/// Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache.
/// </summary>
private const int MEMORY_USAGE = 12; // modified use 12.
/// <summary>
/// Decreasing this value will make the algorithm skip faster data segments considered "incompressible"
/// This may decrease compression ratio dramatically, but will be faster on incompressible data
/// Increasing this value will make the algorithm search more before declaring a segment "incompressible"
/// This could improve compression a bit, but will be slower on incompressible data
/// The default value (6) is recommended.
/// </summary>
private const int NOTCOMPRESSIBLE_DETECTIONLEVEL = 6;
#endregion
#region consts
private const int MINMATCH = 4;
#pragma warning disable 162, 429
private const int SKIPSTRENGTH = NOTCOMPRESSIBLE_DETECTIONLEVEL > 2 ? NOTCOMPRESSIBLE_DETECTIONLEVEL : 2;
#pragma warning restore 162, 429
private const int COPYLENGTH = 8;
private const int LASTLITERALS = 5;
private const int MFLIMIT = COPYLENGTH + MINMATCH;
private const int MINLENGTH = MFLIMIT + 1;
private const int MAXD_LOG = 16;
private const int MAXD = 1 << MAXD_LOG;
private const int MAXD_MASK = MAXD - 1;
private const int MAX_DISTANCE = (1 << MAXD_LOG) - 1;
private const int ML_BITS = 4;
private const int ML_MASK = (1 << ML_BITS) - 1;
private const int RUN_BITS = 8 - ML_BITS;
private const int RUN_MASK = (1 << RUN_BITS) - 1;
private const int STEPSIZE_64 = 8;
private const int STEPSIZE_32 = 4;
private const int LZ4_64KLIMIT = (1 << 16) + (MFLIMIT - 1);
private const int HASH_LOG = MEMORY_USAGE - 2;
private const int HASH_TABLESIZE = 1 << HASH_LOG;
private const int HASH_ADJUST = (MINMATCH * 8) - HASH_LOG;
private const int HASH64K_LOG = HASH_LOG + 1;
private const int HASH64K_TABLESIZE = 1 << HASH64K_LOG;
private const int HASH64K_ADJUST = (MINMATCH * 8) - HASH64K_LOG;
private const int HASHHC_LOG = MAXD_LOG - 1;
private const int HASHHC_TABLESIZE = 1 << HASHHC_LOG;
private const int HASHHC_ADJUST = (MINMATCH * 8) - HASHHC_LOG;
////private const int HASHHC_MASK = HASHHC_TABLESIZE - 1;
private const int MAX_NB_ATTEMPTS = 256;
private const int OPTIMAL_ML = ML_MASK - 1 + MINMATCH;
private const int BLOCK_COPY_LIMIT = 16;
private static readonly int[] DECODER_TABLE_32 = { 0, 3, 2, 3, 0, 0, 0, 0 };
private static readonly int[] DECODER_TABLE_64 = { 0, 0, 0, -1, 0, 1, 2, 3 };
private static readonly int[] DEBRUIJN_TABLE_32 =
{
0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1,
3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1,
};
private static readonly int[] DEBRUIJN_TABLE_64 =
{
0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7,
0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7,
7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6,
7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7,
};
#endregion
#region public interface (common)
/// <summary>Gets maximum the length of the output.</summary>
/// <param name="inputLength">Length of the input.</param>
/// <returns>Maximum number of bytes needed for compressed buffer.</returns>
public static int MaximumOutputLength(int inputLength)
{
return inputLength + (inputLength / 255) + 16;
}
#endregion
#region internal interface (common)
internal static void CheckArguments(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int outputLength)
{
if (inputLength == 0)
{
outputLength = 0;
return;
}
if (input == null)
{
throw new ArgumentNullException("input");
}
if ((uint)inputOffset > (uint)input.Length)
{
throw new ArgumentOutOfRangeException("inputOffset");
}
if ((uint)inputLength > (uint)input.Length - (uint)inputOffset)
{
throw new ArgumentOutOfRangeException("inputLength");
}
if (output == null)
{
throw new ArgumentNullException("output");
}
if ((uint)outputOffset > (uint)output.Length)
{
throw new ArgumentOutOfRangeException("outputOffset");
}
if ((uint)outputLength > (uint)output.Length - (uint)outputOffset)
{
throw new ArgumentOutOfRangeException("outputLength");
}
}
#endregion
}
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: b67a7760eb98ee768b90af4f2d6d9dc4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show more