mirror of
https://github.com/StarBeat/UnityDependencyAnalyzer.git
synced 2026-03-08 05:35:27 +08:00
add AssetDependencyGraph
This commit is contained in:
parent
835ede37f6
commit
23e8539500
16
AssetDependencyGraph/AssetDependencyGraph-Editor.asmdef
Normal file
16
AssetDependencyGraph/AssetDependencyGraph-Editor.asmdef
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "AssetDependencyGraph-Editor",
|
||||
"rootNamespace": "",
|
||||
"references": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f6edbbfd6f04b1479b191b629a0421f
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
AssetDependencyGraph/Editor.meta
Normal file
8
AssetDependencyGraph/Editor.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9303f9c952516f34cbc668b8d9217ee7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
323
AssetDependencyGraph/Editor/AssetDefine.cs
Normal file
323
AssetDependencyGraph/Editor/AssetDefine.cs
Normal file
@ -0,0 +1,323 @@
|
||||
using MemoryPack;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using MongoDB.Driver;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AssetDependencyGraph
|
||||
{
|
||||
[BsonIgnoreExtraElements]
|
||||
[MemoryPackable]
|
||||
public partial class AssetIdentify
|
||||
{
|
||||
public string Path = null!;
|
||||
public string AssetType = null!;
|
||||
public string Guid;
|
||||
public string Md5;
|
||||
}
|
||||
|
||||
public sealed class AssetIdentifyJsonConverter : JsonConverter<AssetIdentify>
|
||||
{
|
||||
static JsonSerializerOptions serializerOptions = new JsonSerializerOptions() { IncludeFields = true };
|
||||
|
||||
public override AssetIdentify? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return JsonSerializer.Deserialize<AssetIdentify>(reader.GetString()!, serializerOptions);
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, AssetIdentify value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStringValue(JsonSerializer.Serialize(value, serializerOptions));
|
||||
}
|
||||
|
||||
public override AssetIdentify ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return Read(ref reader, typeToConvert, serializerOptions)!;
|
||||
}
|
||||
|
||||
public override void WriteAsPropertyName(Utf8JsonWriter writer, [DisallowNull] AssetIdentify value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WritePropertyName(JsonSerializer.Serialize(value, serializerOptions));
|
||||
}
|
||||
}
|
||||
|
||||
[BsonIgnoreExtraElements]
|
||||
[MemoryPackable]
|
||||
public partial class AssetNode
|
||||
{
|
||||
public AssetIdentify Self = null!;
|
||||
public string AssetType = null!;
|
||||
[JsonIgnore]
|
||||
[MemoryPackIgnore]
|
||||
public ConcurrentBag<AssetIdentify> Dependencies = new();
|
||||
[JsonIgnore]
|
||||
[MemoryPackIgnore]
|
||||
public ConcurrentBag<AssetIdentify> Dependent = new();
|
||||
|
||||
[AllowNull]
|
||||
public HashSet<AssetIdentify> DependencySet;
|
||||
[AllowNull]
|
||||
public HashSet<AssetIdentify> DependentSet;
|
||||
}
|
||||
|
||||
public sealed class AssetNodeJsonConverter : JsonConverter<AssetNode>
|
||||
{
|
||||
static JsonSerializerOptions serializerOptions = new JsonSerializerOptions()
|
||||
{
|
||||
IncludeFields = true,
|
||||
Converters = { new AssetIdentifyJsonConverter() }
|
||||
};
|
||||
|
||||
public override AssetNode? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return JsonSerializer.Deserialize<AssetNode>(reader.GetString()!, serializerOptions);
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, AssetNode value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStringValue(JsonSerializer.Serialize(value, serializerOptions));
|
||||
}
|
||||
}
|
||||
|
||||
[BsonIgnoreExtraElements]
|
||||
public sealed class FolderNode : AssetNode
|
||||
{
|
||||
}
|
||||
|
||||
[BsonIgnoreExtraElements]
|
||||
public sealed class PackageNode : AssetNode
|
||||
{
|
||||
}
|
||||
|
||||
public class AssetDependencyGraphDB
|
||||
{
|
||||
MongoClient client;
|
||||
IMongoCollection<FolderNode> FolderNodes;
|
||||
IMongoCollection<PackageNode> PackageNodes;
|
||||
IMongoCollection<AssetNode> AssetNodes;
|
||||
Dictionary<string, AssetNode> findCacheDic = new();
|
||||
|
||||
public AssetDependencyGraphDB(string user, string passwd, string ip)
|
||||
{
|
||||
MongoClientSettings settings;
|
||||
if (string.IsNullOrWhiteSpace(user) && !string.IsNullOrEmpty(ip))
|
||||
{
|
||||
settings = MongoClientSettings.FromUrl(new MongoUrl($"mongodb://{ip}:27017/"));
|
||||
}
|
||||
else
|
||||
{
|
||||
settings = MongoClientSettings.FromUrl(new MongoUrl($"mongodb://{user}:{passwd}@{ip}:27017/"));
|
||||
}
|
||||
|
||||
settings.ConnectTimeout = TimeSpan.FromSeconds(5);
|
||||
settings.MinConnectionPoolSize = 1;
|
||||
settings.MaxConnectionPoolSize = 25;
|
||||
client = new MongoClient(settings);
|
||||
var db = client.GetDatabase("assetgraph");
|
||||
FolderNodes = db.GetCollection<FolderNode>("folder_nodes");
|
||||
PackageNodes = db.GetCollection<PackageNode>("package_nodes");
|
||||
AssetNodes = db.GetCollection<AssetNode>("asset_nodes");
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
client.DropDatabase("assetgraph");
|
||||
var db = client.GetDatabase("assetgraph");
|
||||
FolderNodes = db.GetCollection<FolderNode>("folder_nodes");
|
||||
PackageNodes = db.GetCollection<PackageNode>("package_nodes");
|
||||
AssetNodes = db.GetCollection<AssetNode>("asset_nodes");
|
||||
}
|
||||
|
||||
public void Insert<T>(T node) where T : AssetNode
|
||||
{
|
||||
switch (node)
|
||||
{
|
||||
case FolderNode folderNode:
|
||||
{
|
||||
FolderNodes.InsertOne(folderNode);
|
||||
break;
|
||||
}
|
||||
case PackageNode packageNode:
|
||||
{
|
||||
PackageNodes.InsertOne(packageNode);
|
||||
break;
|
||||
}
|
||||
case AssetNode assetNode:
|
||||
{
|
||||
AssetNodes.InsertOne(assetNode);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateOrInsert<T>(T node) where T : AssetNode
|
||||
{
|
||||
switch (node)
|
||||
{
|
||||
case FolderNode folderNode:
|
||||
{
|
||||
var filter = Builders<FolderNode>.Filter.And(
|
||||
Builders<FolderNode>.Filter.Eq(fn => fn.Self.Path, node.Self.Path)
|
||||
);
|
||||
var found = FolderNodes.Find(filter);
|
||||
if (found == null || found.CountDocuments() == 0)
|
||||
{
|
||||
FolderNodes.InsertOne(folderNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = FolderNodes.UpdateOne(filter, Builders<FolderNode>.Update.Combine(
|
||||
Builders<FolderNode>.Update.Set(fn => fn.Self, folderNode.Self),
|
||||
Builders<FolderNode>.Update.Set(fn => fn.AssetType, folderNode.AssetType),
|
||||
Builders<FolderNode>.Update.Set(fn => fn.Dependencies, folderNode.Dependencies),
|
||||
Builders<FolderNode>.Update.Set(fn => fn.Dependent, folderNode.Dependent)
|
||||
));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PackageNode packageNode:
|
||||
{
|
||||
var filter = Builders<PackageNode>.Filter.And(
|
||||
Builders<PackageNode>.Filter.Eq(fn => fn.Self.Path, node.Self.Path)
|
||||
);
|
||||
var found = PackageNodes.Find(filter);
|
||||
if (found == null || found.CountDocuments() == 0)
|
||||
{
|
||||
PackageNodes.InsertOne(packageNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = PackageNodes.UpdateOne(filter, Builders<PackageNode>.Update.Combine(
|
||||
Builders<PackageNode>.Update.Set(fn => fn.Self, packageNode.Self),
|
||||
Builders<PackageNode>.Update.Set(fn => fn.AssetType, packageNode.AssetType),
|
||||
Builders<PackageNode>.Update.Set(fn => fn.Dependencies, packageNode.Dependencies),
|
||||
Builders<PackageNode>.Update.Set(fn => fn.Dependent, packageNode.Dependent)
|
||||
));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AssetNode assetNode:
|
||||
{
|
||||
var filter = Builders<AssetNode>.Filter.And(
|
||||
Builders<AssetNode>.Filter.Eq(fn => fn.Self.Path, node.Self.Path)
|
||||
);
|
||||
var found = AssetNodes.Find(filter);
|
||||
if (found == null || found.CountDocuments() == 0)
|
||||
{
|
||||
AssetNodes.InsertOne(assetNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = AssetNodes.UpdateOne(filter, Builders<AssetNode>.Update.Combine(
|
||||
Builders<AssetNode>.Update.Set(fn => fn.Self, assetNode.Self),
|
||||
Builders<AssetNode>.Update.Set(fn => fn.AssetType, assetNode.AssetType),
|
||||
Builders<AssetNode>.Update.Set(fn => fn.Dependencies, assetNode.Dependencies),
|
||||
Builders<AssetNode>.Update.Set(fn => fn.Dependent, assetNode.Dependent)
|
||||
));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Delete<T>(T node) where T : AssetNode
|
||||
{
|
||||
switch (node)
|
||||
{
|
||||
case FolderNode folderNode:
|
||||
{
|
||||
var filter = Builders<FolderNode>.Filter.And(
|
||||
Builders<FolderNode>.Filter.Eq(fn => fn.Self.Path, node.Self.Path)
|
||||
);
|
||||
var found = FolderNodes.Find(filter);
|
||||
if (found != null && found.CountDocuments() == 0)
|
||||
{
|
||||
// TODO: del ref dep
|
||||
FolderNodes.DeleteOne(filter);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PackageNode packageNode:
|
||||
{
|
||||
var filter = Builders<PackageNode>.Filter.And(
|
||||
Builders<PackageNode>.Filter.Eq(fn => fn.Self.Path, node.Self.Path)
|
||||
);
|
||||
var found = PackageNodes.Find(filter);
|
||||
if (found != null && found.CountDocuments() == 0)
|
||||
{
|
||||
// TODO: del ref dep
|
||||
PackageNodes.DeleteOne(filter);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AssetNode assetNode:
|
||||
{
|
||||
var filter = Builders<AssetNode>.Filter.And(
|
||||
Builders<AssetNode>.Filter.Eq(fn => fn.Self.Path, node.Self.Path)
|
||||
);
|
||||
var found = AssetNodes.Find(filter);
|
||||
if (found != null && found.CountDocuments() == 0)
|
||||
{
|
||||
// TODO: del ref dep
|
||||
AssetNodes.DeleteOne(filter);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public AssetNode Find(string path)
|
||||
{
|
||||
if (findCacheDic.TryGetValue(path, out var assetNode))
|
||||
{
|
||||
return assetNode;
|
||||
}
|
||||
|
||||
var filter = Builders<AssetNode>.Filter.And(
|
||||
Builders<AssetNode>.Filter.Eq(fn => fn.Self.Path, path)
|
||||
);
|
||||
var found = AssetNodes.Find(filter);
|
||||
if (found != null && found.CountDocuments() != 0)
|
||||
{
|
||||
assetNode = found.First();
|
||||
findCacheDic[path] = assetNode;
|
||||
return assetNode;
|
||||
}
|
||||
|
||||
var filter1 = Builders<PackageNode>.Filter.And(
|
||||
Builders<PackageNode>.Filter.Eq(fn => fn.Self.Path, path)
|
||||
);
|
||||
var found1 = PackageNodes.Find(filter1);
|
||||
if (found1 != null && found1.CountDocuments() != 0)
|
||||
{
|
||||
assetNode = found1.First();
|
||||
findCacheDic[path] = assetNode;
|
||||
return assetNode;
|
||||
}
|
||||
|
||||
var filter2 = Builders<FolderNode>.Filter.And(
|
||||
Builders<FolderNode>.Filter.Eq(fn => fn.Self.Path, path)
|
||||
);
|
||||
var found2 = FolderNodes.Find(filter2);
|
||||
if (found2 != null && found2.CountDocuments() != 0)
|
||||
{
|
||||
assetNode = found2.First();
|
||||
findCacheDic[path] = assetNode;
|
||||
return assetNode;
|
||||
}
|
||||
|
||||
return null!;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
AssetDependencyGraph/Editor/AssetDefine.cs.meta
Normal file
11
AssetDependencyGraph/Editor/AssetDefine.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b678f0fc58371c4cb7735b9906443fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,7 +1,8 @@
|
||||
using MemoryPack;
|
||||
using Sirenix.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
using UnityEditor.UIElements;
|
||||
@ -33,6 +34,7 @@ namespace AssetDependencyGraph
|
||||
|
||||
background.StretchToParentSize();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class AssetGroup
|
||||
@ -72,6 +74,8 @@ namespace AssetDependencyGraph
|
||||
|
||||
private static Dictionary<AssetIdentify, AssetNode> assetId2NodeDic;
|
||||
private static Dictionary<string, AssetIdentify> path2NodeIdDic;
|
||||
private static Dictionary<string, string> guid2PathDic = new();
|
||||
private static Dictionary<string, string> path2GuidDic = new();
|
||||
|
||||
static AssetNode FindAssetNode(string path)
|
||||
{
|
||||
@ -109,25 +113,71 @@ namespace AssetDependencyGraph
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string GUIDToPath(string guid)
|
||||
{
|
||||
if(guid2PathDic != null)
|
||||
{
|
||||
if (guid2PathDic.ContainsKey(guid))
|
||||
{
|
||||
return guid2PathDic[guid];
|
||||
}
|
||||
}
|
||||
return AssetDatabase.GUIDToAssetPath(guid);
|
||||
}
|
||||
|
||||
private static string PathToGUID(string path)
|
||||
{
|
||||
if(path2NodeIdDic != null)
|
||||
{
|
||||
if(path2NodeIdDic.ContainsKey(path))
|
||||
{
|
||||
return path2GuidDic[path];
|
||||
}
|
||||
}
|
||||
|
||||
return AssetDatabase.AssetPathToGUID(path);
|
||||
}
|
||||
|
||||
void ResolveDependency()
|
||||
{
|
||||
var dependencyGraph = Path.Combine(Application.dataPath.Replace("Assets", ""), "Library", "dependencyGraph.json");
|
||||
System.Diagnostics.Stopwatch stopwatch = new();
|
||||
|
||||
var projectPath = Application.dataPath.Replace("Assets", "");
|
||||
var libraryPath = Path.Combine(projectPath, "Library");
|
||||
var dependencyGraph = Path.Combine(libraryPath, "dependencyGraph.bin");
|
||||
if (!File.Exists(dependencyGraph))
|
||||
{
|
||||
EditorUtility.DisplayDialog("提示", "需要解析引用关系", "确认");
|
||||
return;
|
||||
}
|
||||
var js = File.ReadAllText(dependencyGraph);
|
||||
assetId2NodeDic = JsonSerializer.Deserialize<Dictionary<AssetIdentify, AssetNode>>(js, options: new JsonSerializerOptions()
|
||||
|
||||
var bytes = File.ReadAllBytes(dependencyGraph);
|
||||
stopwatch.Restart();
|
||||
|
||||
assetId2NodeDic = MemoryPackSerializer.Deserialize<Dictionary<AssetIdentify, AssetNode>>(bytes.AsSpan());
|
||||
|
||||
var guid2pathBinPath = Path.Combine(libraryPath, "guid2path.bin");
|
||||
if (File.Exists(guid2pathBinPath))
|
||||
{
|
||||
IncludeFields = true,
|
||||
Converters = { new AssetIdentifyJsonConverter(), new AssetNodeJsonConverter() }
|
||||
});
|
||||
guid2PathDic = MemoryPackSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllBytes(guid2pathBinPath));
|
||||
}
|
||||
|
||||
var path2guidBinPath = Path.Combine(libraryPath, "path2guid.bin");
|
||||
if (File.Exists(path2guidBinPath))
|
||||
{
|
||||
path2GuidDic = MemoryPackSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllBytes(path2guidBinPath));
|
||||
}
|
||||
|
||||
stopwatch.Stop();
|
||||
Debug.Log($"Deserialize {stopwatch.ElapsedMilliseconds}");
|
||||
stopwatch.Restart();
|
||||
path2NodeIdDic = new();
|
||||
foreach (var node in assetId2NodeDic)
|
||||
{
|
||||
path2NodeIdDic[node.Key.Path] = node.Key;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
Debug.Log($"ResolveDependency {stopwatch.ElapsedMilliseconds}");
|
||||
}
|
||||
|
||||
void CreateGraph()
|
||||
@ -168,7 +218,7 @@ namespace AssetDependencyGraph
|
||||
toolbar.Add(options);
|
||||
toolbar.Add(new Button(ExploreAsset)
|
||||
{
|
||||
text = "Explore Asset",
|
||||
text = "展示选择对象引用关系",
|
||||
});
|
||||
toolbar.Add(new Button(ClearGraph)
|
||||
{
|
||||
@ -184,21 +234,21 @@ namespace AssetDependencyGraph
|
||||
});
|
||||
toolbar.Add(new Button(() =>
|
||||
{
|
||||
Task.Run(() =>
|
||||
System.Diagnostics.Stopwatch stopwatch = new();
|
||||
stopwatch.Restart();
|
||||
System.Diagnostics.Process.Start(startInfo: new()
|
||||
{
|
||||
System.Diagnostics.Process.Start(startInfo: new()
|
||||
{
|
||||
FileName = $"{Application.dataPath}/../Tools/UnityDependencyAnalyzer.exe",
|
||||
Arguments = $"{Application.dataPath.Replace("Assets", "")} \" \" \" \" localhost ",
|
||||
UseShellExecute = true,
|
||||
})
|
||||
.WaitForExit();
|
||||
|
||||
ResolveDependency();
|
||||
});
|
||||
FileName = $"{Application.dataPath}/../Tools/UnityDependencyAnalyzer.exe",
|
||||
Arguments = $"-reference {Application.dataPath.Replace("Assets", "")} \" \" \" \" localhost ",
|
||||
UseShellExecute = true,
|
||||
})
|
||||
.WaitForExit();
|
||||
stopwatch.Stop();
|
||||
Debug.Log($"resolve {stopwatch.ElapsedMilliseconds}");
|
||||
ResolveDependency();
|
||||
})
|
||||
{
|
||||
text = "Analyze Reference"
|
||||
text = "分析或更新引用"
|
||||
});
|
||||
|
||||
var ts = new ToolbarSearchField();
|
||||
@ -271,13 +321,32 @@ namespace AssetDependencyGraph
|
||||
return toolbar;
|
||||
}
|
||||
|
||||
private static string GetAnalyzedAssetPath(UnityEngine.Object obj)
|
||||
{
|
||||
return AssetDatabase.GetAssetPath(obj).Replace('\\', '/').ToLowerInvariant();
|
||||
}
|
||||
|
||||
private static void OnDeleteAsset(UnityEngine.Object asset)
|
||||
{
|
||||
var path = GetAnalyzedAssetPath(asset);
|
||||
var delAssetNode = FindAssetNode(path);
|
||||
foreach (var dependency in delAssetNode.DependencySet)
|
||||
{
|
||||
assetId2NodeDic[dependency].DependentSet.Remove(delAssetNode.Self);
|
||||
}
|
||||
|
||||
assetId2NodeDic.Remove(delAssetNode.Self);
|
||||
path2NodeIdDic.Remove(path);
|
||||
}
|
||||
|
||||
private void ExploreAsset()
|
||||
{
|
||||
Object[] objs = Selection.objects;
|
||||
if(path2NodeIdDic == null || path2NodeIdDic.Count == 0)
|
||||
if (path2NodeIdDic == null || path2NodeIdDic.Count == 0)
|
||||
{
|
||||
ResolveDependency();
|
||||
}
|
||||
|
||||
foreach (var obj in objs)
|
||||
{
|
||||
//Prevent readding same object
|
||||
@ -289,7 +358,7 @@ namespace AssetDependencyGraph
|
||||
selectedObjects.Add(obj);
|
||||
|
||||
AssetGroup AssetGroup = new AssetGroup();
|
||||
AssetGroup.AssetNode = FindAssetNode(AssetDatabase.GetAssetPath(obj).Replace('\\', '/').ToLowerInvariant());
|
||||
AssetGroup.AssetNode = FindAssetNode(GetAnalyzedAssetPath(obj));
|
||||
assetGroups.Add(AssetGroup);
|
||||
|
||||
// assetPath will be empty if obj is null or isn't an asset (a scene object)
|
||||
@ -400,11 +469,9 @@ namespace AssetDependencyGraph
|
||||
}
|
||||
|
||||
var fullPath = dependAssetId.Path;
|
||||
Debug.Log(fullPath);
|
||||
if (IsGuid(fullPath))
|
||||
{
|
||||
fullPath = AssetDatabase.GUIDToAssetPath(fullPath);
|
||||
Debug.Log(fullPath);
|
||||
fullPath = GUIDToPath(fullPath);
|
||||
}
|
||||
var obj = AssetDatabase.LoadMainAssetAtPath(fullPath);
|
||||
if(obj == null)
|
||||
@ -493,11 +560,9 @@ namespace AssetDependencyGraph
|
||||
continue;
|
||||
}
|
||||
var fullPath = dependAssetId.Path;
|
||||
Debug.Log(fullPath);
|
||||
if (IsGuid(fullPath))
|
||||
{
|
||||
fullPath = AssetDatabase.GUIDToAssetPath(fullPath);
|
||||
Debug.Log(fullPath);
|
||||
fullPath = GUIDToPath(fullPath);
|
||||
}
|
||||
var obj = AssetDatabase.LoadMainAssetAtPath(fullPath);
|
||||
if (obj == null)
|
||||
@ -606,9 +671,9 @@ namespace AssetDependencyGraph
|
||||
{
|
||||
title = obj.name,
|
||||
style =
|
||||
{
|
||||
width = NodeWidth
|
||||
}
|
||||
{
|
||||
width = NodeWidth
|
||||
}
|
||||
};
|
||||
|
||||
objNode.extensionContainer.style.backgroundColor = new Color(0.24f, 0.24f, 0.24f, 0.8f);
|
||||
@ -648,6 +713,7 @@ namespace AssetDependencyGraph
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("提示", "当前 asset 没有引用,是否直接删除", "确认删除", "取消"))
|
||||
{
|
||||
OnDeleteAsset(obj);
|
||||
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(obj));
|
||||
}
|
||||
}
|
||||
@ -708,15 +774,23 @@ namespace AssetDependencyGraph
|
||||
{
|
||||
style =
|
||||
{
|
||||
paddingBottom = 4.0f,
|
||||
paddingTop = 4.0f,
|
||||
paddingLeft = 4.0f,
|
||||
paddingRight = 4.0f,
|
||||
backgroundColor = GetColorByAssetType(typeName)
|
||||
}
|
||||
paddingBottom = 4.0f,
|
||||
paddingTop = 4.0f,
|
||||
paddingLeft = 4.0f,
|
||||
paddingRight = 4.0f,
|
||||
backgroundColor = GetColorByAssetType(typeName)
|
||||
}
|
||||
};
|
||||
|
||||
objNode.extensionContainer.Add(typeContainer);
|
||||
objNode.RegisterCallback<FocusInEvent>(e =>
|
||||
{
|
||||
});
|
||||
|
||||
objNode.RegisterCallback<FocusOutEvent>(e =>
|
||||
{
|
||||
|
||||
});
|
||||
|
||||
#region Node Icon, replaced with color
|
||||
//Texture assetTexture = AssetPreview.GetAssetPreview(obj);
|
||||
@ -755,19 +829,19 @@ namespace AssetDependencyGraph
|
||||
{
|
||||
Port port = objNode.InstantiatePort(Orientation.Horizontal, Direction.Input, Port.Capacity.Single, typeof(Object));
|
||||
port.Add(new Button(() =>
|
||||
{
|
||||
CreateDependentNodes(assetGroup, assetNode, fullPathNodeLookup[fullPath], assetGroup.GroupNode, (int)fullPathNodeLookup[fullPath].userData - 1);
|
||||
EditorApplication.delayCall += () => ResetAllNodes();
|
||||
})
|
||||
{
|
||||
style =
|
||||
{
|
||||
height = 16.0f,
|
||||
alignSelf = Align.Center,
|
||||
alignItems = Align.Center
|
||||
},
|
||||
text = "展开"
|
||||
});
|
||||
{
|
||||
CreateDependentNodes(assetGroup, assetNode, fullPathNodeLookup[fullPath], assetGroup.GroupNode, (int)fullPathNodeLookup[fullPath].userData - 1);
|
||||
EditorApplication.delayCall += () => ResetAllNodes();
|
||||
})
|
||||
{
|
||||
style =
|
||||
{
|
||||
height = 16.0f,
|
||||
alignSelf = Align.Center,
|
||||
alignItems = Align.Center
|
||||
},
|
||||
text = "展开"
|
||||
});
|
||||
port.portName = dependentAmount + "个引用";
|
||||
objNode.inputContainer.Add(port);
|
||||
}
|
||||
@ -777,20 +851,19 @@ namespace AssetDependencyGraph
|
||||
{
|
||||
Port port = objNode.InstantiatePort(Orientation.Horizontal, Direction.Output, Port.Capacity.Single, typeof(Object));
|
||||
port.Add(new Button(() =>
|
||||
{
|
||||
CreateDependencyNodes(assetGroup, assetNode, fullPathNodeLookup[fullPath], assetGroup.GroupNode, (int)fullPathNodeLookup[fullPath].userData + 1);
|
||||
EditorApplication.delayCall += () => ResetAllNodes();
|
||||
|
||||
})
|
||||
{
|
||||
style =
|
||||
{
|
||||
height = 16.0f,
|
||||
alignSelf = Align.Center,
|
||||
alignItems = Align.FlexEnd
|
||||
},
|
||||
text = "展开"
|
||||
});
|
||||
{
|
||||
CreateDependencyNodes(assetGroup, assetNode, fullPathNodeLookup[fullPath], assetGroup.GroupNode, (int)fullPathNodeLookup[fullPath].userData + 1);
|
||||
EditorApplication.delayCall += () => ResetAllNodes();
|
||||
})
|
||||
{
|
||||
style =
|
||||
{
|
||||
height = 16.0f,
|
||||
alignSelf = Align.Center,
|
||||
alignItems = Align.FlexEnd
|
||||
},
|
||||
text = "展开"
|
||||
});
|
||||
port.portName = dependencyAmount + "个依赖";
|
||||
objNode.outputContainer.Add(port);
|
||||
objNode.RefreshPorts();
|
||||
11
AssetDependencyGraph/Editor/AssetDependencyGraph.cs.meta
Normal file
11
AssetDependencyGraph/Editor/AssetDependencyGraph.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43eecbcf2afaca84aa2af29388e193de
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
AssetDependencyGraph/Plugins.meta
Normal file
8
AssetDependencyGraph/Plugins.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9acdcfd297aa7ad4a91bbfde679a3688
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
AssetDependencyGraph/Plugins/MemoryPack.Core.meta
Normal file
8
AssetDependencyGraph/Plugins/MemoryPack.Core.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 590b08b0771f0bd47beca317303e050f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
166
AssetDependencyGraph/Plugins/MemoryPack.Core/Attributes.cs
Normal file
166
AssetDependencyGraph/Plugins/MemoryPack.Core/Attributes.cs
Normal file
@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
namespace MemoryPack {
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class MemoryPackableAttribute : Attribute
|
||||
{
|
||||
public GenerateType GenerateType { get; }
|
||||
public SerializeLayout SerializeLayout { get; }
|
||||
|
||||
// ctor parameter is parsed in MemoryPackGenerator.Parser TypeMeta for detect which ctor used in MemoryPack.Generator.
|
||||
// if modify ctor, be careful.
|
||||
|
||||
/// <summary>
|
||||
/// [generateType, (VersionTolerant or CircularReference) ? SerializeLayout.Explicit : SerializeLayout.Sequential]
|
||||
/// </summary>
|
||||
/// <param name="generateType"></param>
|
||||
public MemoryPackableAttribute(GenerateType generateType = GenerateType.Object)
|
||||
{
|
||||
this.GenerateType = generateType;
|
||||
this.SerializeLayout = (generateType == GenerateType.VersionTolerant || generateType == GenerateType.CircularReference)
|
||||
? SerializeLayout.Explicit
|
||||
: SerializeLayout.Sequential;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [GenerateType.Object, serializeLayout]
|
||||
/// </summary>
|
||||
public MemoryPackableAttribute(SerializeLayout serializeLayout)
|
||||
{
|
||||
this.GenerateType = GenerateType.Object;
|
||||
this.SerializeLayout = serializeLayout;
|
||||
}
|
||||
|
||||
public MemoryPackableAttribute(GenerateType generateType, SerializeLayout serializeLayout)
|
||||
{
|
||||
this.GenerateType = generateType;
|
||||
this.SerializeLayout = serializeLayout;
|
||||
}
|
||||
}
|
||||
|
||||
public enum GenerateType
|
||||
{
|
||||
Object,
|
||||
VersionTolerant,
|
||||
CircularReference,
|
||||
Collection,
|
||||
NoGenerate
|
||||
}
|
||||
|
||||
public enum SerializeLayout
|
||||
{
|
||||
Sequential, // default
|
||||
Explicit
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = false)]
|
||||
public sealed class MemoryPackUnionAttribute : Attribute
|
||||
{
|
||||
public ushort Tag { get; }
|
||||
public Type Type { get; }
|
||||
|
||||
public MemoryPackUnionAttribute(ushort tag, Type type)
|
||||
{
|
||||
this.Tag = tag;
|
||||
this.Type = type;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class MemoryPackUnionFormatterAttribute : Attribute
|
||||
{
|
||||
public Type Type { get; }
|
||||
|
||||
public MemoryPackUnionFormatterAttribute(Type type)
|
||||
{
|
||||
this.Type = type;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class MemoryPackAllowSerializeAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class MemoryPackOrderAttribute : Attribute
|
||||
{
|
||||
public int Order { get; }
|
||||
|
||||
public MemoryPackOrderAttribute(int order)
|
||||
{
|
||||
this.Order = order;
|
||||
}
|
||||
}
|
||||
|
||||
#if !UNITY_2021_2_OR_NEWER
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
|
||||
public abstract class MemoryPackCustomFormatterAttribute<T> : Attribute
|
||||
{
|
||||
public abstract IMemoryPackFormatter<T> GetFormatter();
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
|
||||
public abstract class MemoryPackCustomFormatterAttribute<TFormatter, T> : Attribute
|
||||
where TFormatter : IMemoryPackFormatter<T>
|
||||
{
|
||||
public abstract TFormatter GetFormatter();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// similar naming as System.Text.Json attribtues
|
||||
// https://docs.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonattribute
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class MemoryPackIgnoreAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class MemoryPackIncludeAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class MemoryPackConstructorAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class MemoryPackOnSerializingAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class MemoryPackOnSerializedAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class MemoryPackOnDeserializingAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class MemoryPackOnDeserializedAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
// Others
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class GenerateTypeScriptAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e370fb1f0283f164ba65d0874cbef7f0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a28c9e101e0f564c9ab6b19218741bc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,181 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
#endif
|
||||
|
||||
namespace MemoryPack.Compression {
|
||||
|
||||
[Preserve]
|
||||
public sealed class BitPackFormatter : MemoryPackFormatter<bool[]>
|
||||
{
|
||||
public static readonly BitPackFormatter Default = new BitPackFormatter();
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref bool[]? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullCollectionHeader();
|
||||
return;
|
||||
}
|
||||
writer.WriteCollectionHeader(value.Length);
|
||||
if (value.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var data = 0;
|
||||
#if NET7_0_OR_GREATER
|
||||
ref var item = ref MemoryMarshal.GetArrayDataReference(value);
|
||||
#else
|
||||
ref var item = ref value[0];
|
||||
#endif
|
||||
ref var end = ref Unsafe.Add(ref item, value.Length);
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
if (value.Length >= 32)
|
||||
{
|
||||
ref var loopEnd = ref Unsafe.Subtract(ref end, 32);
|
||||
if (Vector256.IsHardwareAccelerated)
|
||||
{
|
||||
while (!Unsafe.IsAddressGreaterThan(ref item, ref loopEnd))
|
||||
{
|
||||
var vector = Vector256.LoadUnsafe(ref Unsafe.As<bool, byte>(ref item));
|
||||
// false -> 1 true -> 0
|
||||
data = (int)Vector256.Equals(vector, Vector256<byte>.Zero).ExtractMostSignificantBits();
|
||||
writer.WriteUnmanaged(~data);
|
||||
item = ref Unsafe.Add(ref item, 32);
|
||||
}
|
||||
}
|
||||
else if (Vector128.IsHardwareAccelerated)
|
||||
{
|
||||
while (!Unsafe.IsAddressGreaterThan(ref item, ref loopEnd))
|
||||
{
|
||||
var bits0 = (ushort)Vector128.Equals(Vector128.LoadUnsafe(ref Unsafe.As<bool, byte>(ref item)), Vector128<byte>.Zero).ExtractMostSignificantBits();
|
||||
var bits1 = (ushort)Vector128.Equals(Vector128.LoadUnsafe(ref Unsafe.As<bool, byte>(ref item), 16), Vector128<byte>.Zero).ExtractMostSignificantBits();
|
||||
data = bits0 | (bits1 << 16);
|
||||
writer.WriteUnmanaged(~data);
|
||||
item = ref Unsafe.Add(ref item, 32);
|
||||
}
|
||||
}
|
||||
else if (Vector64.IsHardwareAccelerated)
|
||||
{
|
||||
while (!Unsafe.IsAddressGreaterThan(ref item, ref loopEnd))
|
||||
{
|
||||
var bits0 = (byte)Vector64.Equals(Vector64.LoadUnsafe(ref Unsafe.As<bool, byte>(ref item)), Vector64<byte>.Zero).ExtractMostSignificantBits();
|
||||
var bits1 = (byte)Vector64.Equals(Vector64.LoadUnsafe(ref Unsafe.As<bool, byte>(ref item), 8), Vector64<byte>.Zero).ExtractMostSignificantBits();
|
||||
var bits2 = (byte)Vector64.Equals(Vector64.LoadUnsafe(ref Unsafe.As<bool, byte>(ref item), 16), Vector64<byte>.Zero).ExtractMostSignificantBits();
|
||||
var bits3 = (byte)Vector64.Equals(Vector64.LoadUnsafe(ref Unsafe.As<bool, byte>(ref item), 24), Vector64<byte>.Zero).ExtractMostSignificantBits();
|
||||
data = bits0 | (bits1 << 8) | (bits2 << 16) | (bits3 << 24);
|
||||
writer.WriteUnmanaged(~data);
|
||||
item = ref Unsafe.Add(ref item, 32);
|
||||
}
|
||||
}
|
||||
|
||||
data = 0;
|
||||
}
|
||||
#endif
|
||||
var bit = 0;
|
||||
while (Unsafe.IsAddressLessThan(ref item, ref end))
|
||||
{
|
||||
Set(ref data, bit, item);
|
||||
|
||||
item = ref Unsafe.Add(ref item, 1);
|
||||
bit += 1;
|
||||
|
||||
if (bit == 32)
|
||||
{
|
||||
writer.WriteUnmanaged(data);
|
||||
data = 0;
|
||||
bit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (bit != 0)
|
||||
{
|
||||
writer.WriteUnmanaged(data);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref bool[]? value)
|
||||
{
|
||||
if (!reader.DangerousTryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
value = Array.Empty<bool>();
|
||||
return;
|
||||
}
|
||||
|
||||
var readCount = ((length - 1) / 32) + 1;
|
||||
var requireSize = readCount * 4;
|
||||
if (reader.Remaining < requireSize)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowInsufficientBufferUnless(length);
|
||||
}
|
||||
|
||||
if (value == null || value.Length != length)
|
||||
{
|
||||
value = new bool[length];
|
||||
}
|
||||
|
||||
var bit = 0;
|
||||
var data = 0;
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
if (bit == 0)
|
||||
{
|
||||
reader.ReadUnmanaged(out data);
|
||||
}
|
||||
|
||||
value[i] = Get(data, bit);
|
||||
|
||||
bit += 1;
|
||||
|
||||
if (bit == 32)
|
||||
{
|
||||
data = 0;
|
||||
bit = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Get(int data, int index)
|
||||
{
|
||||
return (data & (1 << index)) != 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Set(ref int data, int index, bool value)
|
||||
{
|
||||
int bitMask = 1 << index;
|
||||
if (value)
|
||||
{
|
||||
data |= bitMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
data &= ~bitMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61f1625193facbe4abecb4f90defa276
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,338 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Buffers;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MemoryPack.Compression {
|
||||
|
||||
#if !NET7_0_OR_GREATER
|
||||
#pragma warning disable CS8602
|
||||
#endif
|
||||
|
||||
public
|
||||
#if NET7_0_OR_GREATER
|
||||
struct
|
||||
#else
|
||||
class
|
||||
#endif
|
||||
BrotliCompressor : IBufferWriter<byte>, IDisposable
|
||||
{
|
||||
ReusableLinkedArrayBufferWriter? bufferWriter;
|
||||
readonly int quality;
|
||||
readonly int window;
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
public BrotliCompressor()
|
||||
: this(CompressionLevel.Fastest)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public BrotliCompressor(CompressionLevel compressionLevel)
|
||||
: this(BrotliUtils.GetQualityFromCompressionLevel(compressionLevel), BrotliUtils.WindowBits_Default)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BrotliCompressor(CompressionLevel compressionLevel, int window)
|
||||
: this(BrotliUtils.GetQualityFromCompressionLevel(compressionLevel), window)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BrotliCompressor(int quality = 1, int window = 22)
|
||||
{
|
||||
this.bufferWriter = ReusableLinkedArrayBufferWriterPool.Rent();
|
||||
this.quality = quality;
|
||||
this.window = window;
|
||||
}
|
||||
|
||||
void IBufferWriter<byte>.Advance(int count)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
bufferWriter.Advance(count);
|
||||
}
|
||||
|
||||
Memory<byte> IBufferWriter<byte>.GetMemory(int sizeHint)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
return bufferWriter.GetMemory(sizeHint);
|
||||
}
|
||||
|
||||
Span<byte> IBufferWriter<byte>.GetSpan(int sizeHint)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
return bufferWriter.GetSpan(sizeHint);
|
||||
}
|
||||
|
||||
public byte[] ToArray()
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
using var encoder = new BrotliEncoder(quality, window);
|
||||
|
||||
var maxLength = BrotliUtils.BrotliEncoderMaxCompressedSize(bufferWriter.TotalWritten);
|
||||
|
||||
var finalBuffer = ArrayPool<byte>.Shared.Rent(maxLength);
|
||||
try
|
||||
{
|
||||
var writtenCount = 0;
|
||||
var destination = finalBuffer.AsSpan(0, maxLength);
|
||||
foreach (var source in bufferWriter)
|
||||
{
|
||||
var status = encoder.Compress(source.Span, destination, out var bytesConsumed, out var bytesWritten, isFinalBlock: false);
|
||||
if (status != OperationStatus.Done)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowCompressionFailed(status);
|
||||
}
|
||||
|
||||
if (bytesConsumed != source.Span.Length)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowCompressionFailed();
|
||||
}
|
||||
|
||||
if (bytesWritten > 0)
|
||||
{
|
||||
destination = destination.Slice(bytesWritten);
|
||||
writtenCount += bytesWritten;
|
||||
}
|
||||
}
|
||||
|
||||
// call BrotliEncoderOperation.Finish
|
||||
var finalStatus = encoder.Compress(ReadOnlySpan<byte>.Empty, destination, out var consumed, out var written, isFinalBlock: true);
|
||||
writtenCount += written;
|
||||
|
||||
return finalBuffer.AsSpan(0, writtenCount).ToArray();
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(finalBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyTo(in IBufferWriter<byte> destBufferWriter)
|
||||
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
var encoder = new BrotliEncoder(quality, window);
|
||||
try
|
||||
{
|
||||
var writtenNotAdvanced = 0;
|
||||
foreach (var item in bufferWriter)
|
||||
{
|
||||
writtenNotAdvanced = CompressCore(ref encoder, item.Span, ref Unsafe.AsRef(destBufferWriter), initialLength: null, isFinalBlock: false);
|
||||
}
|
||||
|
||||
// call BrotliEncoderOperation.Finish
|
||||
var finalBlockLength = (writtenNotAdvanced == 0) ? null : (int?)(writtenNotAdvanced + 10);
|
||||
CompressCore(ref encoder, ReadOnlySpan<byte>.Empty, ref Unsafe.AsRef(destBufferWriter), initialLength: finalBlockLength, isFinalBlock: true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
encoder.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask CopyToAsync(Stream stream, int bufferSize = 65535, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
using var encoder = new BrotliEncoder(quality, window);
|
||||
|
||||
var buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
|
||||
try
|
||||
{
|
||||
foreach (var item in bufferWriter)
|
||||
{
|
||||
var source = item;
|
||||
var lastResult = OperationStatus.DestinationTooSmall;
|
||||
while (lastResult == OperationStatus.DestinationTooSmall)
|
||||
{
|
||||
lastResult = encoder.Compress(source.Span, buffer, out int bytesConsumed, out int bytesWritten, isFinalBlock: false);
|
||||
if (lastResult == OperationStatus.InvalidData) MemoryPackSerializationException.ThrowCompressionFailed();
|
||||
if (bytesWritten > 0)
|
||||
{
|
||||
await stream.WriteAsync(buffer.AsMemory(0, bytesWritten), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
if (bytesConsumed > 0)
|
||||
{
|
||||
source = source.Slice(bytesConsumed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// call BrotliEncoderOperation.Finish
|
||||
var finalStatus = encoder.Compress(ReadOnlySpan<byte>.Empty, buffer, out var consumed, out var written, isFinalBlock: true);
|
||||
if (written > 0)
|
||||
{
|
||||
await stream.WriteAsync(buffer.AsMemory(0, written), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyTo(ref MemoryPackWriter memoryPackWriter)
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
var encoder = new BrotliEncoder(quality, window);
|
||||
try
|
||||
{
|
||||
var writtenNotAdvanced = 0;
|
||||
foreach (var item in bufferWriter)
|
||||
{
|
||||
writtenNotAdvanced = CompressCore(ref encoder, item.Span, ref memoryPackWriter, initialLength: null, isFinalBlock: false);
|
||||
}
|
||||
|
||||
// call BrotliEncoderOperation.Finish
|
||||
var finalBlockLength = (writtenNotAdvanced == 0) ? null : (int?)(writtenNotAdvanced + 10);
|
||||
CompressCore(ref encoder, ReadOnlySpan<byte>.Empty, ref memoryPackWriter, initialLength: finalBlockLength, isFinalBlock: true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
encoder.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
static int CompressCore(ref BrotliEncoder encoder, ReadOnlySpan<byte> source, ref IBufferWriter<byte> destBufferWriter, int? initialLength, bool isFinalBlock)
|
||||
|
||||
{
|
||||
var writtenNotAdvanced = 0;
|
||||
|
||||
var lastResult = OperationStatus.DestinationTooSmall;
|
||||
while (lastResult == OperationStatus.DestinationTooSmall)
|
||||
{
|
||||
var dest = destBufferWriter.GetSpan(initialLength ?? source.Length);
|
||||
|
||||
lastResult = encoder.Compress(source, dest, out int bytesConsumed, out int bytesWritten, isFinalBlock: isFinalBlock);
|
||||
writtenNotAdvanced += bytesConsumed;
|
||||
|
||||
if (lastResult == OperationStatus.InvalidData) MemoryPackSerializationException.ThrowCompressionFailed();
|
||||
if (bytesWritten > 0)
|
||||
{
|
||||
destBufferWriter.Advance(bytesWritten);
|
||||
writtenNotAdvanced = 0;
|
||||
}
|
||||
if (bytesConsumed > 0)
|
||||
{
|
||||
source = source.Slice(bytesConsumed);
|
||||
}
|
||||
}
|
||||
|
||||
return writtenNotAdvanced;
|
||||
}
|
||||
|
||||
static int CompressCore(ref BrotliEncoder encoder, ReadOnlySpan<byte> source, ref MemoryPackWriter destBufferWriter, int? initialLength, bool isFinalBlock)
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
{
|
||||
var writtenNotAdvanced = 0;
|
||||
|
||||
var lastResult = OperationStatus.DestinationTooSmall;
|
||||
while (lastResult == OperationStatus.DestinationTooSmall)
|
||||
{
|
||||
ref var spanRef = ref destBufferWriter.GetSpanReference(initialLength ?? source.Length);
|
||||
var dest = MemoryMarshal.CreateSpan(ref spanRef, destBufferWriter.BufferLength);
|
||||
|
||||
lastResult = encoder.Compress(source, dest, out int bytesConsumed, out int bytesWritten, isFinalBlock: isFinalBlock);
|
||||
writtenNotAdvanced += bytesConsumed;
|
||||
|
||||
if (lastResult == OperationStatus.InvalidData) MemoryPackSerializationException.ThrowCompressionFailed();
|
||||
if (bytesWritten > 0)
|
||||
{
|
||||
destBufferWriter.Advance(bytesWritten);
|
||||
writtenNotAdvanced = 0;
|
||||
}
|
||||
if (bytesConsumed > 0)
|
||||
{
|
||||
source = source.Slice(bytesConsumed);
|
||||
}
|
||||
}
|
||||
|
||||
return writtenNotAdvanced;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (bufferWriter == null) return;
|
||||
|
||||
bufferWriter.Reset();
|
||||
ReusableLinkedArrayBufferWriterPool.Return(bufferWriter);
|
||||
bufferWriter = null!;
|
||||
}
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
[MemberNotNull(nameof(bufferWriter))]
|
||||
#endif
|
||||
void ThrowIfDisposed()
|
||||
{
|
||||
if (bufferWriter == null)
|
||||
{
|
||||
throw new ObjectDisposedException(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static partial class BrotliUtils
|
||||
{
|
||||
public const int WindowBits_Min = 10;
|
||||
public const int WindowBits_Default = 22;
|
||||
public const int WindowBits_Max = 24;
|
||||
public const int Quality_Min = 0;
|
||||
public const int Quality_Default = 4;
|
||||
public const int Quality_Max = 11;
|
||||
public const int MaxInputSize = int.MaxValue - 515; // 515 is the max compressed extra bytes
|
||||
|
||||
internal static int GetQualityFromCompressionLevel(CompressionLevel compressionLevel) =>
|
||||
compressionLevel switch
|
||||
{
|
||||
CompressionLevel.NoCompression => Quality_Min,
|
||||
CompressionLevel.Fastest => 1,
|
||||
CompressionLevel.Optimal => Quality_Default,
|
||||
#if NET7_0_OR_GREATER
|
||||
CompressionLevel.SmallestSize => Quality_Max,
|
||||
#endif
|
||||
_ => throw new ArgumentException()
|
||||
};
|
||||
|
||||
|
||||
// https://github.com/dotnet/runtime/issues/35142
|
||||
// BrotliEncoder.GetMaxCompressedLength is broken in .NET 7
|
||||
// port from encode.c https://github.com/google/brotli/blob/3914999fcc1fda92e750ef9190aa6db9bf7bdb07/c/enc/encode.c#L1200
|
||||
internal static int BrotliEncoderMaxCompressedSize(int input_size)
|
||||
{
|
||||
var num_large_blocks = input_size >> 14;
|
||||
var overhead = 2 + (4 * num_large_blocks) + 3 + 1;
|
||||
var result = input_size + overhead;
|
||||
if (input_size == 0) return 2;
|
||||
return (result < input_size) ? 0 : result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62473f8441644d1479405f2eb8f863c9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,162 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace MemoryPack.Compression {
|
||||
|
||||
public struct BrotliDecompressor : IDisposable
|
||||
{
|
||||
ReusableReadOnlySequenceBuilder? sequenceBuilder;
|
||||
|
||||
public ReadOnlySequence<byte> Decompress(ReadOnlySpan<byte> compressedSpan)
|
||||
{
|
||||
return Decompress(compressedSpan, out _);
|
||||
}
|
||||
|
||||
public ReadOnlySequence<byte> Decompress(ReadOnlySpan<byte> compressedSpan, out int consumed)
|
||||
{
|
||||
if (sequenceBuilder != null)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowAlreadyDecompressed();
|
||||
}
|
||||
|
||||
sequenceBuilder = ReusableReadOnlySequenceBuilderPool.Rent();
|
||||
var decoder = new BrotliDecoder();
|
||||
try
|
||||
{
|
||||
var status = OperationStatus.DestinationTooSmall;
|
||||
DecompressCore(ref status, ref decoder, compressedSpan, out consumed);
|
||||
if (status == OperationStatus.NeedMoreData)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowCompressionFailed(status);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
decoder.Dispose();
|
||||
}
|
||||
|
||||
return sequenceBuilder.Build();
|
||||
}
|
||||
|
||||
public ReadOnlySequence<byte> Decompress(ReadOnlySequence<byte> compressedSequence)
|
||||
{
|
||||
return Decompress(compressedSequence, out _);
|
||||
}
|
||||
|
||||
public ReadOnlySequence<byte> Decompress(ReadOnlySequence<byte> compressedSequence, out int consumed)
|
||||
{
|
||||
if (sequenceBuilder != null)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowAlreadyDecompressed();
|
||||
}
|
||||
|
||||
sequenceBuilder = ReusableReadOnlySequenceBuilderPool.Rent();
|
||||
var decoder = new BrotliDecoder();
|
||||
try
|
||||
{
|
||||
var status = OperationStatus.DestinationTooSmall;
|
||||
consumed = 0;
|
||||
foreach (var item in compressedSequence)
|
||||
{
|
||||
DecompressCore(ref status, ref decoder, item.Span, out var bytesConsumed);
|
||||
consumed += bytesConsumed;
|
||||
}
|
||||
|
||||
if (status == OperationStatus.NeedMoreData)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowCompressionFailed(status);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
decoder.Dispose();
|
||||
}
|
||||
|
||||
return sequenceBuilder.Build();
|
||||
}
|
||||
|
||||
void DecompressCore(ref OperationStatus status, ref BrotliDecoder decoder, ReadOnlySpan<byte> source, out int consumed)
|
||||
{
|
||||
Debug.Assert(sequenceBuilder != null);
|
||||
consumed = 0;
|
||||
|
||||
byte[]? buffer = null;
|
||||
status = OperationStatus.DestinationTooSmall;
|
||||
var nextCapacity = source.Length;
|
||||
while (status == OperationStatus.DestinationTooSmall)
|
||||
{
|
||||
if (buffer == null)
|
||||
{
|
||||
nextCapacity = GetDoubleCapacity(nextCapacity);
|
||||
buffer = ArrayPool<byte>.Shared.Rent(nextCapacity);
|
||||
}
|
||||
|
||||
status = decoder.Decompress(source, buffer, out var bytesConsumed, out var bytesWritten);
|
||||
consumed += bytesConsumed;
|
||||
|
||||
if (status == OperationStatus.InvalidData)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowCompressionFailed(status);
|
||||
}
|
||||
|
||||
if (status == OperationStatus.NeedMoreData)
|
||||
{
|
||||
if (bytesWritten > 0)
|
||||
{
|
||||
sequenceBuilder.Add(buffer.AsMemory(0, bytesWritten), true);
|
||||
}
|
||||
if (bytesConsumed > 0)
|
||||
{
|
||||
source = source.Slice(bytesConsumed);
|
||||
}
|
||||
if (source.Length != 0)
|
||||
{
|
||||
// not consumed source fully
|
||||
MemoryPackSerializationException.ThrowCompressionFailed();
|
||||
}
|
||||
|
||||
// continue for next sequence.
|
||||
return;
|
||||
}
|
||||
|
||||
if (bytesConsumed > 0)
|
||||
{
|
||||
source = source.Slice(bytesConsumed);
|
||||
}
|
||||
if (bytesWritten > 0)
|
||||
{
|
||||
sequenceBuilder.Add(buffer.AsMemory(0, bytesWritten), true);
|
||||
buffer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (sequenceBuilder != null)
|
||||
{
|
||||
ReusableReadOnlySequenceBuilderPool.Return(sequenceBuilder);
|
||||
sequenceBuilder = null;
|
||||
}
|
||||
}
|
||||
|
||||
int GetDoubleCapacity(int length)
|
||||
{
|
||||
var newCapacity = unchecked(length * 2);
|
||||
if ((uint)newCapacity > int.MaxValue) newCapacity = int.MaxValue;
|
||||
return Math.Max(newCapacity, 4096);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe3786d11daa23f4488fa639754af3a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,213 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Buffers;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MemoryPack.Compression {
|
||||
|
||||
// serialize as (uncompressedLength, compressedLength, values...)
|
||||
|
||||
[Preserve]
|
||||
public sealed class BrotliFormatter : MemoryPackFormatter<byte[]>
|
||||
{
|
||||
internal const int DefaultDecompssionSizeLimit = 1024 * 1024 * 128; // 128MB
|
||||
|
||||
public static readonly BrotliFormatter Default = new BrotliFormatter();
|
||||
|
||||
readonly System.IO.Compression.CompressionLevel compressionLevel;
|
||||
readonly int window;
|
||||
readonly int decompressionSizeLimit;
|
||||
|
||||
public BrotliFormatter()
|
||||
: this(System.IO.Compression.CompressionLevel.Fastest)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BrotliFormatter(System.IO.Compression.CompressionLevel compressionLevel)
|
||||
: this(compressionLevel, BrotliUtils.WindowBits_Default)
|
||||
{
|
||||
}
|
||||
|
||||
public BrotliFormatter(System.IO.Compression.CompressionLevel compressionLevel, int window)
|
||||
: this(compressionLevel, window, DefaultDecompssionSizeLimit)
|
||||
{
|
||||
}
|
||||
|
||||
public BrotliFormatter(System.IO.Compression.CompressionLevel compressionLevel, int window, int decompressionSizeLimit)
|
||||
{
|
||||
this.compressionLevel = compressionLevel;
|
||||
this.window = window;
|
||||
this.decompressionSizeLimit = decompressionSizeLimit;
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref byte[]? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullCollectionHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.Length == 0)
|
||||
{
|
||||
writer.WriteCollectionHeader(0);
|
||||
return;
|
||||
}
|
||||
|
||||
var quality = BrotliUtils.GetQualityFromCompressionLevel(compressionLevel);
|
||||
|
||||
using var encoder = new BrotliEncoder(quality, window);
|
||||
|
||||
var maxLength = BrotliUtils.BrotliEncoderMaxCompressedSize(value.Length);
|
||||
|
||||
ref var head = ref writer.GetSpanReference(maxLength + 8);
|
||||
|
||||
var dest = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref head, 8), maxLength);
|
||||
var status = encoder.Compress(value.AsSpan(), dest, out var bytesConsumed, out var bytesWritten, isFinalBlock: true);
|
||||
if (status != OperationStatus.Done)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowCompressionFailed(status);
|
||||
}
|
||||
|
||||
if (bytesConsumed != value.Length)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowCompressionFailed();
|
||||
}
|
||||
|
||||
// write to buffer header (uncompressedLength, compressedLength, values...)
|
||||
Unsafe.WriteUnaligned(ref head, value.Length);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.Add(ref head, 4), bytesWritten);
|
||||
|
||||
writer.Advance(bytesWritten + 8);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref byte[]? value)
|
||||
{
|
||||
var uncompressedLength = reader.ReadUnmanaged<int>();
|
||||
|
||||
reader.DangerousReadUnmanagedSpanView<byte>(out var isNull, out var compressedBuffer);
|
||||
|
||||
if (isNull)
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (compressedBuffer.Length == 0)
|
||||
{
|
||||
value = Array.Empty<byte>();
|
||||
return;
|
||||
}
|
||||
|
||||
// security, require to check length
|
||||
if (decompressionSizeLimit < uncompressedLength)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowDecompressionSizeLimitExceeded(decompressionSizeLimit, uncompressedLength);
|
||||
}
|
||||
|
||||
if (value == null || value.Length != uncompressedLength)
|
||||
{
|
||||
value = new byte[uncompressedLength];
|
||||
}
|
||||
|
||||
using var decoder = new BrotliDecoder();
|
||||
|
||||
var status = decoder.Decompress(compressedBuffer, value, out var bytesConsumed, out var bytesWritten);
|
||||
if (status != OperationStatus.Done)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowCompressionFailed(status);
|
||||
}
|
||||
|
||||
if (bytesConsumed != compressedBuffer.Length || bytesWritten != value.Length)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowCompressionFailed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Preserve]
|
||||
public sealed class BrotliFormatter<T> : MemoryPackFormatter<T>
|
||||
{
|
||||
internal const int DefaultDecompssionSizeLimit = 1024 * 1024 * 128; // 128MB
|
||||
|
||||
public static readonly BrotliFormatter Default = new BrotliFormatter();
|
||||
|
||||
readonly System.IO.Compression.CompressionLevel compressionLevel;
|
||||
readonly int window;
|
||||
|
||||
public BrotliFormatter()
|
||||
: this(System.IO.Compression.CompressionLevel.Fastest)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BrotliFormatter(System.IO.Compression.CompressionLevel compressionLevel)
|
||||
: this(compressionLevel, BrotliUtils.WindowBits_Default)
|
||||
{
|
||||
}
|
||||
|
||||
public BrotliFormatter(System.IO.Compression.CompressionLevel compressionLevel, int window)
|
||||
{
|
||||
this.compressionLevel = compressionLevel;
|
||||
this.window = window;
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref T? value)
|
||||
{
|
||||
var compressor = new BrotliCompressor(compressionLevel, window);
|
||||
try
|
||||
{
|
||||
var coWriter = new MemoryPackWriter(ref Unsafe.As<BrotliCompressor, IBufferWriter<byte>>(ref compressor), writer.OptionalState);
|
||||
|
||||
coWriter.WriteValue(value);
|
||||
coWriter.Flush();
|
||||
|
||||
compressor.CopyTo(ref writer);
|
||||
}
|
||||
finally
|
||||
{
|
||||
compressor.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref T? value)
|
||||
{
|
||||
using var decompressor = new BrotliDecompressor();
|
||||
|
||||
reader.GetRemainingSource(out var singleSource, out var remainingSource);
|
||||
|
||||
int consumed;
|
||||
ReadOnlySequence<byte> decompressedSource;
|
||||
if (singleSource.Length != 0)
|
||||
{
|
||||
decompressedSource = decompressor.Decompress(singleSource, out consumed);
|
||||
}
|
||||
else
|
||||
{
|
||||
decompressedSource = decompressor.Decompress(remainingSource, out consumed);
|
||||
}
|
||||
|
||||
using var coReader = new MemoryPackReader(decompressedSource, reader.OptionalState);
|
||||
coReader.ReadValue(ref value);
|
||||
|
||||
reader.Advance(consumed);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45b39997d100c0848bcdb691400b2c1f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Compression;
|
||||
using MemoryPack.Formatters;
|
||||
|
||||
namespace MemoryPack {
|
||||
|
||||
#if !UNITY_2021_2_OR_NEWER
|
||||
|
||||
public sealed class Utf8StringFormatterAttribute : MemoryPackCustomFormatterAttribute<Utf8StringFormatter, string>
|
||||
{
|
||||
public override Utf8StringFormatter GetFormatter()
|
||||
{
|
||||
return Utf8StringFormatter.Default;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Utf16StringFormatterAttribute : MemoryPackCustomFormatterAttribute<Utf16StringFormatter, string>
|
||||
{
|
||||
public override Utf16StringFormatter GetFormatter()
|
||||
{
|
||||
return Utf16StringFormatter.Default;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class OrdinalIgnoreCaseStringDictionaryFormatter<TValue> : MemoryPackCustomFormatterAttribute<DictionaryFormatter<string, TValue?>, Dictionary<string, TValue?>>
|
||||
{
|
||||
static readonly DictionaryFormatter<string, TValue?> formatter = new DictionaryFormatter<string, TValue?>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public override DictionaryFormatter<string, TValue?> GetFormatter()
|
||||
{
|
||||
return formatter;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class InternStringFormatterAttribute : MemoryPackCustomFormatterAttribute<InternStringFormatter, string>
|
||||
{
|
||||
public override InternStringFormatter GetFormatter()
|
||||
{
|
||||
return InternStringFormatter.Default;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class BitPackFormatterAttribute : MemoryPackCustomFormatterAttribute<BitPackFormatter, bool[]>
|
||||
{
|
||||
public override BitPackFormatter GetFormatter()
|
||||
{
|
||||
return BitPackFormatter.Default;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class BrotliFormatterAttribute : MemoryPackCustomFormatterAttribute<BrotliFormatter, byte[]>
|
||||
{
|
||||
public System.IO.Compression.CompressionLevel CompressionLevel { get; }
|
||||
public int Window { get; }
|
||||
public int DecompressionSizeLimit { get; }
|
||||
|
||||
public BrotliFormatterAttribute(System.IO.Compression.CompressionLevel compressionLevel = System.IO.Compression.CompressionLevel.Fastest, int window = BrotliUtils.WindowBits_Default, int decompressionSizeLimit = BrotliFormatter.DefaultDecompssionSizeLimit)
|
||||
{
|
||||
this.CompressionLevel = compressionLevel;
|
||||
this.Window = window;
|
||||
this.DecompressionSizeLimit = decompressionSizeLimit;
|
||||
}
|
||||
|
||||
public override BrotliFormatter GetFormatter()
|
||||
{
|
||||
return new BrotliFormatter(CompressionLevel, Window, DecompressionSizeLimit);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class BrotliFormatterAttribute<T> : MemoryPackCustomFormatterAttribute<BrotliFormatter<T>, T>
|
||||
{
|
||||
public System.IO.Compression.CompressionLevel CompressionLevel { get; }
|
||||
public int Window { get; }
|
||||
|
||||
public BrotliFormatterAttribute(System.IO.Compression.CompressionLevel compressionLevel = System.IO.Compression.CompressionLevel.Fastest, int window = BrotliUtils.WindowBits_Default)
|
||||
{
|
||||
this.CompressionLevel = compressionLevel;
|
||||
this.Window = window;
|
||||
}
|
||||
|
||||
public override BrotliFormatter<T> GetFormatter()
|
||||
{
|
||||
return new BrotliFormatter<T>(CompressionLevel, Window);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class BrotliStringFormatterAttribute : MemoryPackCustomFormatterAttribute<BrotliStringFormatter, string>
|
||||
{
|
||||
public System.IO.Compression.CompressionLevel CompressionLevel { get; }
|
||||
public int Window { get; }
|
||||
public int DecompressionSizeLimit { get; }
|
||||
|
||||
public BrotliStringFormatterAttribute(System.IO.Compression.CompressionLevel compressionLevel = System.IO.Compression.CompressionLevel.Fastest, int window = BrotliUtils.WindowBits_Default, int decompressionSizeLimit = BrotliFormatter.DefaultDecompssionSizeLimit)
|
||||
{
|
||||
this.CompressionLevel = compressionLevel;
|
||||
this.Window = window;
|
||||
this.DecompressionSizeLimit = decompressionSizeLimit;
|
||||
}
|
||||
|
||||
public override BrotliStringFormatter GetFormatter()
|
||||
{
|
||||
return new BrotliStringFormatter(CompressionLevel, Window, DecompressionSizeLimit);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MemoryPoolFormatterAttribute<T> : MemoryPackCustomFormatterAttribute<MemoryPoolFormatter<T>, Memory<T?>>
|
||||
{
|
||||
static readonly MemoryPoolFormatter<T> formatter = new MemoryPoolFormatter<T>();
|
||||
|
||||
public override MemoryPoolFormatter<T> GetFormatter()
|
||||
{
|
||||
return formatter;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ReadOnlyMemoryPoolFormatterAttribute<T> : MemoryPackCustomFormatterAttribute<ReadOnlyMemoryPoolFormatter<T>, ReadOnlyMemory<T?>>
|
||||
{
|
||||
static readonly ReadOnlyMemoryPoolFormatter<T> formatter = new ReadOnlyMemoryPoolFormatter<T>();
|
||||
|
||||
public override ReadOnlyMemoryPoolFormatter<T> GetFormatter()
|
||||
{
|
||||
return formatter;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1cc6f8595850d1c41ba61d06616f2d67
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c76a067728428843ae9ce827d31f1ec
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,228 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Formatters;
|
||||
using MemoryPack.Internal;
|
||||
using System.Buffers;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Array and Array-like type formatters
|
||||
// T[]
|
||||
// T[] where T: unmnaged
|
||||
// Memory
|
||||
// ReadOnlyMemory
|
||||
// ArraySegment
|
||||
// ReadOnlySequence
|
||||
|
||||
namespace MemoryPack
|
||||
{
|
||||
public static partial class MemoryPackFormatterProvider
|
||||
{
|
||||
static readonly Dictionary<Type, Type> ArrayLikeFormatters = new Dictionary<Type, Type>(4)
|
||||
{
|
||||
// If T[], choose UnmanagedArrayFormatter or DangerousUnmanagedTypeArrayFormatter or ArrayFormatter
|
||||
{ typeof(ArraySegment<>), typeof(ArraySegmentFormatter<>) },
|
||||
{ typeof(Memory<>), typeof(MemoryFormatter<>) },
|
||||
{ typeof(ReadOnlyMemory<>), typeof(ReadOnlyMemoryFormatter<>) },
|
||||
{ typeof(ReadOnlySequence<>), typeof(ReadOnlySequenceFormatter<>) },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace MemoryPack.Formatters
|
||||
{
|
||||
[Preserve]
|
||||
public sealed class UnmanagedArrayFormatter<T> : MemoryPackFormatter<T[]>
|
||||
where T : unmanaged
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref T[]? value)
|
||||
{
|
||||
writer.WriteUnmanagedArray(value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref T[]? value)
|
||||
{
|
||||
reader.ReadUnmanagedArray<T>(ref value);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class DangerousUnmanagedArrayFormatter<T> : MemoryPackFormatter<T[]>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref T[]? value)
|
||||
{
|
||||
writer.DangerousWriteUnmanagedArray(value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref T[]? value)
|
||||
{
|
||||
reader.DangerousReadUnmanagedArray<T>(ref value);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class ArrayFormatter<T> : MemoryPackFormatter<T?[]>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref T?[]? value)
|
||||
{
|
||||
writer.WriteArray(value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref T?[]? value)
|
||||
{
|
||||
reader.ReadArray(ref value);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class ArraySegmentFormatter<T> : MemoryPackFormatter<ArraySegment<T?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref ArraySegment<T?> value)
|
||||
{
|
||||
writer.WriteSpan(value.AsMemory().Span);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref ArraySegment<T?> value)
|
||||
{
|
||||
var array = reader.ReadArray<T>();
|
||||
value = (array == null) ? default : (ArraySegment<T?>)array;
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class MemoryFormatter<T> : MemoryPackFormatter<Memory<T?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref Memory<T?> value)
|
||||
{
|
||||
writer.WriteSpan(value.Span);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref Memory<T?> value)
|
||||
{
|
||||
value = reader.ReadArray<T>();
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class ReadOnlyMemoryFormatter<T> : MemoryPackFormatter<ReadOnlyMemory<T?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref ReadOnlyMemory<T?> value)
|
||||
{
|
||||
writer.WriteSpan(value.Span);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref ReadOnlyMemory<T?> value)
|
||||
{
|
||||
value = reader.ReadArray<T>();
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class ReadOnlySequenceFormatter<T> : MemoryPackFormatter<ReadOnlySequence<T?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref ReadOnlySequence<T?> value)
|
||||
{
|
||||
if (value.IsSingleSegment)
|
||||
{
|
||||
writer.WriteSpan(value.FirstSpan);
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteCollectionHeader(checked((int)value.Length));
|
||||
foreach (var memory in value)
|
||||
{
|
||||
writer.WriteSpanWithoutLengthHeader(memory.Span);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref ReadOnlySequence<T?> value)
|
||||
{
|
||||
var array = reader.ReadArray<T>();
|
||||
value = (array == null) ? default : new ReadOnlySequence<T?>(array);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class MemoryPoolFormatter<T> : MemoryPackFormatter<Memory<T?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref Memory<T?> value)
|
||||
{
|
||||
writer.WriteSpan(value.Span);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref Memory<T?> value)
|
||||
{
|
||||
if (!reader.TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
value = Memory<T?>.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
var memory = ArrayPool<T?>.Shared.Rent(length).AsMemory(0, length);
|
||||
var span = memory.Span;
|
||||
reader.ReadSpanWithoutReadLengthHeader(length, ref span);
|
||||
value = memory;
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class ReadOnlyMemoryPoolFormatter<T> : MemoryPackFormatter<ReadOnlyMemory<T?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref ReadOnlyMemory<T?> value)
|
||||
{
|
||||
writer.WriteSpan(value.Span);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref ReadOnlyMemory<T?> value)
|
||||
{
|
||||
if (!reader.TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
value = Memory<T?>.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
var memory = ArrayPool<T?>.Shared.Rent(length).AsMemory(0, length);
|
||||
var span = memory.Span;
|
||||
reader.ReadSpanWithoutReadLengthHeader(length, ref span);
|
||||
value = memory;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ea47c22508b03445aabd57919531dc4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
[Preserve]
|
||||
public sealed class BigIntegerFormatter : MemoryPackFormatter<BigInteger>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref BigInteger value)
|
||||
{
|
||||
#if !UNITY_2021_2_OR_NEWER
|
||||
Span<byte> temp = stackalloc byte[255];
|
||||
if (value.TryWriteBytes(temp, out var written))
|
||||
{
|
||||
writer.WriteUnmanagedSpan(temp.Slice(written));
|
||||
return;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
var byteArray = value.ToByteArray();
|
||||
writer.WriteUnmanagedArray(byteArray);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref BigInteger value)
|
||||
{
|
||||
if (!reader.TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = default;
|
||||
return;
|
||||
}
|
||||
|
||||
ref var src = ref reader.GetSpanReference(length);
|
||||
value = new BigInteger(MemoryMarshal.CreateReadOnlySpan(ref src, length));
|
||||
|
||||
reader.Advance(length);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85c3a3fc180ed724798da6a6bd7c8635
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
[Preserve]
|
||||
public sealed class BitArrayFormatter : MemoryPackFormatter<BitArray>
|
||||
{
|
||||
// serialize [m_length, m_array]
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref BitArray? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
ref var view = ref Unsafe.As<BitArray, BitArrayView>(ref value);
|
||||
|
||||
writer.WriteUnmanagedWithObjectHeader(2, view.m_length);
|
||||
writer.WriteUnmanagedArray(view.m_array);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref BitArray? value)
|
||||
{
|
||||
if (!reader.TryReadObjectHeader(out var count))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (count != 2) MemoryPackSerializationException.ThrowInvalidPropertyCount(2, count);
|
||||
|
||||
reader.ReadUnmanaged(out int length);
|
||||
|
||||
var bitArray = new BitArray(length, false); // create internal int[] and set m_length to length
|
||||
|
||||
ref var view = ref Unsafe.As<BitArray, BitArrayView>(ref bitArray);
|
||||
reader.ReadUnmanagedArray(ref view.m_array!);
|
||||
|
||||
value = bitArray;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
[Preserve]
|
||||
internal class BitArrayView
|
||||
{
|
||||
public int[] m_array;
|
||||
public int m_length;
|
||||
public int _version;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7910d03f8a5023479d0bf2968f56267
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e648f2f021a720e45a7fda5bddd7aae9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using System.Globalization;
|
||||
using MemoryPack.Internal;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
[Preserve]
|
||||
public sealed class CultureInfoFormatter : MemoryPackFormatter<CultureInfo>
|
||||
{
|
||||
// treat as a string(Name).
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref CultureInfo? value)
|
||||
{
|
||||
writer.WriteString(value?.Name);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref CultureInfo? value)
|
||||
{
|
||||
var str = reader.ReadString();
|
||||
if (str == null)
|
||||
{
|
||||
value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = CultureInfo.GetCultureInfo(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20da488211e109640859d46ab47e442d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
public sealed class DynamicUnionFormatter<T> : MemoryPackFormatter<T>
|
||||
where T : class
|
||||
{
|
||||
readonly Dictionary<Type, ushort> typeToTag;
|
||||
readonly Dictionary<ushort, Type> tagToType;
|
||||
|
||||
public DynamicUnionFormatter(params (ushort Tag, Type Type)[] memoryPackUnions)
|
||||
{
|
||||
typeToTag = memoryPackUnions.ToDictionary(x => x.Type, x => x.Tag);
|
||||
tagToType = memoryPackUnions.ToDictionary(x => x.Tag, x => x.Type);
|
||||
}
|
||||
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref T? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullUnionHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
var type = value.GetType();
|
||||
if (typeToTag.TryGetValue(type, out var tag))
|
||||
{
|
||||
writer.WriteUnionHeader(tag);
|
||||
writer.WriteValue(type, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryPackSerializationException.ThrowNotFoundInUnionType(type, typeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref T? value)
|
||||
{
|
||||
if (!reader.TryReadUnionHeader(out var tag))
|
||||
{
|
||||
value = default;
|
||||
return;
|
||||
}
|
||||
|
||||
if (tagToType.TryGetValue(tag, out var type))
|
||||
{
|
||||
object? v = value;
|
||||
reader.ReadValue(type, ref v);
|
||||
value = (T?)v;
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryPackSerializationException.ThrowInvalidTag(tag, typeof(T));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6edda14b6f541844284c998396cafa2a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,182 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
[Preserve]
|
||||
public sealed class GenericCollectionFormatter<TCollection, TElement> : MemoryPackFormatter<TCollection?>
|
||||
where TCollection : ICollection<TElement?>, new()
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref TCollection? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullCollectionHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
var formatter = writer.GetFormatter<TElement?>();
|
||||
|
||||
writer.WriteCollectionHeader(value.Count);
|
||||
foreach (var item in value)
|
||||
{
|
||||
var v = item;
|
||||
formatter.Serialize(ref writer, ref v);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref TCollection? value)
|
||||
{
|
||||
if (!reader.TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = default;
|
||||
return;
|
||||
}
|
||||
|
||||
var formatter = reader.GetFormatter<TElement?>();
|
||||
|
||||
var collection = new TCollection();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
TElement? v = default;
|
||||
formatter.Deserialize(ref reader, ref v);
|
||||
collection.Add(v);
|
||||
}
|
||||
|
||||
value = collection;
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public abstract class GenericSetFormatterBase<TSet, TElement> : MemoryPackFormatter<TSet?>
|
||||
where TSet : ISet<TElement?>
|
||||
{
|
||||
[Preserve]
|
||||
protected abstract TSet CreateSet();
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref TSet? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullCollectionHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
var formatter = writer.GetFormatter<TElement?>();
|
||||
|
||||
writer.WriteCollectionHeader(value.Count);
|
||||
foreach (var item in value)
|
||||
{
|
||||
var v = item;
|
||||
formatter.Serialize(ref writer, ref v);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref TSet? value)
|
||||
{
|
||||
if (!reader.TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = default;
|
||||
return;
|
||||
}
|
||||
|
||||
var formatter = reader.GetFormatter<TElement?>();
|
||||
|
||||
var collection = CreateSet();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
TElement? v = default;
|
||||
formatter.Deserialize(ref reader, ref v);
|
||||
collection.Add(v);
|
||||
}
|
||||
|
||||
value = collection;
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class GenericSetFormatter<TSet, TElement> : GenericSetFormatterBase<TSet, TElement>
|
||||
where TSet : ISet<TElement?>, new()
|
||||
{
|
||||
protected override TSet CreateSet()
|
||||
{
|
||||
return new();
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public abstract class GenericDictionaryFormatterBase<TDictionary, TKey, TValue> : MemoryPackFormatter<TDictionary?>
|
||||
where TKey : notnull
|
||||
where TDictionary : IDictionary<TKey, TValue?>
|
||||
{
|
||||
[Preserve]
|
||||
protected abstract TDictionary CreateDictionary();
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref TDictionary? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullCollectionHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
var keyFormatter = writer.GetFormatter<TKey>();
|
||||
var valueFormatter = writer.GetFormatter<TValue>();
|
||||
|
||||
writer.WriteCollectionHeader(value.Count);
|
||||
foreach (var item in value)
|
||||
{
|
||||
KeyValuePairFormatter.Serialize(keyFormatter, valueFormatter, ref writer, item!);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref TDictionary? value)
|
||||
{
|
||||
if (!reader.TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = default;
|
||||
return;
|
||||
}
|
||||
|
||||
var keyFormatter = reader.GetFormatter<TKey>();
|
||||
var valueFormatter = reader.GetFormatter<TValue>();
|
||||
|
||||
var dict = CreateDictionary();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
KeyValuePairFormatter.Deserialize(keyFormatter, valueFormatter, ref reader, out var k, out var v);
|
||||
dict.Add(k!, v);
|
||||
}
|
||||
|
||||
value = dict;
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class GenericDictionaryFormatter<TDictionary, TKey, TValue> : GenericDictionaryFormatterBase<TDictionary, TKey, TValue>
|
||||
where TKey : notnull
|
||||
where TDictionary : IDictionary<TKey, TValue?>, new()
|
||||
{
|
||||
[Preserve]
|
||||
protected override TDictionary CreateDictionary()
|
||||
{
|
||||
return new();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b0ee256b8ba5bf44904e20cbfd830e6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,725 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Formatters;
|
||||
using MemoryPack.Internal;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// interface collection formatters
|
||||
// IEnumerable, ICollection, IReadOnlyCollection, IList, IReadOnlyList
|
||||
// IDictionary, IReadOnlyDictionary, ILookup, IGrouping, ISet, IReadOnlySet
|
||||
|
||||
namespace MemoryPack
|
||||
{
|
||||
public static partial class MemoryPackFormatterProvider
|
||||
{
|
||||
static readonly Dictionary<Type, Type> InterfaceCollectionFormatters = new(11)
|
||||
{
|
||||
{ typeof(IEnumerable<>), typeof(InterfaceEnumerableFormatter<>) },
|
||||
{ typeof(ICollection<>), typeof(InterfaceCollectionFormatter<>) },
|
||||
{ typeof(IReadOnlyCollection<>), typeof(InterfaceReadOnlyCollectionFormatter<>) },
|
||||
{ typeof(IList<>), typeof(InterfaceListFormatter<>) },
|
||||
{ typeof(IReadOnlyList<>), typeof(InterfaceReadOnlyListFormatter<>) },
|
||||
{ typeof(IDictionary<,>), typeof(InterfaceDictionaryFormatter<,>) },
|
||||
{ typeof(IReadOnlyDictionary<,>), typeof(InterfaceReadOnlyDictionaryFormatter<,>) },
|
||||
{ typeof(ILookup<,>), typeof(InterfaceLookupFormatter<,>) },
|
||||
{ typeof(IGrouping<,>), typeof(InterfaceGroupingFormatter<,>) },
|
||||
{ typeof(ISet<>), typeof(InterfaceSetFormatter<>) },
|
||||
#if NET7_0_OR_GREATER
|
||||
{ typeof(IReadOnlySet<>), typeof(InterfaceReadOnlySetFormatter<>) },
|
||||
#endif
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace MemoryPack.Formatters
|
||||
{
|
||||
using static InterfaceCollectionFormatterUtils;
|
||||
|
||||
internal static class InterfaceCollectionFormatterUtils
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool TrySerializeOptimized<TCollection, TElement>(ref MemoryPackWriter writer, [NotNullWhen(false)] ref TCollection? value)
|
||||
where TCollection : IEnumerable<TElement>
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullCollectionHeader();
|
||||
return true;
|
||||
}
|
||||
|
||||
// optimize for list or array
|
||||
|
||||
if (value is TElement?[] array)
|
||||
{
|
||||
writer.WriteArray(array);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
if (value is List<TElement?> list)
|
||||
{
|
||||
writer.WriteSpan(CollectionsMarshal.AsSpan(list));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void SerializeCollection<TCollection, TElement>(ref MemoryPackWriter writer, ref TCollection? value)
|
||||
where TCollection : ICollection<TElement>
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
{
|
||||
if (TrySerializeOptimized<TCollection, TElement>(ref writer, ref value)) return;
|
||||
|
||||
var formatter = writer.GetFormatter<TElement>();
|
||||
writer.WriteCollectionHeader(value.Count);
|
||||
foreach (var item in value)
|
||||
{
|
||||
var v = item;
|
||||
formatter.Serialize(ref writer, ref v!);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SerializeReadOnlyCollection<TCollection, TElement>(ref MemoryPackWriter writer, ref TCollection? value)
|
||||
where TCollection : IReadOnlyCollection<TElement>
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
{
|
||||
if (TrySerializeOptimized<TCollection, TElement>(ref writer, ref value)) return;
|
||||
|
||||
var formatter = writer.GetFormatter<TElement>();
|
||||
writer.WriteCollectionHeader(value.Count);
|
||||
foreach (var item in value)
|
||||
{
|
||||
var v = item;
|
||||
formatter.Serialize(ref writer, ref v!);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<T?>? ReadList<T>(ref MemoryPackReader reader)
|
||||
{
|
||||
var formatter = reader.GetFormatter<List<T?>>();
|
||||
List<T?>? v = default;
|
||||
formatter.Deserialize(ref reader, ref v);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class InterfaceEnumerableFormatter<T> : MemoryPackFormatter<IEnumerable<T?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref IEnumerable<T?>? value)
|
||||
{
|
||||
if (TrySerializeOptimized<IEnumerable<T?>, T?>(ref writer, ref value)) return;
|
||||
|
||||
if (value.TryGetNonEnumeratedCountEx(out var count))
|
||||
{
|
||||
var formatter = writer.GetFormatter<T?>();
|
||||
writer.WriteCollectionHeader(count);
|
||||
foreach (var item in value)
|
||||
{
|
||||
var v = item;
|
||||
formatter.Serialize(ref writer, ref v);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// write to tempbuffer(because we don't know length so can't write header)
|
||||
var tempBuffer = ReusableLinkedArrayBufferWriterPool.Rent();
|
||||
try
|
||||
{
|
||||
var tempWriter = new MemoryPackWriter(ref Unsafe.As<ReusableLinkedArrayBufferWriter, IBufferWriter<byte>>(ref tempBuffer), writer.OptionalState);
|
||||
|
||||
count = 0;
|
||||
var formatter = writer.GetFormatter<T?>();
|
||||
foreach (var item in value)
|
||||
{
|
||||
count++;
|
||||
var v = item;
|
||||
formatter.Serialize(ref tempWriter, ref v);
|
||||
}
|
||||
|
||||
tempWriter.Flush();
|
||||
|
||||
// write to parameter writer.
|
||||
writer.WriteCollectionHeader(count);
|
||||
tempBuffer.WriteToAndReset(ref writer);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ReusableLinkedArrayBufferWriterPool.Return(tempBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref IEnumerable<T?>? value)
|
||||
{
|
||||
value = reader.ReadArray<T?>();
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class InterfaceCollectionFormatter<T> : MemoryPackFormatter<ICollection<T?>>
|
||||
{
|
||||
static InterfaceCollectionFormatter()
|
||||
{
|
||||
if (!MemoryPackFormatterProvider.IsRegistered<List<T?>>())
|
||||
{
|
||||
MemoryPackFormatterProvider.Register(new ListFormatter<T>());
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref ICollection<T?>? value)
|
||||
{
|
||||
SerializeCollection<ICollection<T?>, T?>(ref writer, ref value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref ICollection<T?>? value)
|
||||
{
|
||||
value = ReadList<T?>(ref reader);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class InterfaceReadOnlyCollectionFormatter<T> : MemoryPackFormatter<IReadOnlyCollection<T?>>
|
||||
{
|
||||
static InterfaceReadOnlyCollectionFormatter()
|
||||
{
|
||||
if (!MemoryPackFormatterProvider.IsRegistered<List<T?>>())
|
||||
{
|
||||
MemoryPackFormatterProvider.Register(new ListFormatter<T>());
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref IReadOnlyCollection<T?>? value)
|
||||
{
|
||||
SerializeReadOnlyCollection<IReadOnlyCollection<T?>, T?>(ref writer, ref value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref IReadOnlyCollection<T?>? value)
|
||||
{
|
||||
value = ReadList<T?>(ref reader);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class InterfaceListFormatter<T> : MemoryPackFormatter<IList<T?>>
|
||||
{
|
||||
static InterfaceListFormatter()
|
||||
{
|
||||
if (!MemoryPackFormatterProvider.IsRegistered<List<T?>>())
|
||||
{
|
||||
MemoryPackFormatterProvider.Register(new ListFormatter<T>());
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref IList<T?>? value)
|
||||
{
|
||||
SerializeCollection<IList<T?>, T?>(ref writer, ref value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref IList<T?>? value)
|
||||
{
|
||||
value = ReadList<T?>(ref reader);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class InterfaceReadOnlyListFormatter<T> : MemoryPackFormatter<IReadOnlyList<T?>>
|
||||
{
|
||||
static InterfaceReadOnlyListFormatter()
|
||||
{
|
||||
if (!MemoryPackFormatterProvider.IsRegistered<List<T?>>())
|
||||
{
|
||||
MemoryPackFormatterProvider.Register(new ListFormatter<T>());
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref IReadOnlyList<T?>? value)
|
||||
{
|
||||
SerializeReadOnlyCollection<IReadOnlyList<T?>, T?>(ref writer, ref value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref IReadOnlyList<T?>? value)
|
||||
{
|
||||
value = ReadList<T?>(ref reader);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class InterfaceDictionaryFormatter<TKey, TValue> : MemoryPackFormatter<IDictionary<TKey, TValue?>>
|
||||
where TKey : notnull
|
||||
{
|
||||
readonly IEqualityComparer<TKey>? equalityComparer;
|
||||
|
||||
public InterfaceDictionaryFormatter()
|
||||
: this(null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public InterfaceDictionaryFormatter(IEqualityComparer<TKey>? equalityComparer)
|
||||
{
|
||||
this.equalityComparer = equalityComparer;
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref IDictionary<TKey, TValue?>? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullCollectionHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
var keyFormatter = writer.GetFormatter<TKey>();
|
||||
var valueFormatter = writer.GetFormatter<TValue>();
|
||||
|
||||
writer.WriteCollectionHeader(value.Count);
|
||||
foreach (var item in value)
|
||||
{
|
||||
KeyValuePairFormatter.Serialize(keyFormatter, valueFormatter, ref writer, item!);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref IDictionary<TKey, TValue?>? value)
|
||||
{
|
||||
if (!reader.TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var dict = new Dictionary<TKey, TValue?>(equalityComparer);
|
||||
|
||||
var keyFormatter = reader.GetFormatter<TKey>();
|
||||
var valueFormatter = reader.GetFormatter<TValue>();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
KeyValuePairFormatter.Deserialize(keyFormatter, valueFormatter, ref reader, out var k, out var v);
|
||||
dict.Add(k!, v);
|
||||
}
|
||||
|
||||
value = dict;
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class InterfaceReadOnlyDictionaryFormatter<TKey, TValue> : MemoryPackFormatter<IReadOnlyDictionary<TKey, TValue?>>
|
||||
where TKey : notnull
|
||||
{
|
||||
readonly IEqualityComparer<TKey>? equalityComparer;
|
||||
|
||||
public InterfaceReadOnlyDictionaryFormatter()
|
||||
: this(null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public InterfaceReadOnlyDictionaryFormatter(IEqualityComparer<TKey>? equalityComparer)
|
||||
{
|
||||
this.equalityComparer = equalityComparer;
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref IReadOnlyDictionary<TKey, TValue?>? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullCollectionHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
var keyFormatter = writer.GetFormatter<TKey>();
|
||||
var valueFormatter = writer.GetFormatter<TValue>();
|
||||
|
||||
writer.WriteCollectionHeader(value.Count);
|
||||
foreach (var item in value)
|
||||
{
|
||||
KeyValuePairFormatter.Serialize(keyFormatter, valueFormatter, ref writer, item!);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref IReadOnlyDictionary<TKey, TValue?>? value)
|
||||
{
|
||||
if (!reader.TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var dict = new Dictionary<TKey, TValue?>(equalityComparer);
|
||||
|
||||
var keyFormatter = reader.GetFormatter<TKey>();
|
||||
var valueFormatter = reader.GetFormatter<TValue>();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
KeyValuePairFormatter.Deserialize(keyFormatter, valueFormatter, ref reader, out var k, out var v);
|
||||
dict.Add(k!, v);
|
||||
}
|
||||
|
||||
value = dict;
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class InterfaceLookupFormatter<TKey, TElement> : MemoryPackFormatter<ILookup<TKey, TElement>>
|
||||
where TKey : notnull
|
||||
{
|
||||
static InterfaceLookupFormatter()
|
||||
{
|
||||
if (!MemoryPackFormatterProvider.IsRegistered<IGrouping<TKey, TElement>>())
|
||||
{
|
||||
MemoryPackFormatterProvider.Register(new InterfaceGroupingFormatter<TKey, TElement>());
|
||||
}
|
||||
}
|
||||
|
||||
readonly IEqualityComparer<TKey>? equalityComparer;
|
||||
|
||||
public InterfaceLookupFormatter()
|
||||
: this(null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public InterfaceLookupFormatter(IEqualityComparer<TKey>? equalityComparer)
|
||||
{
|
||||
this.equalityComparer = equalityComparer;
|
||||
}
|
||||
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref ILookup<TKey, TElement>? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullCollectionHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
var formatter = writer.GetFormatter<IGrouping<TKey, TElement>>();
|
||||
writer.WriteCollectionHeader(value.Count);
|
||||
foreach (var item in value)
|
||||
{
|
||||
var v = item;
|
||||
formatter.Serialize(ref writer, ref v);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref ILookup<TKey, TElement>? value)
|
||||
{
|
||||
if (!reader.TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var dict = new Dictionary<TKey, IGrouping<TKey, TElement>>(equalityComparer);
|
||||
|
||||
var formatter = reader.GetFormatter<IGrouping<TKey, TElement>>();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
IGrouping<TKey, TElement>? item = default;
|
||||
formatter.Deserialize(ref reader, ref item);
|
||||
if (item != null)
|
||||
{
|
||||
dict.Add(item.Key, item);
|
||||
}
|
||||
}
|
||||
value = new Lookup<TKey, TElement>(dict);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class InterfaceGroupingFormatter<TKey, TElement> : MemoryPackFormatter<IGrouping<TKey, TElement>>
|
||||
where TKey : notnull
|
||||
{
|
||||
// serialize as {key, [collection]}
|
||||
|
||||
static InterfaceGroupingFormatter()
|
||||
{
|
||||
if (!MemoryPackFormatterProvider.IsRegistered<IEnumerable<TElement>>())
|
||||
{
|
||||
MemoryPackFormatterProvider.Register(new InterfaceEnumerableFormatter<TElement>());
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref IGrouping<TKey, TElement>? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteObjectHeader(2);
|
||||
writer.WriteValue(value.Key);
|
||||
writer.WriteValue<IEnumerable<TElement>>(value); // write as IEnumerable<TElement>
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref IGrouping<TKey, TElement>? value)
|
||||
{
|
||||
if (!reader.TryReadObjectHeader(out var count))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (count != 2) MemoryPackSerializationException.ThrowInvalidPropertyCount(2, count);
|
||||
|
||||
var key = reader.ReadValue<TKey>();
|
||||
var values = reader.ReadArray<TElement>() as IEnumerable<TElement>;
|
||||
|
||||
if (key == null) MemoryPackSerializationException.ThrowDeserializeObjectIsNull(nameof(key));
|
||||
if (values == null) MemoryPackSerializationException.ThrowDeserializeObjectIsNull(nameof(values));
|
||||
|
||||
value = new Grouping<TKey, TElement>(key, values);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class InterfaceSetFormatter<T> : MemoryPackFormatter<ISet<T?>>
|
||||
{
|
||||
static InterfaceSetFormatter()
|
||||
{
|
||||
if (!MemoryPackFormatterProvider.IsRegistered<HashSet<T>>())
|
||||
{
|
||||
MemoryPackFormatterProvider.Register(new HashSetFormatter<T>());
|
||||
}
|
||||
}
|
||||
|
||||
readonly IEqualityComparer<T?>? equalityComparer;
|
||||
|
||||
public InterfaceSetFormatter()
|
||||
: this(null)
|
||||
{
|
||||
}
|
||||
|
||||
public InterfaceSetFormatter(IEqualityComparer<T?>? equalityComparer)
|
||||
{
|
||||
this.equalityComparer = equalityComparer;
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref ISet<T?>? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullCollectionHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
var formatter = writer.GetFormatter<T>();
|
||||
writer.WriteCollectionHeader(value.Count);
|
||||
foreach (var item in value)
|
||||
{
|
||||
var v = item;
|
||||
formatter.Serialize(ref writer, ref v);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref ISet<T?>? value)
|
||||
{
|
||||
if (!reader.TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var set = new HashSet<T?>(length, equalityComparer);
|
||||
|
||||
var formatter = reader.GetFormatter<T>();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
T? item = default;
|
||||
formatter.Deserialize(ref reader, ref item);
|
||||
set.Add(item);
|
||||
}
|
||||
|
||||
value = set;
|
||||
}
|
||||
}
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
[Preserve]
|
||||
public sealed class InterfaceReadOnlySetFormatter<T> : MemoryPackFormatter<IReadOnlySet<T?>>
|
||||
{
|
||||
static InterfaceReadOnlySetFormatter()
|
||||
{
|
||||
if (!MemoryPackFormatterProvider.IsRegistered<HashSet<T>>())
|
||||
{
|
||||
MemoryPackFormatterProvider.Register(new HashSetFormatter<T>());
|
||||
}
|
||||
}
|
||||
|
||||
readonly IEqualityComparer<T?>? equalityComparer;
|
||||
|
||||
public InterfaceReadOnlySetFormatter()
|
||||
: this(null)
|
||||
{
|
||||
}
|
||||
|
||||
public InterfaceReadOnlySetFormatter(IEqualityComparer<T?>? equalityComparer)
|
||||
{
|
||||
this.equalityComparer = equalityComparer;
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref IReadOnlySet<T?>? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullCollectionHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
var formatter = writer.GetFormatter<T>();
|
||||
writer.WriteCollectionHeader(value.Count);
|
||||
foreach (var item in value)
|
||||
{
|
||||
var v = item;
|
||||
formatter.Serialize(ref writer, ref v);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref IReadOnlySet<T?>? value)
|
||||
{
|
||||
if (!reader.TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var set = new HashSet<T?>(length, equalityComparer);
|
||||
|
||||
var formatter = reader.GetFormatter<T>();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
T? item = default;
|
||||
formatter.Deserialize(ref reader, ref item);
|
||||
set.Add(item);
|
||||
}
|
||||
|
||||
value = set;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
[Preserve]
|
||||
internal sealed class Grouping<TKey, TElement> : IGrouping<TKey, TElement>
|
||||
{
|
||||
readonly TKey key;
|
||||
readonly IEnumerable<TElement> elements;
|
||||
|
||||
public Grouping(TKey key, IEnumerable<TElement> elements)
|
||||
{
|
||||
this.key = key;
|
||||
this.elements = elements;
|
||||
}
|
||||
|
||||
public TKey Key
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.key;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<TElement> GetEnumerator()
|
||||
{
|
||||
return this.elements.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this.elements.GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
internal sealed class Lookup<TKey, TElement> : ILookup<TKey, TElement>
|
||||
where TKey : notnull
|
||||
{
|
||||
readonly Dictionary<TKey, IGrouping<TKey, TElement>> groupings;
|
||||
|
||||
public Lookup(Dictionary<TKey, IGrouping<TKey, TElement>> groupings)
|
||||
{
|
||||
this.groupings = groupings;
|
||||
}
|
||||
|
||||
public IEnumerable<TElement> this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.groupings[key];
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.groupings.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(TKey key)
|
||||
{
|
||||
return this.groupings.ContainsKey(key);
|
||||
}
|
||||
|
||||
public IEnumerator<IGrouping<TKey, TElement>> GetEnumerator()
|
||||
{
|
||||
return this.groupings.Values.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this.groupings.Values.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 92a5c3e606f68e940a5504e80e372051
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Buffers;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
[Preserve]
|
||||
public static class KeyValuePairFormatter
|
||||
{
|
||||
// for Dictionary serialization
|
||||
|
||||
[Preserve]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Serialize<TKey, TValue>(IMemoryPackFormatter<TKey> keyFormatter, IMemoryPackFormatter<TValue> valueFormatter, ref MemoryPackWriter writer, KeyValuePair<TKey?, TValue?> value)
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<KeyValuePair<TKey?, TValue?>>())
|
||||
{
|
||||
writer.DangerousWriteUnmanaged(value);
|
||||
return;
|
||||
}
|
||||
|
||||
value.Deconstruct(out var k, out var v);
|
||||
keyFormatter.Serialize(ref writer, ref k);
|
||||
valueFormatter.Serialize(ref writer, ref v);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Deserialize<TKey, TValue>(IMemoryPackFormatter<TKey> keyFormatter, IMemoryPackFormatter<TValue> valueFormatter, ref MemoryPackReader reader, out TKey? key, out TValue? value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<KeyValuePair<TKey?, TValue?>>())
|
||||
{
|
||||
reader.DangerousReadUnmanaged(out KeyValuePair<TKey?, TValue?> kvp);
|
||||
key = kvp.Key;
|
||||
value = kvp.Value;
|
||||
return;
|
||||
}
|
||||
|
||||
key = default;
|
||||
value = default;
|
||||
keyFormatter.Deserialize(ref reader, ref key);
|
||||
valueFormatter.Deserialize(ref reader, ref value);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class KeyValuePairFormatter<TKey, TValue> : MemoryPackFormatter<KeyValuePair<TKey?, TValue?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref KeyValuePair<TKey?, TValue?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<KeyValuePair<TKey?, TValue?>>())
|
||||
{
|
||||
writer.DangerousWriteUnmanaged(value);
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteValue(value.Key);
|
||||
writer.WriteValue(value.Value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref KeyValuePair<TKey?, TValue?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<KeyValuePair<TKey?, TValue?>>())
|
||||
{
|
||||
reader.DangerousReadUnmanaged(out value);
|
||||
return;
|
||||
}
|
||||
|
||||
value = new KeyValuePair<TKey?, TValue?>(
|
||||
reader.ReadValue<TKey>(),
|
||||
reader.ReadValue<TValue>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f407ce074ce08af448c71d52ab5ef2c4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
[Preserve]
|
||||
public sealed class LazyFormatter<T> : MemoryPackFormatter<Lazy<T?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref Lazy<T?>? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteObjectHeader(1);
|
||||
writer.WriteValue(value.Value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref Lazy<T?>? value)
|
||||
{
|
||||
if (!reader.TryReadObjectHeader(out var count))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (count != 1) MemoryPackSerializationException.ThrowInvalidPropertyCount(1, count);
|
||||
|
||||
var v = reader.ReadValue<T>();
|
||||
value = new Lazy<T?>(v);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 435e06feb1c6e99469622c788eb68163
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
[Preserve]
|
||||
public sealed class MemoryPackableFormatter<T> : MemoryPackFormatter<T>
|
||||
where T : IMemoryPackable<T>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref T? value)
|
||||
{
|
||||
T.Serialize(ref writer, ref Unsafe.AsRef(value));
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref T? value)
|
||||
{
|
||||
T.Deserialize(ref reader, ref value);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86918186878d8454db7dc10ffc57057d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,373 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
[Preserve]
|
||||
public sealed class TwoDimensionalArrayFormatter<T> : MemoryPackFormatter<T?[,]>
|
||||
{
|
||||
// {i-length, j-length, [total-length, values]}
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref T?[,]? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteObjectHeader(3);
|
||||
|
||||
var i = value.GetLength(0);
|
||||
var j = value.GetLength(1);
|
||||
writer.WriteUnmanaged(i, j);
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T?>())
|
||||
{
|
||||
var byteCount = Unsafe.SizeOf<T>() * i * j;
|
||||
ref var src = ref MemoryMarshal.GetArrayDataReference(value);
|
||||
ref var dest = ref writer.GetSpanReference(byteCount + 4);
|
||||
|
||||
Unsafe.WriteUnaligned(ref dest, value.Length);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.Add(ref dest, 4), ref src, (uint)byteCount);
|
||||
writer.Advance(byteCount + 4);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
|
||||
writer.WriteCollectionHeader(value.Length);
|
||||
var formatter = writer.GetFormatter<T?>();
|
||||
foreach (var item in value)
|
||||
{
|
||||
var v = item;
|
||||
formatter.Serialize(ref writer, ref v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref T?[,]? value)
|
||||
{
|
||||
if (!reader.TryReadObjectHeader(out var propertyCount))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (propertyCount != 3)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowInvalidPropertyCount(3, propertyCount);
|
||||
}
|
||||
|
||||
reader.ReadUnmanaged(out int iLength, out int jLength);
|
||||
|
||||
if (!reader.TryReadCollectionHeader(out var length))
|
||||
{
|
||||
MemoryPackSerializationException.ThrowInvalidCollection();
|
||||
}
|
||||
|
||||
if (value != null && value.GetLength(0) == iLength && value.GetLength(1) == jLength && value.Length == length)
|
||||
{
|
||||
// allow overwrite
|
||||
}
|
||||
else
|
||||
{
|
||||
value = new T[iLength, jLength];
|
||||
}
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T?>())
|
||||
{
|
||||
var byteCount = Unsafe.SizeOf<T>() * iLength * jLength;
|
||||
ref var dest = ref MemoryMarshal.GetArrayDataReference(value);
|
||||
ref var src = ref reader.GetSpanReference(byteCount);
|
||||
Unsafe.CopyBlockUnaligned(ref dest, ref src, (uint)byteCount);
|
||||
|
||||
reader.Advance(byteCount);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
var formatter = reader.GetFormatter<T?>();
|
||||
|
||||
var i = 0;
|
||||
var j = -1;
|
||||
var count = 0;
|
||||
while (count++ < length)
|
||||
{
|
||||
if (j < jLength - 1)
|
||||
{
|
||||
j++;
|
||||
}
|
||||
else
|
||||
{
|
||||
j = 0;
|
||||
i++;
|
||||
}
|
||||
|
||||
formatter.Deserialize(ref reader, ref value[i, j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class ThreeDimensionalArrayFormatter<T> : MemoryPackFormatter<T?[,,]>
|
||||
{
|
||||
// {i-length, j-length, k-length, [total-length, values]}
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref T?[,,]? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteObjectHeader(4);
|
||||
|
||||
var i = value.GetLength(0);
|
||||
var j = value.GetLength(1);
|
||||
var k = value.GetLength(2);
|
||||
writer.WriteUnmanaged(i, j, k);
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T?>())
|
||||
{
|
||||
var byteCount = Unsafe.SizeOf<T>() * i * j * k;
|
||||
ref var src = ref MemoryMarshal.GetArrayDataReference(value);
|
||||
ref var dest = ref writer.GetSpanReference(byteCount + 4);
|
||||
|
||||
Unsafe.WriteUnaligned(ref dest, value.Length);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.Add(ref dest, 4), ref src, (uint)byteCount);
|
||||
writer.Advance(byteCount + 4);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
writer.WriteCollectionHeader(value.Length);
|
||||
var formatter = writer.GetFormatter<T?>();
|
||||
foreach (var item in value)
|
||||
{
|
||||
var v = item;
|
||||
formatter.Serialize(ref writer, ref v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref T?[,,]? value)
|
||||
{
|
||||
if (!reader.TryReadObjectHeader(out var propertyCount))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (propertyCount != 4)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowInvalidPropertyCount(4, propertyCount);
|
||||
}
|
||||
|
||||
reader.ReadUnmanaged(out int iLength, out int jLength, out int kLength);
|
||||
|
||||
if (!reader.TryReadCollectionHeader(out var length))
|
||||
{
|
||||
MemoryPackSerializationException.ThrowInvalidCollection();
|
||||
}
|
||||
|
||||
if (value != null && value.GetLength(0) == iLength && value.GetLength(1) == jLength && value.GetLength(2) == kLength && value.Length == length)
|
||||
{
|
||||
// allow overwrite
|
||||
}
|
||||
else
|
||||
{
|
||||
value = new T[iLength, jLength, kLength];
|
||||
}
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T?>())
|
||||
{
|
||||
var byteCount = Unsafe.SizeOf<T>() * iLength * jLength * kLength;
|
||||
ref var dest = ref MemoryMarshal.GetArrayDataReference(value);
|
||||
ref var src = ref reader.GetSpanReference(byteCount);
|
||||
Unsafe.CopyBlockUnaligned(ref dest, ref src, (uint)byteCount);
|
||||
|
||||
reader.Advance(byteCount);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
var formatter = reader.GetFormatter<T?>();
|
||||
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
var k = -1;
|
||||
var count = 0;
|
||||
while (count++ < length)
|
||||
{
|
||||
if (k < kLength - 1)
|
||||
{
|
||||
k++;
|
||||
}
|
||||
else if (j < jLength - 1)
|
||||
{
|
||||
k = 0;
|
||||
j++;
|
||||
}
|
||||
else
|
||||
{
|
||||
k = 0;
|
||||
j = 0;
|
||||
i++;
|
||||
}
|
||||
|
||||
formatter.Deserialize(ref reader, ref value[i, j, k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class FourDimensionalArrayFormatter<T> : MemoryPackFormatter<T?[,,,]>
|
||||
{
|
||||
// {i-length, j-length, k-length, l-length, [total-length, values]}
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref T?[,,,]? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteObjectHeader(5);
|
||||
|
||||
var i = value.GetLength(0);
|
||||
var j = value.GetLength(1);
|
||||
var k = value.GetLength(2);
|
||||
var l = value.GetLength(3);
|
||||
writer.WriteUnmanaged(i, j, k, l);
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T?>())
|
||||
{
|
||||
var byteCount = Unsafe.SizeOf<T>() * i * j * k * l;
|
||||
ref var src = ref MemoryMarshal.GetArrayDataReference(value);
|
||||
ref var dest = ref writer.GetSpanReference(byteCount + 4);
|
||||
|
||||
Unsafe.WriteUnaligned(ref dest, value.Length);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.Add(ref dest, 4), ref src, (uint)byteCount);
|
||||
writer.Advance(byteCount + 4);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
writer.WriteCollectionHeader(value.Length);
|
||||
var formatter = writer.GetFormatter<T?>();
|
||||
foreach (var item in value)
|
||||
{
|
||||
var v = item;
|
||||
formatter.Serialize(ref writer, ref v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref T?[,,,]? value)
|
||||
{
|
||||
if (!reader.TryReadObjectHeader(out var propertyCount))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (propertyCount != 5)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowInvalidPropertyCount(5, propertyCount);
|
||||
}
|
||||
|
||||
reader.ReadUnmanaged(out int iLength, out int jLength, out int kLength, out int lLength);
|
||||
|
||||
if (!reader.TryReadCollectionHeader(out var length))
|
||||
{
|
||||
MemoryPackSerializationException.ThrowInvalidCollection();
|
||||
}
|
||||
|
||||
if (value != null && value.GetLength(0) == iLength && value.GetLength(1) == jLength && value.GetLength(2) == kLength && value.GetLength(3) == lLength && value.Length == length)
|
||||
{
|
||||
// allow overwrite
|
||||
}
|
||||
else
|
||||
{
|
||||
value = new T[iLength, jLength, kLength, lLength];
|
||||
}
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T?>())
|
||||
{
|
||||
var byteCount = Unsafe.SizeOf<T>() * iLength * jLength * kLength * lLength;
|
||||
ref var dest = ref MemoryMarshal.GetArrayDataReference(value);
|
||||
ref var src = ref reader.GetSpanReference(byteCount);
|
||||
Unsafe.CopyBlockUnaligned(ref dest, ref src, (uint)byteCount);
|
||||
|
||||
reader.Advance(byteCount);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
var formatter = reader.GetFormatter<T?>();
|
||||
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
var k = 0;
|
||||
var l = -1;
|
||||
var count = 0;
|
||||
while (count++ < length)
|
||||
{
|
||||
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++;
|
||||
}
|
||||
|
||||
formatter.Deserialize(ref reader, ref value[i, j, k, l]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 31ec28888c1521f45a5e0eb1ca226149
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
[Preserve]
|
||||
public sealed class NullableFormatter<T> : MemoryPackFormatter<T?>
|
||||
where T : struct
|
||||
{
|
||||
// Nullable<T> is sometimes serialized on UnmanagedFormatter.
|
||||
// to keep same result, check if type is unmanaged.
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref T? value)
|
||||
{
|
||||
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T>())
|
||||
{
|
||||
writer.DangerousWriteUnmanaged(value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!value.HasValue)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteObjectHeader(1);
|
||||
}
|
||||
|
||||
writer.WriteValue(value.Value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref T? value)
|
||||
{
|
||||
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T>())
|
||||
{
|
||||
reader.DangerousReadUnmanaged(out value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!reader.TryReadObjectHeader(out var count))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (count != 1) MemoryPackSerializationException.ThrowInvalidPropertyCount(1, count);
|
||||
|
||||
value = reader.ReadValue<T>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5cbe20000eeecfe429b3f80fca2ba176
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
[Preserve]
|
||||
public sealed class StringBuilderFormatter : MemoryPackFormatter<StringBuilder>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref StringBuilder? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullCollectionHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
// for performance reason, currently StringBuilder encode as Utf16, however try to write Utf8?
|
||||
// if (writer.Options.StringEncoding == StringEncoding.Utf16)
|
||||
{
|
||||
writer.WriteCollectionHeader(value.Length);
|
||||
|
||||
foreach (var chunk in value.GetChunks())
|
||||
{
|
||||
ref var p = ref writer.GetSpanReference(checked(chunk.Length * 2));
|
||||
ref var src = ref Unsafe.As<char, byte>(ref MemoryMarshal.GetReference(chunk.Span));
|
||||
Unsafe.CopyBlockUnaligned(ref p, ref src, (uint)chunk.Length * 2);
|
||||
|
||||
writer.Advance(chunk.Length * 2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
// write as utf16
|
||||
writer.WriteUtf16(value.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref StringBuilder? value)
|
||||
{
|
||||
if (!reader.TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
value = new StringBuilder(length);
|
||||
}
|
||||
else
|
||||
{
|
||||
value.Clear();
|
||||
value.EnsureCapacity(length);
|
||||
}
|
||||
|
||||
// note: require to check is Utf8
|
||||
// note: to improvement append as chunk(per 64K?)
|
||||
var size = checked(length * 2);
|
||||
ref var p = ref reader.GetSpanReference(size);
|
||||
var src = MemoryMarshal.CreateSpan(ref Unsafe.As<byte, char>(ref p), length);
|
||||
value.Append(src);
|
||||
|
||||
reader.Advance(size);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78f865f986bf7a844bcb6d3474b401a6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,279 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Compression;
|
||||
using MemoryPack.Internal;
|
||||
using System.Buffers;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
[Preserve]
|
||||
public sealed class StringFormatter : MemoryPackFormatter<string>
|
||||
{
|
||||
public static readonly StringFormatter Default = new StringFormatter();
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref string? value)
|
||||
{
|
||||
writer.WriteString(value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref string? value)
|
||||
{
|
||||
value = reader.ReadString();
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class Utf8StringFormatter : MemoryPackFormatter<string>
|
||||
{
|
||||
public static readonly Utf8StringFormatter Default = new Utf8StringFormatter();
|
||||
|
||||
[Preserve]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref string? value)
|
||||
{
|
||||
writer.WriteUtf8(value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref string? value)
|
||||
{
|
||||
value = reader.ReadString();
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class Utf16StringFormatter : MemoryPackFormatter<string>
|
||||
{
|
||||
public static readonly Utf16StringFormatter Default = new Utf16StringFormatter();
|
||||
|
||||
[Preserve]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref string? value)
|
||||
{
|
||||
writer.WriteUtf16(value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref string? value)
|
||||
{
|
||||
value = reader.ReadString();
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class InternStringFormatter : MemoryPackFormatter<string>
|
||||
{
|
||||
public static readonly InternStringFormatter Default = new InternStringFormatter();
|
||||
|
||||
[Preserve]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref string? value)
|
||||
{
|
||||
writer.WriteString(value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref string? value)
|
||||
{
|
||||
var str = reader.ReadString();
|
||||
if (str == null)
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
value = string.Intern(str);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class BrotliStringFormatter : MemoryPackFormatter<string>
|
||||
{
|
||||
[ThreadStatic]
|
||||
static StrongBox<int>? threadStaticConsumedBox;
|
||||
|
||||
internal const int DefaultDecompssionSizeLimit = 1024 * 1024 * 128; // 128MB
|
||||
|
||||
public static readonly BrotliStringFormatter Default = new BrotliStringFormatter();
|
||||
|
||||
readonly System.IO.Compression.CompressionLevel compressionLevel;
|
||||
readonly int window;
|
||||
readonly int decompressionSizeLimit;
|
||||
|
||||
public BrotliStringFormatter()
|
||||
: this(System.IO.Compression.CompressionLevel.Fastest)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BrotliStringFormatter(System.IO.Compression.CompressionLevel compressionLevel)
|
||||
: this(compressionLevel, BrotliUtils.WindowBits_Default)
|
||||
{
|
||||
this.compressionLevel = compressionLevel;
|
||||
}
|
||||
|
||||
public BrotliStringFormatter(System.IO.Compression.CompressionLevel compressionLevel, int window)
|
||||
: this(compressionLevel, window, DefaultDecompssionSizeLimit)
|
||||
{
|
||||
}
|
||||
|
||||
public BrotliStringFormatter(System.IO.Compression.CompressionLevel compressionLevel, int window, int decompressionSizeLimit)
|
||||
{
|
||||
this.compressionLevel = compressionLevel;
|
||||
this.window = window;
|
||||
this.decompressionSizeLimit = decompressionSizeLimit;
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref string? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullCollectionHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.Length == 0)
|
||||
{
|
||||
writer.WriteCollectionHeader(0);
|
||||
return;
|
||||
}
|
||||
|
||||
var quality = BrotliUtils.GetQualityFromCompressionLevel(compressionLevel);
|
||||
using var encoder = new BrotliEncoder(quality, window);
|
||||
|
||||
var srcLength = value.Length * 2;
|
||||
var maxLength = BrotliUtils.BrotliEncoderMaxCompressedSize(srcLength);
|
||||
|
||||
ref var spanRef = ref writer.GetSpanReference(maxLength + 4);
|
||||
var dest = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref spanRef, 4), maxLength);
|
||||
|
||||
var status = encoder.Compress(MemoryMarshal.AsBytes(value.AsSpan()), dest, out var bytesConsumed, out var bytesWritten, isFinalBlock: true);
|
||||
if (status != OperationStatus.Done)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowCompressionFailed(status);
|
||||
}
|
||||
|
||||
if (bytesConsumed != srcLength)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowCompressionFailed();
|
||||
}
|
||||
|
||||
Unsafe.WriteUnaligned(ref spanRef, value.Length);
|
||||
writer.Advance(bytesWritten + 4);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref string? value)
|
||||
{
|
||||
if (!reader.DangerousTryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
value = "";
|
||||
return;
|
||||
}
|
||||
|
||||
var byteLength = length * 2;
|
||||
|
||||
// security, require to check length
|
||||
if (decompressionSizeLimit < byteLength)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowDecompressionSizeLimitExceeded(decompressionSizeLimit, byteLength);
|
||||
}
|
||||
|
||||
reader.GetRemainingSource(out var singleSource, out var remainingSource);
|
||||
|
||||
var consumedBox = threadStaticConsumedBox;
|
||||
if (consumedBox == null)
|
||||
{
|
||||
consumedBox = threadStaticConsumedBox = new StrongBox<int>();
|
||||
}
|
||||
else
|
||||
{
|
||||
consumedBox.Value = 0;
|
||||
}
|
||||
|
||||
if (singleSource.Length != 0)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* p = singleSource)
|
||||
{
|
||||
value = string.Create(length, ((IntPtr)p, singleSource.Length, byteLength, consumedBox), static (stringSpan, state) =>
|
||||
{
|
||||
var src = MemoryMarshal.CreateSpan(ref Unsafe.AsRef<byte>((byte*)state.Item1), state.Item2);
|
||||
var destination = MemoryMarshal.AsBytes(stringSpan);
|
||||
|
||||
using var decoder = new BrotliDecoder();
|
||||
var status = decoder.Decompress(src, destination, out var bytesConsumed, out var bytesWritten);
|
||||
if (status != OperationStatus.Done)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowCompressionFailed(status);
|
||||
}
|
||||
if (bytesWritten != state.byteLength)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowCompressionFailed();
|
||||
}
|
||||
|
||||
state.consumedBox.Value = bytesConsumed;
|
||||
});
|
||||
reader.Advance(consumedBox.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = string.Create(length, (remainingSource, remainingSource.Length, byteLength, consumedBox), static (stringSpan, state) =>
|
||||
{
|
||||
var destination = MemoryMarshal.AsBytes(stringSpan);
|
||||
|
||||
using var decoder = new BrotliDecoder();
|
||||
|
||||
var consumed = 0;
|
||||
OperationStatus status = OperationStatus.DestinationTooSmall;
|
||||
foreach (var item in state.remainingSource)
|
||||
{
|
||||
status = decoder.Decompress(item.Span, destination, out var bytesConsumed, out var bytesWritten);
|
||||
consumed += bytesConsumed;
|
||||
|
||||
destination = destination.Slice(bytesWritten);
|
||||
if (status == OperationStatus.Done)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (status != OperationStatus.Done)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowCompressionFailed(status);
|
||||
}
|
||||
|
||||
state.consumedBox.Value = consumed;
|
||||
});
|
||||
reader.Advance(consumedBox.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07af9b01eb2a94d439eba905a7b72deb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Buffers;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
[Preserve]
|
||||
public sealed class TimeZoneInfoFormatter : MemoryPackFormatter<TimeZoneInfo>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref TimeZoneInfo? value)
|
||||
{
|
||||
writer.WriteString(value?.ToSerializedString());
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref TimeZoneInfo? value)
|
||||
{
|
||||
var source = reader.ReadString();
|
||||
if (source == null)
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
value = TimeZoneInfo.FromSerializedString(source);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ec2daec89486cc439549ac3139a872a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,657 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
internal static class TupleFormatterTypes
|
||||
{
|
||||
public static readonly Dictionary<Type, Type> TupleFormatters = new Dictionary<Type, Type>(16)
|
||||
{
|
||||
{ typeof(Tuple<>), typeof(TupleFormatter<>) },
|
||||
{ typeof(ValueTuple<>), typeof(ValueTupleFormatter<>) },
|
||||
{ typeof(Tuple<,>), typeof(TupleFormatter<,>) },
|
||||
{ typeof(ValueTuple<,>), typeof(ValueTupleFormatter<,>) },
|
||||
{ typeof(Tuple<,,>), typeof(TupleFormatter<,,>) },
|
||||
{ typeof(ValueTuple<,,>), typeof(ValueTupleFormatter<,,>) },
|
||||
{ typeof(Tuple<,,,>), typeof(TupleFormatter<,,,>) },
|
||||
{ typeof(ValueTuple<,,,>), typeof(ValueTupleFormatter<,,,>) },
|
||||
{ typeof(Tuple<,,,,>), typeof(TupleFormatter<,,,,>) },
|
||||
{ typeof(ValueTuple<,,,,>), typeof(ValueTupleFormatter<,,,,>) },
|
||||
{ typeof(Tuple<,,,,,>), typeof(TupleFormatter<,,,,,>) },
|
||||
{ typeof(ValueTuple<,,,,,>), typeof(ValueTupleFormatter<,,,,,>) },
|
||||
{ typeof(Tuple<,,,,,,>), typeof(TupleFormatter<,,,,,,>) },
|
||||
{ typeof(ValueTuple<,,,,,,>), typeof(ValueTupleFormatter<,,,,,,>) },
|
||||
{ typeof(Tuple<,,,,,,,>), typeof(TupleFormatter<,,,,,,,>) },
|
||||
{ typeof(ValueTuple<,,,,,,,>), typeof(ValueTupleFormatter<,,,,,,,>) },
|
||||
};
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class TupleFormatter<T1> : MemoryPackFormatter<Tuple<T1?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref Tuple<T1?>? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteObjectHeader(1);
|
||||
writer.WriteValue(value.Item1);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref Tuple<T1?>? value)
|
||||
{
|
||||
if (!reader.TryReadObjectHeader(out var count))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (count != 1) MemoryPackSerializationException.ThrowInvalidPropertyCount(1, count);
|
||||
|
||||
value = new Tuple<T1?>(
|
||||
reader.ReadValue<T1>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class TupleFormatter<T1, T2> : MemoryPackFormatter<Tuple<T1?, T2?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref Tuple<T1?, T2?>? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteObjectHeader(2);
|
||||
writer.WriteValue(value.Item1);
|
||||
writer.WriteValue(value.Item2);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref Tuple<T1?, T2?>? value)
|
||||
{
|
||||
if (!reader.TryReadObjectHeader(out var count))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (count != 2) MemoryPackSerializationException.ThrowInvalidPropertyCount(2, count);
|
||||
|
||||
value = new Tuple<T1?, T2?>(
|
||||
reader.ReadValue<T1>(),
|
||||
reader.ReadValue<T2>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class TupleFormatter<T1, T2, T3> : MemoryPackFormatter<Tuple<T1?, T2?, T3?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref Tuple<T1?, T2?, T3?>? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteObjectHeader(3);
|
||||
writer.WriteValue(value.Item1);
|
||||
writer.WriteValue(value.Item2);
|
||||
writer.WriteValue(value.Item3);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref Tuple<T1?, T2?, T3?>? value)
|
||||
{
|
||||
if (!reader.TryReadObjectHeader(out var count))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (count != 3) MemoryPackSerializationException.ThrowInvalidPropertyCount(3, count);
|
||||
|
||||
value = new Tuple<T1?, T2?, T3?>(
|
||||
reader.ReadValue<T1>(),
|
||||
reader.ReadValue<T2>(),
|
||||
reader.ReadValue<T3>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class TupleFormatter<T1, T2, T3, T4> : MemoryPackFormatter<Tuple<T1?, T2?, T3?, T4?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref Tuple<T1?, T2?, T3?, T4?>? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteObjectHeader(4);
|
||||
writer.WriteValue(value.Item1);
|
||||
writer.WriteValue(value.Item2);
|
||||
writer.WriteValue(value.Item3);
|
||||
writer.WriteValue(value.Item4);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref Tuple<T1?, T2?, T3?, T4?>? value)
|
||||
{
|
||||
if (!reader.TryReadObjectHeader(out var count))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (count != 4) MemoryPackSerializationException.ThrowInvalidPropertyCount(4, count);
|
||||
|
||||
value = new Tuple<T1?, T2?, T3?, T4?>(
|
||||
reader.ReadValue<T1>(),
|
||||
reader.ReadValue<T2>(),
|
||||
reader.ReadValue<T3>(),
|
||||
reader.ReadValue<T4>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class TupleFormatter<T1, T2, T3, T4, T5> : MemoryPackFormatter<Tuple<T1?, T2?, T3?, T4?, T5?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref Tuple<T1?, T2?, T3?, T4?, T5?>? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteObjectHeader(5);
|
||||
writer.WriteValue(value.Item1);
|
||||
writer.WriteValue(value.Item2);
|
||||
writer.WriteValue(value.Item3);
|
||||
writer.WriteValue(value.Item4);
|
||||
writer.WriteValue(value.Item5);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref Tuple<T1?, T2?, T3?, T4?, T5?>? value)
|
||||
{
|
||||
if (!reader.TryReadObjectHeader(out var count))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (count != 5) MemoryPackSerializationException.ThrowInvalidPropertyCount(5, count);
|
||||
|
||||
value = new Tuple<T1?, T2?, T3?, T4?, T5?>(
|
||||
reader.ReadValue<T1>(),
|
||||
reader.ReadValue<T2>(),
|
||||
reader.ReadValue<T3>(),
|
||||
reader.ReadValue<T4>(),
|
||||
reader.ReadValue<T5>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class TupleFormatter<T1, T2, T3, T4, T5, T6> : MemoryPackFormatter<Tuple<T1?, T2?, T3?, T4?, T5?, T6?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref Tuple<T1?, T2?, T3?, T4?, T5?, T6?>? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteObjectHeader(6);
|
||||
writer.WriteValue(value.Item1);
|
||||
writer.WriteValue(value.Item2);
|
||||
writer.WriteValue(value.Item3);
|
||||
writer.WriteValue(value.Item4);
|
||||
writer.WriteValue(value.Item5);
|
||||
writer.WriteValue(value.Item6);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref Tuple<T1?, T2?, T3?, T4?, T5?, T6?>? value)
|
||||
{
|
||||
if (!reader.TryReadObjectHeader(out var count))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (count != 6) MemoryPackSerializationException.ThrowInvalidPropertyCount(6, count);
|
||||
|
||||
value = new Tuple<T1?, T2?, T3?, T4?, T5?, T6?>(
|
||||
reader.ReadValue<T1>(),
|
||||
reader.ReadValue<T2>(),
|
||||
reader.ReadValue<T3>(),
|
||||
reader.ReadValue<T4>(),
|
||||
reader.ReadValue<T5>(),
|
||||
reader.ReadValue<T6>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class TupleFormatter<T1, T2, T3, T4, T5, T6, T7> : MemoryPackFormatter<Tuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref Tuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?>? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteObjectHeader(7);
|
||||
writer.WriteValue(value.Item1);
|
||||
writer.WriteValue(value.Item2);
|
||||
writer.WriteValue(value.Item3);
|
||||
writer.WriteValue(value.Item4);
|
||||
writer.WriteValue(value.Item5);
|
||||
writer.WriteValue(value.Item6);
|
||||
writer.WriteValue(value.Item7);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref Tuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?>? value)
|
||||
{
|
||||
if (!reader.TryReadObjectHeader(out var count))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (count != 7) MemoryPackSerializationException.ThrowInvalidPropertyCount(7, count);
|
||||
|
||||
value = new Tuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?>(
|
||||
reader.ReadValue<T1>(),
|
||||
reader.ReadValue<T2>(),
|
||||
reader.ReadValue<T3>(),
|
||||
reader.ReadValue<T4>(),
|
||||
reader.ReadValue<T5>(),
|
||||
reader.ReadValue<T6>(),
|
||||
reader.ReadValue<T7>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class TupleFormatter<T1, T2, T3, T4, T5, T6, T7, TRest> : MemoryPackFormatter<Tuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?, TRest>>
|
||||
where TRest : notnull
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref Tuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?, TRest>? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteObjectHeader(8);
|
||||
writer.WriteValue(value.Item1);
|
||||
writer.WriteValue(value.Item2);
|
||||
writer.WriteValue(value.Item3);
|
||||
writer.WriteValue(value.Item4);
|
||||
writer.WriteValue(value.Item5);
|
||||
writer.WriteValue(value.Item6);
|
||||
writer.WriteValue(value.Item7);
|
||||
writer.WriteValue(value.Rest);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref Tuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?, TRest>? value)
|
||||
{
|
||||
if (!reader.TryReadObjectHeader(out var count))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (count != 8) MemoryPackSerializationException.ThrowInvalidPropertyCount(8, count);
|
||||
|
||||
value = new Tuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?, TRest>(
|
||||
reader.ReadValue<T1>(),
|
||||
reader.ReadValue<T2>(),
|
||||
reader.ReadValue<T3>(),
|
||||
reader.ReadValue<T4>(),
|
||||
reader.ReadValue<T5>(),
|
||||
reader.ReadValue<T6>(),
|
||||
reader.ReadValue<T7>(),
|
||||
reader.ReadValue<TRest>()!
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Preserve]
|
||||
public sealed class ValueTupleFormatter<T1> : MemoryPackFormatter<ValueTuple<T1?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref ValueTuple<T1?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?>>())
|
||||
{
|
||||
writer.DangerousWriteUnmanaged(value);
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteValue(value.Item1);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref ValueTuple<T1?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?>>())
|
||||
{
|
||||
reader.DangerousReadUnmanaged(out value);
|
||||
return;
|
||||
}
|
||||
|
||||
value = new ValueTuple<T1?>(
|
||||
reader.ReadValue<T1>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class ValueTupleFormatter<T1, T2> : MemoryPackFormatter<ValueTuple<T1?, T2?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref ValueTuple<T1?, T2?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?, T2?>>())
|
||||
{
|
||||
writer.DangerousWriteUnmanaged(value);
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteValue(value.Item1);
|
||||
writer.WriteValue(value.Item2);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref ValueTuple<T1?, T2?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?, T2?>>())
|
||||
{
|
||||
reader.DangerousReadUnmanaged(out value);
|
||||
return;
|
||||
}
|
||||
|
||||
value = new ValueTuple<T1?, T2?>(
|
||||
reader.ReadValue<T1>(),
|
||||
reader.ReadValue<T2>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class ValueTupleFormatter<T1, T2, T3> : MemoryPackFormatter<ValueTuple<T1?, T2?, T3?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref ValueTuple<T1?, T2?, T3?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?, T2?, T3?>>())
|
||||
{
|
||||
writer.DangerousWriteUnmanaged(value);
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteValue(value.Item1);
|
||||
writer.WriteValue(value.Item2);
|
||||
writer.WriteValue(value.Item3);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref ValueTuple<T1?, T2?, T3?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?, T2?, T3?>>())
|
||||
{
|
||||
reader.DangerousReadUnmanaged(out value);
|
||||
return;
|
||||
}
|
||||
|
||||
value = new ValueTuple<T1?, T2?, T3?>(
|
||||
reader.ReadValue<T1>(),
|
||||
reader.ReadValue<T2>(),
|
||||
reader.ReadValue<T3>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class ValueTupleFormatter<T1, T2, T3, T4> : MemoryPackFormatter<ValueTuple<T1?, T2?, T3?, T4?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref ValueTuple<T1?, T2?, T3?, T4?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?, T2?, T3?, T4?>>())
|
||||
{
|
||||
writer.DangerousWriteUnmanaged(value);
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteValue(value.Item1);
|
||||
writer.WriteValue(value.Item2);
|
||||
writer.WriteValue(value.Item3);
|
||||
writer.WriteValue(value.Item4);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref ValueTuple<T1?, T2?, T3?, T4?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?, T2?, T3?, T4?>>())
|
||||
{
|
||||
reader.DangerousReadUnmanaged(out value);
|
||||
return;
|
||||
}
|
||||
|
||||
value = new ValueTuple<T1?, T2?, T3?, T4?>(
|
||||
reader.ReadValue<T1>(),
|
||||
reader.ReadValue<T2>(),
|
||||
reader.ReadValue<T3>(),
|
||||
reader.ReadValue<T4>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class ValueTupleFormatter<T1, T2, T3, T4, T5> : MemoryPackFormatter<ValueTuple<T1?, T2?, T3?, T4?, T5?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref ValueTuple<T1?, T2?, T3?, T4?, T5?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?, T2?, T3?, T4?, T5?>>())
|
||||
{
|
||||
writer.DangerousWriteUnmanaged(value);
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteValue(value.Item1);
|
||||
writer.WriteValue(value.Item2);
|
||||
writer.WriteValue(value.Item3);
|
||||
writer.WriteValue(value.Item4);
|
||||
writer.WriteValue(value.Item5);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref ValueTuple<T1?, T2?, T3?, T4?, T5?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?, T2?, T3?, T4?, T5?>>())
|
||||
{
|
||||
reader.DangerousReadUnmanaged(out value);
|
||||
return;
|
||||
}
|
||||
|
||||
value = new ValueTuple<T1?, T2?, T3?, T4?, T5?>(
|
||||
reader.ReadValue<T1>(),
|
||||
reader.ReadValue<T2>(),
|
||||
reader.ReadValue<T3>(),
|
||||
reader.ReadValue<T4>(),
|
||||
reader.ReadValue<T5>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class ValueTupleFormatter<T1, T2, T3, T4, T5, T6> : MemoryPackFormatter<ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?>>())
|
||||
{
|
||||
writer.DangerousWriteUnmanaged(value);
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteValue(value.Item1);
|
||||
writer.WriteValue(value.Item2);
|
||||
writer.WriteValue(value.Item3);
|
||||
writer.WriteValue(value.Item4);
|
||||
writer.WriteValue(value.Item5);
|
||||
writer.WriteValue(value.Item6);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?>>())
|
||||
{
|
||||
reader.DangerousReadUnmanaged(out value);
|
||||
return;
|
||||
}
|
||||
|
||||
value = new ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?>(
|
||||
reader.ReadValue<T1>(),
|
||||
reader.ReadValue<T2>(),
|
||||
reader.ReadValue<T3>(),
|
||||
reader.ReadValue<T4>(),
|
||||
reader.ReadValue<T5>(),
|
||||
reader.ReadValue<T6>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class ValueTupleFormatter<T1, T2, T3, T4, T5, T6, T7> : MemoryPackFormatter<ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?>>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?>>())
|
||||
{
|
||||
writer.DangerousWriteUnmanaged(value);
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteValue(value.Item1);
|
||||
writer.WriteValue(value.Item2);
|
||||
writer.WriteValue(value.Item3);
|
||||
writer.WriteValue(value.Item4);
|
||||
writer.WriteValue(value.Item5);
|
||||
writer.WriteValue(value.Item6);
|
||||
writer.WriteValue(value.Item7);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?>>())
|
||||
{
|
||||
reader.DangerousReadUnmanaged(out value);
|
||||
return;
|
||||
}
|
||||
|
||||
value = new ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?>(
|
||||
reader.ReadValue<T1>(),
|
||||
reader.ReadValue<T2>(),
|
||||
reader.ReadValue<T3>(),
|
||||
reader.ReadValue<T4>(),
|
||||
reader.ReadValue<T5>(),
|
||||
reader.ReadValue<T6>(),
|
||||
reader.ReadValue<T7>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class ValueTupleFormatter<T1, T2, T3, T4, T5, T6, T7, TRest> : MemoryPackFormatter<ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?, TRest>>
|
||||
where TRest : struct
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?, TRest> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?, TRest>>())
|
||||
{
|
||||
writer.DangerousWriteUnmanaged(value);
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteValue(value.Item1);
|
||||
writer.WriteValue(value.Item2);
|
||||
writer.WriteValue(value.Item3);
|
||||
writer.WriteValue(value.Item4);
|
||||
writer.WriteValue(value.Item5);
|
||||
writer.WriteValue(value.Item6);
|
||||
writer.WriteValue(value.Item7);
|
||||
writer.WriteValue(value.Rest);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?, TRest> value)
|
||||
{
|
||||
if (!System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences<ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?, TRest>>())
|
||||
{
|
||||
reader.DangerousReadUnmanaged(out value);
|
||||
return;
|
||||
}
|
||||
|
||||
value = new ValueTuple<T1?, T2?, T3?, T4?, T5?, T6?, T7?, TRest>(
|
||||
reader.ReadValue<T1>(),
|
||||
reader.ReadValue<T2>(),
|
||||
reader.ReadValue<T3>(),
|
||||
reader.ReadValue<T4>(),
|
||||
reader.ReadValue<T5>(),
|
||||
reader.ReadValue<T6>(),
|
||||
reader.ReadValue<T7>(),
|
||||
reader.ReadValue<TRest>()!
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 82746260603df5a45a8369e256a78e75
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
[Preserve]
|
||||
public sealed partial class TypeFormatter : MemoryPackFormatter<Type>
|
||||
{
|
||||
// Remove Version, Culture, PublicKeyToken from AssemblyQualifiedName.
|
||||
// Result will be "TypeName, Assembly"
|
||||
// see:http://msdn.microsoft.com/en-us/library/w3f99sx1.aspx
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
[GeneratedRegex(@", Version=\d+.\d+.\d+.\d+, Culture=[\w-]+, PublicKeyToken=(?:null|[a-f0-9]{16})")]
|
||||
private static partial Regex ShortTypeNameRegex();
|
||||
|
||||
#else
|
||||
|
||||
static readonly Regex _shortTypeNameRegex = new Regex(@", Version=\d+.\d+.\d+.\d+, Culture=[\w-]+, PublicKeyToken=(?:null|[a-f0-9]{16})", RegexOptions.Compiled);
|
||||
static Regex ShortTypeNameRegex() => _shortTypeNameRegex;
|
||||
|
||||
#endif
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref Type? value)
|
||||
{
|
||||
var full = value?.AssemblyQualifiedName;
|
||||
if (full == null)
|
||||
{
|
||||
writer.WriteNullCollectionHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
var shortName = ShortTypeNameRegex().Replace(full, "");
|
||||
writer.WriteString(shortName);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref Type? value)
|
||||
{
|
||||
var typeName = reader.ReadString();
|
||||
if (typeName == null)
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
value = Type.GetType(typeName, throwOnError: true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1f7f7bddb1670c4ea52c7efc399000a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
// for unamanged types( https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/unmanaged-types )
|
||||
// * sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool
|
||||
// * Any enum type
|
||||
// * Any pointer type
|
||||
// * Any user-defined struct type that contains fields of unmanaged types only
|
||||
[Preserve]
|
||||
public sealed class UnmanagedFormatter<T> : MemoryPackFormatter<T>
|
||||
where T : unmanaged
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref T value)
|
||||
{
|
||||
Unsafe.WriteUnaligned(ref writer.GetSpanReference(Unsafe.SizeOf<T>()), value);
|
||||
writer.Advance(Unsafe.SizeOf<T>());
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref T value)
|
||||
{
|
||||
value = Unsafe.ReadUnaligned<T>(ref reader.GetSpanReference(Unsafe.SizeOf<T>()));
|
||||
reader.Advance(Unsafe.SizeOf<T>());
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public sealed class DangerousUnmanagedFormatter<T> : MemoryPackFormatter<T>
|
||||
{
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref T? value)
|
||||
{
|
||||
Unsafe.WriteUnaligned(ref writer.GetSpanReference(Unsafe.SizeOf<T>()), value);
|
||||
writer.Advance(Unsafe.SizeOf<T>());
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref T? value)
|
||||
{
|
||||
value = Unsafe.ReadUnaligned<T>(ref reader.GetSpanReference(Unsafe.SizeOf<T>()));
|
||||
reader.Advance(Unsafe.SizeOf<T>());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87c49cf15480faa4aa13b0027ba10b2b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Buffers;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
[Preserve]
|
||||
public sealed class UriFormatter : MemoryPackFormatter<Uri>
|
||||
{
|
||||
// treat as a string(OriginalString).
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref Uri? value)
|
||||
{
|
||||
writer.WriteString(value?.OriginalString);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref Uri? value)
|
||||
{
|
||||
var str = reader.ReadString();
|
||||
if (str == null)
|
||||
{
|
||||
value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = new Uri(str, UriKind.RelativeOrAbsolute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 815be7f2c6d469548b382f4531c8d4d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
|
||||
namespace MemoryPack.Formatters {
|
||||
|
||||
[Preserve]
|
||||
public sealed class VersionFormatter : MemoryPackFormatter<Version>
|
||||
{
|
||||
// Serialize as [Major, Minor, Build, Revision]
|
||||
|
||||
[Preserve]
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref Version? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteUnmanagedWithObjectHeader(4, value.Major, value.Minor, value.Build, value.Revision);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref Version? value)
|
||||
{
|
||||
if (!reader.TryReadObjectHeader(out var count))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (count != 4) MemoryPackSerializationException.ThrowInvalidPropertyCount(4, count);
|
||||
|
||||
reader.ReadUnmanaged(out int major, out int minor, out int build, out int revision);
|
||||
|
||||
// when use new Version(major, minor), build and revision will be -1, it can not use constructor.
|
||||
if (revision == -1)
|
||||
{
|
||||
if (build == -1)
|
||||
{
|
||||
value = new Version(major, minor);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = new Version(major, minor, build);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = new Version(major, minor, build, revision);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 65775f54fba192b47a6014ccdccf27ed
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Internal;
|
||||
using System.Buffers;
|
||||
|
||||
namespace MemoryPack {
|
||||
|
||||
[Preserve]
|
||||
public interface IMemoryPackFormatter
|
||||
{
|
||||
[Preserve]
|
||||
void Serialize(ref MemoryPackWriter writer, ref object? value)
|
||||
#if NET7_0_OR_GREATER
|
||||
;
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
[Preserve]
|
||||
void Deserialize(ref MemoryPackReader reader, ref object? value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public interface IMemoryPackFormatter<T>
|
||||
{
|
||||
[Preserve]
|
||||
void Serialize(ref MemoryPackWriter writer, ref T? value)
|
||||
#if NET7_0_OR_GREATER
|
||||
;
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
[Preserve]
|
||||
void Deserialize(ref MemoryPackReader reader, ref T? value);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
public abstract class MemoryPackFormatter<T> : IMemoryPackFormatter<T>, IMemoryPackFormatter
|
||||
{
|
||||
[Preserve]
|
||||
public abstract void Serialize(ref MemoryPackWriter writer, ref T? value)
|
||||
#if NET7_0_OR_GREATER
|
||||
;
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
[Preserve]
|
||||
public abstract void Deserialize(ref MemoryPackReader reader, ref T? value);
|
||||
|
||||
[Preserve]
|
||||
void IMemoryPackFormatter.Serialize(ref MemoryPackWriter writer, ref object? value)
|
||||
{
|
||||
var v = (value == null)
|
||||
? default(T?)
|
||||
: (T?)value;
|
||||
Serialize(ref writer, ref v);
|
||||
}
|
||||
|
||||
[Preserve]
|
||||
void IMemoryPackFormatter.Deserialize(ref MemoryPackReader reader, ref object? value)
|
||||
{
|
||||
var v = (value == null)
|
||||
? default(T?)
|
||||
: (T?)value;
|
||||
Deserialize(ref reader, ref v);
|
||||
value = v;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b17111635233244459e4c2668df6e763
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using System.Buffers;
|
||||
|
||||
namespace MemoryPack {
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
public interface IFixedSizeMemoryPackable
|
||||
{
|
||||
static abstract int Size { get; }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public interface IMemoryPackFormatterRegister
|
||||
{
|
||||
#if NET7_0_OR_GREATER
|
||||
static abstract void RegisterFormatter();
|
||||
#endif
|
||||
}
|
||||
|
||||
public interface IMemoryPackable<T> : IMemoryPackFormatterRegister
|
||||
{
|
||||
// note: serialize parameter should be `ref readonly` but current lang spec can not.
|
||||
// see proposal https://github.com/dotnet/csharplang/issues/6010
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
static abstract void Serialize(ref MemoryPackWriter writer, ref T? value)
|
||||
;
|
||||
static abstract void Deserialize(ref MemoryPackReader reader, ref T? value);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53c6fb0170766704aa3ec4b1aedf050d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f8ccfb431cbe7f4299e0245f9c74309
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
namespace MemoryPack.Internal {
|
||||
|
||||
internal static class EnumerableExtensions
|
||||
{
|
||||
public static bool TryGetNonEnumeratedCountEx<T>(this IEnumerable<T> value, out int count)
|
||||
{
|
||||
// TryGetNonEnumeratedCount is not check IReadOnlyCollection<T> so add check manually.
|
||||
// https://github.com/dotnet/runtime/issues/54764
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
if (value.TryGetNonEnumeratedCount(out count))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
count = 0;
|
||||
if (value is ICollection<T> collection)
|
||||
{
|
||||
count = collection.Count;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (value is IReadOnlyCollection<T> readOnlyCollection)
|
||||
{
|
||||
count = readOnlyCollection.Count;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b7de601a63709940b09c18eb34cf772
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using System.Buffers;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MemoryPack.Internal {
|
||||
|
||||
internal struct FixedArrayBufferWriter : IBufferWriter<byte>
|
||||
{
|
||||
byte[] buffer;
|
||||
int written;
|
||||
|
||||
public FixedArrayBufferWriter(byte[] buffer)
|
||||
{
|
||||
this.buffer = buffer;
|
||||
this.written = 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Advance(int count)
|
||||
{
|
||||
this.written += count;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Memory<byte> GetMemory(int sizeHint = 0)
|
||||
{
|
||||
var memory = buffer.AsMemory(written);
|
||||
if (memory.Length >= sizeHint)
|
||||
{
|
||||
return memory;
|
||||
}
|
||||
|
||||
MemoryPackSerializationException.ThrowMessage("Requested invalid sizeHint.");
|
||||
return memory;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Span<byte> GetSpan(int sizeHint = 0)
|
||||
{
|
||||
var span = buffer.AsSpan(written);
|
||||
if (span.Length >= sizeHint)
|
||||
{
|
||||
return span;
|
||||
}
|
||||
|
||||
MemoryPackSerializationException.ThrowMessage("Requested invalid sizeHint.");
|
||||
return span;
|
||||
}
|
||||
|
||||
public byte[] GetFilledBuffer()
|
||||
{
|
||||
if (written != buffer.Length)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowMessage("Not filled buffer.");
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61f475a704e250d4ab0dd882130e9fdd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MemoryPack.Internal {
|
||||
|
||||
internal static class MathEx
|
||||
{
|
||||
const int ArrayMexLength = 0x7FFFFFC7;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int NewArrayCapacity(int size)
|
||||
{
|
||||
var newSize = unchecked(size * 2);
|
||||
if ((uint)newSize > ArrayMexLength)
|
||||
{
|
||||
newSize = ArrayMexLength;
|
||||
}
|
||||
return newSize;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 927c0eadb944275499836693dc80f88b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
#if !NET7_0_OR_GREATER
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MemoryPack.Internal {
|
||||
|
||||
internal static class MemoryMarshalEx
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ref T GetArrayDataReference<T>(T[] array)
|
||||
{
|
||||
return ref MemoryMarshal.GetReference(array.AsSpan());
|
||||
}
|
||||
|
||||
// GC
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T[] AllocateUninitializedArray<T>(int length, bool pinned = false)
|
||||
{
|
||||
return new T[length];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2909cb9ffb605ae47b659f8140c62ca9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
namespace MemoryPack.Internal {
|
||||
|
||||
// Preserve for Unity IL2CPP(internal but used for code generator)
|
||||
|
||||
public sealed class PreserveAttribute : System.Attribute
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d985418ff3c30b2429f7cdc878e0ddf9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,395 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MemoryPack.Internal {
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
using static GC;
|
||||
using static MemoryMarshal;
|
||||
#else
|
||||
using static MemoryPack.Internal.MemoryMarshalEx;
|
||||
#endif
|
||||
|
||||
// internal but used by generator code
|
||||
|
||||
public static class ReusableLinkedArrayBufferWriterPool
|
||||
{
|
||||
static readonly ConcurrentQueue<ReusableLinkedArrayBufferWriter> queue = new ConcurrentQueue<ReusableLinkedArrayBufferWriter>();
|
||||
|
||||
public static ReusableLinkedArrayBufferWriter Rent()
|
||||
{
|
||||
if (queue.TryDequeue(out var writer))
|
||||
{
|
||||
return writer;
|
||||
}
|
||||
return new ReusableLinkedArrayBufferWriter(useFirstBuffer: false, pinned: false); // does not cache firstBuffer
|
||||
}
|
||||
|
||||
public static void Return(ReusableLinkedArrayBufferWriter writer)
|
||||
{
|
||||
writer.Reset();
|
||||
queue.Enqueue(writer);
|
||||
}
|
||||
}
|
||||
|
||||
// This class has large buffer so should cache [ThreadStatic] or Pool.
|
||||
public sealed class ReusableLinkedArrayBufferWriter : IBufferWriter<byte>
|
||||
{
|
||||
const int InitialBufferSize = 262144; // 256K(32768, 65536, 131072, 262144)
|
||||
static readonly byte[] noUseFirstBufferSentinel = new byte[0];
|
||||
|
||||
List<BufferSegment> buffers; // add freezed buffer.
|
||||
|
||||
byte[] firstBuffer; // cache firstBuffer to avoid call ArrayPoo.Rent/Return
|
||||
int firstBufferWritten;
|
||||
|
||||
BufferSegment current;
|
||||
int nextBufferSize;
|
||||
|
||||
int totalWritten;
|
||||
|
||||
public int TotalWritten => totalWritten;
|
||||
bool UseFirstBuffer => firstBuffer != noUseFirstBufferSentinel;
|
||||
|
||||
public ReusableLinkedArrayBufferWriter(bool useFirstBuffer, bool pinned)
|
||||
{
|
||||
this.buffers = new List<BufferSegment>();
|
||||
this.firstBuffer = useFirstBuffer
|
||||
? AllocateUninitializedArray<byte>(InitialBufferSize, pinned)
|
||||
: noUseFirstBufferSentinel;
|
||||
this.firstBufferWritten = 0;
|
||||
this.current = default;
|
||||
this.nextBufferSize = InitialBufferSize;
|
||||
this.totalWritten = 0;
|
||||
}
|
||||
|
||||
public byte[] DangerousGetFirstBuffer() => firstBuffer;
|
||||
|
||||
public Memory<byte> GetMemory(int sizeHint = 0)
|
||||
{
|
||||
// MemoryPack don't use GetMemory.
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public Span<byte> GetSpan(int sizeHint = 0)
|
||||
{
|
||||
if (current.IsNull)
|
||||
{
|
||||
// use firstBuffer
|
||||
var free = firstBuffer.Length - firstBufferWritten;
|
||||
if (free != 0 && sizeHint <= free)
|
||||
{
|
||||
return firstBuffer.AsSpan(firstBufferWritten);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var buffer = current.FreeBuffer;
|
||||
if (buffer.Length > sizeHint)
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
BufferSegment next;
|
||||
if (sizeHint <= nextBufferSize)
|
||||
{
|
||||
next = new BufferSegment(nextBufferSize);
|
||||
nextBufferSize = MathEx.NewArrayCapacity(nextBufferSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
next = new BufferSegment(sizeHint);
|
||||
}
|
||||
|
||||
if (current.WrittenCount != 0)
|
||||
{
|
||||
buffers.Add(current);
|
||||
}
|
||||
current = next;
|
||||
return next.FreeBuffer;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Advance(int count)
|
||||
{
|
||||
if (current.IsNull)
|
||||
{
|
||||
firstBufferWritten += count;
|
||||
}
|
||||
else
|
||||
{
|
||||
current.Advance(count);
|
||||
}
|
||||
totalWritten += count;
|
||||
}
|
||||
|
||||
public byte[] ToArrayAndReset()
|
||||
{
|
||||
if (totalWritten == 0) return Array.Empty<byte>();
|
||||
|
||||
var result = AllocateUninitializedArray<byte>(totalWritten);
|
||||
var dest = result.AsSpan();
|
||||
|
||||
if (UseFirstBuffer)
|
||||
{
|
||||
firstBuffer.AsSpan(0, firstBufferWritten).CopyTo(dest);
|
||||
dest = dest.Slice(firstBufferWritten);
|
||||
}
|
||||
|
||||
if (buffers.Count > 0)
|
||||
{
|
||||
#if NET7_0_OR_GREATER
|
||||
foreach (ref var item in CollectionsMarshal.AsSpan(buffers))
|
||||
#else
|
||||
foreach (var item in buffers)
|
||||
#endif
|
||||
{
|
||||
item.WrittenBuffer.CopyTo(dest);
|
||||
dest = dest.Slice(item.WrittenCount);
|
||||
item.Clear(); // reset buffer-segment in this loop to avoid iterate twice for Reset
|
||||
}
|
||||
}
|
||||
|
||||
if (!current.IsNull)
|
||||
{
|
||||
current.WrittenBuffer.CopyTo(dest);
|
||||
current.Clear();
|
||||
}
|
||||
|
||||
ResetCore();
|
||||
return result;
|
||||
}
|
||||
|
||||
public void WriteToAndReset(ref MemoryPackWriter writer)
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
{
|
||||
if (totalWritten == 0) return;
|
||||
|
||||
if (UseFirstBuffer)
|
||||
{
|
||||
ref var spanRef = ref writer.GetSpanReference(firstBufferWritten);
|
||||
firstBuffer.AsSpan(0, firstBufferWritten).CopyTo(MemoryMarshal.CreateSpan(ref spanRef, firstBufferWritten));
|
||||
writer.Advance(firstBufferWritten);
|
||||
}
|
||||
|
||||
if (buffers.Count > 0)
|
||||
{
|
||||
#if NET7_0_OR_GREATER
|
||||
foreach (ref var item in CollectionsMarshal.AsSpan(buffers))
|
||||
#else
|
||||
foreach (var item in buffers)
|
||||
#endif
|
||||
{
|
||||
ref var spanRef = ref writer.GetSpanReference(item.WrittenCount);
|
||||
item.WrittenBuffer.CopyTo(MemoryMarshal.CreateSpan(ref spanRef, item.WrittenCount));
|
||||
writer.Advance(item.WrittenCount);
|
||||
item.Clear(); // reset
|
||||
}
|
||||
}
|
||||
|
||||
if (!current.IsNull)
|
||||
{
|
||||
ref var spanRef = ref writer.GetSpanReference(current.WrittenCount);
|
||||
current.WrittenBuffer.CopyTo(MemoryMarshal.CreateSpan(ref spanRef, current.WrittenCount));
|
||||
writer.Advance(current.WrittenCount);
|
||||
current.Clear();
|
||||
}
|
||||
|
||||
ResetCore();
|
||||
}
|
||||
|
||||
public async ValueTask WriteToAndResetAsync(Stream stream, CancellationToken cancellationToken)
|
||||
{
|
||||
if (totalWritten == 0) return;
|
||||
|
||||
if (UseFirstBuffer)
|
||||
{
|
||||
await stream.WriteAsync(firstBuffer.AsMemory(0, firstBufferWritten), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (buffers.Count > 0)
|
||||
{
|
||||
foreach (var item in buffers)
|
||||
{
|
||||
await stream.WriteAsync(item.WrittenMemory, cancellationToken).ConfigureAwait(false);
|
||||
item.Clear(); // reset
|
||||
}
|
||||
}
|
||||
|
||||
if (!current.IsNull)
|
||||
{
|
||||
await stream.WriteAsync(current.WrittenMemory, cancellationToken).ConfigureAwait(false);
|
||||
current.Clear();
|
||||
}
|
||||
|
||||
ResetCore();
|
||||
}
|
||||
|
||||
public Enumerator GetEnumerator()
|
||||
{
|
||||
return new Enumerator(this);
|
||||
}
|
||||
|
||||
// reset without list's BufferSegment element
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void ResetCore()
|
||||
{
|
||||
firstBufferWritten = 0;
|
||||
buffers.Clear();
|
||||
totalWritten = 0;
|
||||
current = default;
|
||||
nextBufferSize = InitialBufferSize;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Reset()
|
||||
{
|
||||
if (totalWritten == 0) return;
|
||||
#if NET7_0_OR_GREATER
|
||||
foreach (ref var item in CollectionsMarshal.AsSpan(buffers))
|
||||
#else
|
||||
foreach (var item in buffers)
|
||||
#endif
|
||||
{
|
||||
item.Clear();
|
||||
}
|
||||
current.Clear();
|
||||
ResetCore();
|
||||
}
|
||||
|
||||
public struct Enumerator : IEnumerator<Memory<byte>>
|
||||
{
|
||||
ReusableLinkedArrayBufferWriter parent;
|
||||
State state;
|
||||
Memory<byte> current;
|
||||
List<BufferSegment>.Enumerator buffersEnumerator;
|
||||
|
||||
public Enumerator(ReusableLinkedArrayBufferWriter parent)
|
||||
{
|
||||
this.parent = parent;
|
||||
this.state = default;
|
||||
this.current = default;
|
||||
this.buffersEnumerator = default;
|
||||
}
|
||||
|
||||
public Memory<byte> Current => current;
|
||||
|
||||
object IEnumerator.Current => throw new NotSupportedException();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (state == State.FirstBuffer)
|
||||
{
|
||||
state = State.BuffersInit;
|
||||
|
||||
if (parent.UseFirstBuffer)
|
||||
{
|
||||
current = parent.firstBuffer.AsMemory(0, parent.firstBufferWritten);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == State.BuffersInit)
|
||||
{
|
||||
state = State.BuffersIterate;
|
||||
|
||||
buffersEnumerator = parent.buffers.GetEnumerator();
|
||||
}
|
||||
|
||||
if (state == State.BuffersIterate)
|
||||
{
|
||||
if (buffersEnumerator.MoveNext())
|
||||
{
|
||||
current = buffersEnumerator.Current.WrittenMemory;
|
||||
return true;
|
||||
}
|
||||
|
||||
buffersEnumerator.Dispose();
|
||||
state = State.Current;
|
||||
}
|
||||
|
||||
if (state == State.Current)
|
||||
{
|
||||
state = State.End;
|
||||
|
||||
current = parent.current.WrittenMemory;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
enum State
|
||||
{
|
||||
FirstBuffer,
|
||||
BuffersInit,
|
||||
BuffersIterate,
|
||||
Current,
|
||||
End
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal struct BufferSegment
|
||||
{
|
||||
byte[] buffer;
|
||||
int written;
|
||||
|
||||
public bool IsNull => buffer == null;
|
||||
|
||||
public int WrittenCount => written;
|
||||
public Span<byte> WrittenBuffer => buffer.AsSpan(0, written);
|
||||
public Memory<byte> WrittenMemory => buffer.AsMemory(0, written);
|
||||
public Span<byte> FreeBuffer => buffer.AsSpan(written);
|
||||
|
||||
public BufferSegment(int size)
|
||||
{
|
||||
buffer = ArrayPool<byte>.Shared.Rent(size);
|
||||
written = 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Advance(int count)
|
||||
{
|
||||
written += count;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Clear()
|
||||
{
|
||||
if (buffer != null)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(buffer);
|
||||
}
|
||||
buffer = null!;
|
||||
written = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42122ccd6d229c5478197bd7fbce99d0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using System.Buffers;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MemoryPack.Internal {
|
||||
|
||||
internal static class ReusableReadOnlySequenceBuilderPool
|
||||
{
|
||||
static readonly ConcurrentQueue<ReusableReadOnlySequenceBuilder> queue = new();
|
||||
|
||||
public static ReusableReadOnlySequenceBuilder Rent()
|
||||
{
|
||||
if (queue.TryDequeue(out var builder))
|
||||
{
|
||||
return builder;
|
||||
}
|
||||
return new ReusableReadOnlySequenceBuilder();
|
||||
}
|
||||
|
||||
public static void Return(ReusableReadOnlySequenceBuilder builder)
|
||||
{
|
||||
builder.Reset();
|
||||
queue.Enqueue(builder);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ReusableReadOnlySequenceBuilder
|
||||
{
|
||||
readonly Stack<Segment> segmentPool;
|
||||
readonly List<Segment> list;
|
||||
|
||||
public ReusableReadOnlySequenceBuilder()
|
||||
{
|
||||
list = new();
|
||||
segmentPool = new Stack<Segment>();
|
||||
}
|
||||
|
||||
public void Add(ReadOnlyMemory<byte> buffer, bool returnToPool)
|
||||
{
|
||||
if (!segmentPool.TryPop(out var segment))
|
||||
{
|
||||
segment = new Segment();
|
||||
}
|
||||
|
||||
segment.SetBuffer(buffer, returnToPool);
|
||||
list.Add(segment);
|
||||
}
|
||||
|
||||
public bool TryGetSingleMemory(out ReadOnlyMemory<byte> memory)
|
||||
{
|
||||
if (list.Count == 1)
|
||||
{
|
||||
memory = list[0].Memory;
|
||||
return true;
|
||||
}
|
||||
memory = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
public ReadOnlySequence<byte> Build()
|
||||
{
|
||||
if (list.Count == 0)
|
||||
{
|
||||
return ReadOnlySequence<byte>.Empty;
|
||||
}
|
||||
|
||||
if (list.Count == 1)
|
||||
{
|
||||
return new ReadOnlySequence<byte>(list[0].Memory);
|
||||
}
|
||||
|
||||
long running = 0;
|
||||
#if NET7_0_OR_GREATER
|
||||
var span = CollectionsMarshal.AsSpan(list);
|
||||
for (int i = 0; i < span.Length; i++)
|
||||
{
|
||||
var next = i < span.Length - 1 ? span[i + 1] : null;
|
||||
span[i].SetRunningIndexAndNext(running, next);
|
||||
running += span[i].Memory.Length;
|
||||
}
|
||||
var firstSegment = span[0];
|
||||
var lastSegment = span[span.Length - 1];
|
||||
#else
|
||||
var span = list;
|
||||
for (int i = 0; i < span.Count; i++)
|
||||
{
|
||||
var next = i < span.Count - 1 ? span[i + 1] : null;
|
||||
span[i].SetRunningIndexAndNext(running, next);
|
||||
running += span[i].Memory.Length;
|
||||
}
|
||||
var firstSegment = span[0];
|
||||
var lastSegment = span[span.Count - 1];
|
||||
#endif
|
||||
return new ReadOnlySequence<byte>(firstSegment, 0, lastSegment, lastSegment.Memory.Length);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
#if NET7_0_OR_GREATER
|
||||
var span = CollectionsMarshal.AsSpan(list);
|
||||
#else
|
||||
var span = list;
|
||||
#endif
|
||||
foreach (var item in span)
|
||||
{
|
||||
item.Reset();
|
||||
segmentPool.Push(item);
|
||||
}
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
class Segment : ReadOnlySequenceSegment<byte>
|
||||
{
|
||||
bool returnToPool;
|
||||
|
||||
public Segment()
|
||||
{
|
||||
returnToPool = false;
|
||||
}
|
||||
|
||||
public void SetBuffer(ReadOnlyMemory<byte> buffer, bool returnToPool)
|
||||
{
|
||||
Memory = buffer;
|
||||
this.returnToPool = returnToPool;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
if (returnToPool)
|
||||
{
|
||||
if (MemoryMarshal.TryGetArray(Memory, out var segment) && segment.Array != null)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(segment.Array, clearArray: false);
|
||||
}
|
||||
}
|
||||
Memory = default;
|
||||
RunningIndex = 0;
|
||||
Next = null;
|
||||
}
|
||||
|
||||
public void SetRunningIndexAndNext(long runningIndex, Segment? nextSegment)
|
||||
{
|
||||
RunningIndex = runningIndex;
|
||||
Next = nextSegment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b700925f1ee40614ca7c44623074da57
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MemoryPack.Internal {
|
||||
|
||||
internal static class TypeHelpers
|
||||
{
|
||||
static readonly MethodInfo isReferenceOrContainsReferences = typeof(RuntimeHelpers).GetMethod("IsReferenceOrContainsReferences")!;
|
||||
static readonly MethodInfo unsafeSizeOf = typeof(Unsafe).GetMethod("SizeOf")!;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsReferenceOrNullable<T>()
|
||||
{
|
||||
return Cache<T>.IsReferenceOrNullable;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static TypeKind TryGetUnmanagedSZArrayElementSizeOrMemoryPackableFixedSize<T>(out int size)
|
||||
{
|
||||
if (Cache<T>.IsUnmanagedSZArray)
|
||||
{
|
||||
size = Cache<T>.UnmanagedSZArrayElementSize;
|
||||
return TypeKind.UnmanagedSZArray;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Cache<T>.IsFixedSizeMemoryPackable)
|
||||
{
|
||||
size = Cache<T>.MemoryPackableFixedSize;
|
||||
return TypeKind.FixedSizeMemoryPackable;
|
||||
}
|
||||
}
|
||||
|
||||
size = 0;
|
||||
return TypeKind.None;
|
||||
}
|
||||
|
||||
public static bool IsAnonymous(Type type)
|
||||
{
|
||||
return type.Namespace == null
|
||||
&& type.IsSealed
|
||||
&& (type.Name.StartsWith("<>f__AnonymousType", StringComparison.Ordinal)
|
||||
|| type.Name.StartsWith("<>__AnonType", StringComparison.Ordinal)
|
||||
|| type.Name.StartsWith("VB$AnonymousType_", StringComparison.Ordinal))
|
||||
&& type.IsDefined(typeof(CompilerGeneratedAttribute), false);
|
||||
}
|
||||
|
||||
static class Cache<T>
|
||||
{
|
||||
public static bool IsReferenceOrNullable;
|
||||
public static bool IsUnmanagedSZArray;
|
||||
public static int UnmanagedSZArrayElementSize;
|
||||
public static bool IsFixedSizeMemoryPackable = false;
|
||||
public static int MemoryPackableFixedSize = 0;
|
||||
|
||||
static Cache()
|
||||
{
|
||||
try
|
||||
{
|
||||
var type = typeof(T);
|
||||
IsReferenceOrNullable = !type.IsValueType || Nullable.GetUnderlyingType(type) != null;
|
||||
|
||||
if (type.IsSZArray)
|
||||
{
|
||||
var elementType = type.GetElementType();
|
||||
bool containsReference = (bool)(isReferenceOrContainsReferences.MakeGenericMethod(elementType!).Invoke(null, null)!);
|
||||
if (!containsReference)
|
||||
{
|
||||
IsUnmanagedSZArray = true;
|
||||
UnmanagedSZArrayElementSize = (int)unsafeSizeOf.MakeGenericMethod(elementType!).Invoke(null, null)!;
|
||||
}
|
||||
}
|
||||
#if NET7_0_OR_GREATER
|
||||
else
|
||||
{
|
||||
if (typeof(IFixedSizeMemoryPackable).IsAssignableFrom(type))
|
||||
{
|
||||
var prop = type.GetProperty("global::MemoryPack.IFixedSizeMemoryPackable.Size", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
|
||||
if (prop != null)
|
||||
{
|
||||
IsFixedSizeMemoryPackable = true;
|
||||
MemoryPackableFixedSize = (int)prop.GetValue(null)!;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
catch
|
||||
{
|
||||
IsUnmanagedSZArray = false;
|
||||
IsFixedSizeMemoryPackable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal enum TypeKind : byte
|
||||
{
|
||||
None,
|
||||
UnmanagedSZArray,
|
||||
FixedSizeMemoryPackable
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 329bffde10972564f8819da18337cbc8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
namespace MemoryPack {
|
||||
|
||||
public static class MemoryPackCode
|
||||
{
|
||||
// Collection Header
|
||||
// 0~* is length, -1 is null
|
||||
public const int NullCollection = -1;
|
||||
|
||||
// Object/Union Header
|
||||
// 0~249 is member count or tag, 250~254 is unused, 255 is null
|
||||
public const byte WideTag = 250; // for Union, 250 is wide tag
|
||||
public const byte ReferenceId = 250; // for CircularReference, 250 is referenceId marker, next VarInt id reference.
|
||||
|
||||
public const byte Reserved1 = 250;
|
||||
public const byte Reserved2 = 251;
|
||||
public const byte Reserved3 = 252;
|
||||
public const byte Reserved4 = 253;
|
||||
public const byte Reserved5 = 254;
|
||||
public const byte NullObject = 255;
|
||||
|
||||
// predefined, C# compiler optimize byte[] as ReadOnlySpan<byte> property
|
||||
internal static ReadOnlySpan<byte> NullCollectionData => new byte[] { 255, 255, 255, 255 }; // -1
|
||||
internal static ReadOnlySpan<byte> ZeroCollectionData => new byte[] { 0, 0, 0, 0 }; // 0
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 47fb89e30884e9940988b0d3021773f0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Formatters;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Numerics;
|
||||
|
||||
namespace MemoryPack {
|
||||
|
||||
public static partial class MemoryPackFormatterProvider
|
||||
{
|
||||
internal static void RegisterWellKnownTypesFormatters()
|
||||
{
|
||||
Register(new UnmanagedFormatter<SByte>());
|
||||
Register(new UnmanagedArrayFormatter<SByte>());
|
||||
Register(new NullableFormatter<SByte>());
|
||||
Register(new UnmanagedFormatter<Byte>());
|
||||
Register(new UnmanagedArrayFormatter<Byte>());
|
||||
Register(new NullableFormatter<Byte>());
|
||||
Register(new UnmanagedFormatter<Int16>());
|
||||
Register(new UnmanagedArrayFormatter<Int16>());
|
||||
Register(new NullableFormatter<Int16>());
|
||||
Register(new UnmanagedFormatter<UInt16>());
|
||||
Register(new UnmanagedArrayFormatter<UInt16>());
|
||||
Register(new NullableFormatter<UInt16>());
|
||||
Register(new UnmanagedFormatter<Int32>());
|
||||
Register(new UnmanagedArrayFormatter<Int32>());
|
||||
Register(new NullableFormatter<Int32>());
|
||||
Register(new UnmanagedFormatter<UInt32>());
|
||||
Register(new UnmanagedArrayFormatter<UInt32>());
|
||||
Register(new NullableFormatter<UInt32>());
|
||||
Register(new UnmanagedFormatter<Int64>());
|
||||
Register(new UnmanagedArrayFormatter<Int64>());
|
||||
Register(new NullableFormatter<Int64>());
|
||||
Register(new UnmanagedFormatter<UInt64>());
|
||||
Register(new UnmanagedArrayFormatter<UInt64>());
|
||||
Register(new NullableFormatter<UInt64>());
|
||||
Register(new UnmanagedFormatter<Char>());
|
||||
Register(new UnmanagedArrayFormatter<Char>());
|
||||
Register(new NullableFormatter<Char>());
|
||||
Register(new UnmanagedFormatter<Single>());
|
||||
Register(new UnmanagedArrayFormatter<Single>());
|
||||
Register(new NullableFormatter<Single>());
|
||||
Register(new UnmanagedFormatter<Double>());
|
||||
Register(new UnmanagedArrayFormatter<Double>());
|
||||
Register(new NullableFormatter<Double>());
|
||||
Register(new UnmanagedFormatter<Decimal>());
|
||||
Register(new UnmanagedArrayFormatter<Decimal>());
|
||||
Register(new NullableFormatter<Decimal>());
|
||||
Register(new UnmanagedFormatter<Boolean>());
|
||||
Register(new UnmanagedArrayFormatter<Boolean>());
|
||||
Register(new NullableFormatter<Boolean>());
|
||||
Register(new UnmanagedFormatter<IntPtr>());
|
||||
Register(new UnmanagedArrayFormatter<IntPtr>());
|
||||
Register(new NullableFormatter<IntPtr>());
|
||||
Register(new UnmanagedFormatter<UIntPtr>());
|
||||
Register(new UnmanagedArrayFormatter<UIntPtr>());
|
||||
Register(new NullableFormatter<UIntPtr>());
|
||||
Register(new UnmanagedFormatter<DateTime>());
|
||||
Register(new UnmanagedArrayFormatter<DateTime>());
|
||||
Register(new NullableFormatter<DateTime>());
|
||||
Register(new UnmanagedFormatter<DateTimeOffset>());
|
||||
Register(new UnmanagedArrayFormatter<DateTimeOffset>());
|
||||
Register(new NullableFormatter<DateTimeOffset>());
|
||||
Register(new UnmanagedFormatter<TimeSpan>());
|
||||
Register(new UnmanagedArrayFormatter<TimeSpan>());
|
||||
Register(new NullableFormatter<TimeSpan>());
|
||||
Register(new UnmanagedFormatter<Guid>());
|
||||
Register(new UnmanagedArrayFormatter<Guid>());
|
||||
Register(new NullableFormatter<Guid>());
|
||||
Register(new UnmanagedFormatter<Complex>());
|
||||
Register(new UnmanagedArrayFormatter<Complex>());
|
||||
Register(new NullableFormatter<Complex>());
|
||||
Register(new UnmanagedFormatter<Plane>());
|
||||
Register(new UnmanagedArrayFormatter<Plane>());
|
||||
Register(new NullableFormatter<Plane>());
|
||||
Register(new UnmanagedFormatter<Quaternion>());
|
||||
Register(new UnmanagedArrayFormatter<Quaternion>());
|
||||
Register(new NullableFormatter<Quaternion>());
|
||||
Register(new UnmanagedFormatter<Matrix3x2>());
|
||||
Register(new UnmanagedArrayFormatter<Matrix3x2>());
|
||||
Register(new NullableFormatter<Matrix3x2>());
|
||||
Register(new UnmanagedFormatter<Matrix4x4>());
|
||||
Register(new UnmanagedArrayFormatter<Matrix4x4>());
|
||||
Register(new NullableFormatter<Matrix4x4>());
|
||||
Register(new UnmanagedFormatter<Vector2>());
|
||||
Register(new UnmanagedArrayFormatter<Vector2>());
|
||||
Register(new NullableFormatter<Vector2>());
|
||||
Register(new UnmanagedFormatter<Vector3>());
|
||||
Register(new UnmanagedArrayFormatter<Vector3>());
|
||||
Register(new NullableFormatter<Vector3>());
|
||||
Register(new UnmanagedFormatter<Vector4>());
|
||||
Register(new UnmanagedArrayFormatter<Vector4>());
|
||||
Register(new NullableFormatter<Vector4>());
|
||||
#if NET7_0_OR_GREATER
|
||||
Register(new UnmanagedFormatter<Rune>());
|
||||
Register(new UnmanagedArrayFormatter<Rune>());
|
||||
Register(new NullableFormatter<Rune>());
|
||||
Register(new UnmanagedFormatter<DateOnly>());
|
||||
Register(new UnmanagedArrayFormatter<DateOnly>());
|
||||
Register(new NullableFormatter<DateOnly>());
|
||||
Register(new UnmanagedFormatter<TimeOnly>());
|
||||
Register(new UnmanagedArrayFormatter<TimeOnly>());
|
||||
Register(new NullableFormatter<TimeOnly>());
|
||||
Register(new UnmanagedFormatter<Half>());
|
||||
Register(new UnmanagedArrayFormatter<Half>());
|
||||
Register(new NullableFormatter<Half>());
|
||||
Register(new UnmanagedFormatter<Int128>());
|
||||
Register(new UnmanagedArrayFormatter<Int128>());
|
||||
Register(new NullableFormatter<Int128>());
|
||||
Register(new UnmanagedFormatter<UInt128>());
|
||||
Register(new UnmanagedArrayFormatter<UInt128>());
|
||||
Register(new NullableFormatter<UInt128>());
|
||||
#endif
|
||||
Register(new StringFormatter());
|
||||
Register(new ArrayFormatter<String>());
|
||||
Register(new VersionFormatter());
|
||||
Register(new ArrayFormatter<Version>());
|
||||
Register(new UriFormatter());
|
||||
Register(new ArrayFormatter<Uri>());
|
||||
Register(new TimeZoneInfoFormatter());
|
||||
Register(new ArrayFormatter<TimeZoneInfo>());
|
||||
Register(new BigIntegerFormatter());
|
||||
Register(new ArrayFormatter<BigInteger>());
|
||||
Register(new BitArrayFormatter());
|
||||
Register(new ArrayFormatter<BitArray>());
|
||||
Register(new StringBuilderFormatter());
|
||||
Register(new ArrayFormatter<StringBuilder>());
|
||||
Register(new TypeFormatter());
|
||||
Register(new ArrayFormatter<Type>());
|
||||
Register(new CultureInfoFormatter());
|
||||
Register(new ArrayFormatter<CultureInfo>());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c06329799b27a34abe37d38dac0a197
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,458 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using MemoryPack.Formatters;
|
||||
using MemoryPack.Internal;
|
||||
using System.Buffers;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace MemoryPack {
|
||||
|
||||
// This service provider is not extension point, for wellknown types
|
||||
// and fallback if can't resolve in compile time(like generics).
|
||||
// Therefore, unlike MessagePack for C#, it is static and not extensible.
|
||||
|
||||
public static partial class MemoryPackFormatterProvider
|
||||
{
|
||||
// for nongenerics methods
|
||||
static readonly ConcurrentDictionary<Type, IMemoryPackFormatter> formatters = new ConcurrentDictionary<Type, IMemoryPackFormatter>(Environment.ProcessorCount, 150);
|
||||
|
||||
// custom generic formatters
|
||||
static readonly ConcurrentDictionary<Type, Type> genericFormatterFactory = new ConcurrentDictionary<Type, Type>();
|
||||
|
||||
// custom generic collection formatters
|
||||
static readonly ConcurrentDictionary<Type, Type> genericCollectionFormatterFactory = new ConcurrentDictionary<Type, Type>();
|
||||
|
||||
// generics known types
|
||||
static readonly Dictionary<Type, Type> KnownGenericTypeFormatters = new Dictionary<Type, Type>(3)
|
||||
{
|
||||
{ typeof(KeyValuePair<,>), typeof(KeyValuePairFormatter<,>) },
|
||||
{ typeof(Lazy<>), typeof(LazyFormatter<>) },
|
||||
{ typeof(Nullable<>), typeof(NullableFormatter<>) },
|
||||
};
|
||||
|
||||
static partial void RegisterInitialFormatters();
|
||||
|
||||
static MemoryPackFormatterProvider()
|
||||
{
|
||||
// Initialize on startup
|
||||
RegisterWellKnownTypesFormatters();
|
||||
// Extension for Unity or others
|
||||
RegisterInitialFormatters();
|
||||
}
|
||||
|
||||
public static bool IsRegistered<T>() => Check<T>.registered;
|
||||
|
||||
public static void Register<T>(MemoryPackFormatter<T> formatter)
|
||||
{
|
||||
Check<T>.registered = true; // avoid to call Cache() constructor called.
|
||||
formatters[typeof(T)] = formatter;
|
||||
Cache<T>.formatter = formatter;
|
||||
}
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
public static void Register<T>()
|
||||
where T : IMemoryPackFormatterRegister
|
||||
{
|
||||
T.RegisterFormatter();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public static void RegisterGenericType(Type genericType, Type genericFormatterType)
|
||||
{
|
||||
if (genericType.IsGenericType && genericFormatterType.IsGenericType)
|
||||
{
|
||||
genericFormatterFactory[genericType] = genericFormatterType;
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryPackSerializationException.ThrowMessage($"Registered type is not generic type. genericType:{genericType.FullName}, formatterType:{genericFormatterType.FullName}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void RegisterCollection<TCollection, TElement>()
|
||||
where TCollection : ICollection<TElement?>, new()
|
||||
{
|
||||
Register(new GenericCollectionFormatter<TCollection, TElement>());
|
||||
}
|
||||
|
||||
public static void RegisterCollection(Type genericCollectionType)
|
||||
{
|
||||
if (genericCollectionType.IsGenericType && genericCollectionType.GetGenericArguments().Length == 1)
|
||||
{
|
||||
genericCollectionFormatterFactory[genericCollectionType] = typeof(GenericCollectionFormatter<,>);
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryPackSerializationException.ThrowMessage($"Registered generic collection is not filled generic formatter constraint. type: {genericCollectionType.FullName}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void RegisterSet<TSet, TElement>()
|
||||
where TSet : ISet<TElement?>, new()
|
||||
{
|
||||
Register(new GenericSetFormatter<TSet, TElement>());
|
||||
}
|
||||
|
||||
public static void RegisterSet(Type genericSetType)
|
||||
{
|
||||
if (genericSetType.IsGenericType && genericSetType.GetGenericArguments().Length == 1)
|
||||
{
|
||||
genericCollectionFormatterFactory[genericSetType] = typeof(GenericSetFormatter<,>);
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryPackSerializationException.ThrowMessage($"Registered generic set is not filled generic formatter constraint. type: {genericSetType.FullName}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void RegisterDictionary<TDictionary, TKey, TValue>()
|
||||
where TKey : notnull
|
||||
where TDictionary : IDictionary<TKey, TValue?>, new()
|
||||
{
|
||||
Register(new GenericDictionaryFormatter<TDictionary, TKey, TValue>());
|
||||
}
|
||||
|
||||
public static void RegisterDictionary(Type genericDictionaryType)
|
||||
{
|
||||
if (genericDictionaryType.IsGenericType && genericDictionaryType.GetGenericArguments().Length == 2)
|
||||
{
|
||||
genericCollectionFormatterFactory[genericDictionaryType] = typeof(GenericDictionaryFormatter<,,>);
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryPackSerializationException.ThrowMessage($"Registered generic collection is not filled generic formatter constraint. type: {genericDictionaryType.FullName}");
|
||||
}
|
||||
}
|
||||
|
||||
// almostly get from Writer/Reader
|
||||
// in future, will change static provider to instance provider.
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static MemoryPackFormatter<T> GetFormatter<T>()
|
||||
{
|
||||
return Cache<T>.formatter;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static IMemoryPackFormatter GetFormatter(Type type)
|
||||
{
|
||||
if (formatters.TryGetValue(type, out var formatter))
|
||||
{
|
||||
return formatter;
|
||||
}
|
||||
|
||||
if (TryInvokeRegisterFormatter(type))
|
||||
{
|
||||
// try again
|
||||
if (formatters.TryGetValue(type, out formatter))
|
||||
{
|
||||
return formatter;
|
||||
}
|
||||
}
|
||||
|
||||
if (TypeHelpers.IsAnonymous(type))
|
||||
{
|
||||
formatter = new ErrorMemoryPackFormatter(type, "Serialize anonymous type is not supported, use record or tuple instead.");
|
||||
goto END;
|
||||
}
|
||||
|
||||
// non registered, try to create generic formatter
|
||||
// can not detect IsReferenceOrContainsReference but it only uses array type select so safe).
|
||||
var formatter2 = CreateGenericFormatter(type, typeIsReferenceOrContainsReferences: true) as IMemoryPackFormatter;
|
||||
if (formatter2 == null)
|
||||
{
|
||||
formatter2 = new ErrorMemoryPackFormatter(type);
|
||||
}
|
||||
formatter = formatter2;
|
||||
|
||||
END:
|
||||
formatters[type] = formatter;
|
||||
return formatter;
|
||||
}
|
||||
|
||||
static bool TryInvokeRegisterFormatter(Type type)
|
||||
{
|
||||
if (typeof(IMemoryPackFormatterRegister).IsAssignableFrom(type))
|
||||
{
|
||||
// currently C# can not call like `if (T is IMemoryPackFormatterRegister) T.RegisterFormatter()`, so use reflection instead.
|
||||
var m = type.GetMethod("MemoryPack.IMemoryPackFormatterRegister.RegisterFormatter", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
|
||||
if (m == null)
|
||||
{
|
||||
// Roslyn3.11 generator generate public static method
|
||||
m = type.GetMethod("RegisterFormatter", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
|
||||
}
|
||||
if (m == null)
|
||||
{
|
||||
throw new InvalidOperationException("Type implements IMemoryPackFormatterRegister but can not found RegisterFormatter. Type: " + type.FullName);
|
||||
}
|
||||
m!.Invoke(null, null); // Cache<T>.formatter will set from method
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static class Check<T>
|
||||
{
|
||||
public static bool registered;
|
||||
}
|
||||
|
||||
static class Cache<T>
|
||||
{
|
||||
public static MemoryPackFormatter<T> formatter = default!;
|
||||
|
||||
static Cache()
|
||||
{
|
||||
if (Check<T>.registered) return;
|
||||
|
||||
try
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (TryInvokeRegisterFormatter(type))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (TypeHelpers.IsAnonymous(type))
|
||||
{
|
||||
formatter = new ErrorMemoryPackFormatter<T>("Serialize anonymous type is not supported, use record or tuple instead.");
|
||||
goto END;
|
||||
}
|
||||
|
||||
var typeIsReferenceOrContainsReferences = RuntimeHelpers.IsReferenceOrContainsReferences<T>();
|
||||
var f = CreateGenericFormatter(type, typeIsReferenceOrContainsReferences) as MemoryPackFormatter<T>;
|
||||
|
||||
formatter = f ?? new ErrorMemoryPackFormatter<T>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
formatter = new ErrorMemoryPackFormatter<T>(ex);
|
||||
}
|
||||
|
||||
END:
|
||||
formatters[typeof(T)] = formatter;
|
||||
Check<T>.registered = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal static object? CreateGenericFormatter(Type type, bool typeIsReferenceOrContainsReferences)
|
||||
{
|
||||
Type? formatterType = null;
|
||||
|
||||
if (type.IsArray)
|
||||
{
|
||||
if (type.IsSZArray)
|
||||
{
|
||||
if (!typeIsReferenceOrContainsReferences)
|
||||
{
|
||||
formatterType = typeof(DangerousUnmanagedArrayFormatter<>).MakeGenericType(type.GetElementType()!);
|
||||
goto CREATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
formatterType = typeof(ArrayFormatter<>).MakeGenericType(type.GetElementType()!);
|
||||
goto CREATE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var rank = type.GetArrayRank();
|
||||
switch (rank)
|
||||
{
|
||||
case 2:
|
||||
formatterType = typeof(TwoDimensionalArrayFormatter<>).MakeGenericType(type.GetElementType()!);
|
||||
goto CREATE;
|
||||
case 3:
|
||||
formatterType = typeof(ThreeDimensionalArrayFormatter<>).MakeGenericType(type.GetElementType()!);
|
||||
goto CREATE;
|
||||
case 4:
|
||||
formatterType = typeof(FourDimensionalArrayFormatter<>).MakeGenericType(type.GetElementType()!);
|
||||
goto CREATE;
|
||||
default:
|
||||
return null; // not supported
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type.IsEnum || !typeIsReferenceOrContainsReferences)
|
||||
{
|
||||
formatterType = typeof(DangerousUnmanagedFormatter<>).MakeGenericType(type);
|
||||
goto CREATE;
|
||||
}
|
||||
|
||||
formatterType = TryCreateGenericFormatterType(type, TupleFormatterTypes.TupleFormatters);
|
||||
if (formatterType != null) goto CREATE;
|
||||
|
||||
formatterType = TryCreateGenericFormatterType(type, KnownGenericTypeFormatters);
|
||||
if (formatterType != null) goto CREATE;
|
||||
|
||||
formatterType = TryCreateGenericFormatterType(type, ArrayLikeFormatters);
|
||||
if (formatterType != null) goto CREATE;
|
||||
|
||||
formatterType = TryCreateGenericFormatterType(type, CollectionFormatters);
|
||||
if (formatterType != null) goto CREATE;
|
||||
|
||||
#if !UNITY_2021_2_OR_NEWER
|
||||
formatterType = TryCreateGenericFormatterType(type, ImmutableCollectionFormatters);
|
||||
if (formatterType != null) goto CREATE;
|
||||
#endif
|
||||
|
||||
formatterType = TryCreateGenericFormatterType(type, InterfaceCollectionFormatters);
|
||||
if (formatterType != null) goto CREATE;
|
||||
|
||||
// finally custom generated
|
||||
formatterType = TryCreateGenericFormatterType(type, genericFormatterFactory);
|
||||
if (formatterType != null) goto CREATE;
|
||||
|
||||
// genericCollectionFormatterFactory
|
||||
formatterType = TryCreateGenericCollectionFormatterType(type);
|
||||
if (formatterType != null) goto CREATE;
|
||||
|
||||
// Can't resolve formatter, return null(will create ErrorMemoryPackFormatter<T>).
|
||||
return null;
|
||||
|
||||
CREATE:
|
||||
return Activator.CreateInstance(formatterType);
|
||||
}
|
||||
|
||||
static Type? TryCreateGenericFormatterType(Type type, IDictionary<Type, Type> knownTypes)
|
||||
{
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
var genericDefinition = type.GetGenericTypeDefinition();
|
||||
|
||||
if (knownTypes.TryGetValue(genericDefinition, out var formatterType))
|
||||
{
|
||||
return formatterType.MakeGenericType(type.GetGenericArguments());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static Type? TryCreateGenericCollectionFormatterType(Type type)
|
||||
{
|
||||
if (type.IsGenericType && genericCollectionFormatterFactory.TryGetValue(type, out var formatterType))
|
||||
{
|
||||
var genericDefinition = type.GetGenericTypeDefinition();
|
||||
var elementTypes = genericDefinition.GetGenericArguments();
|
||||
|
||||
// formatterType is <TCollection, TArgs> so concat type at first
|
||||
return formatterType.MakeGenericType(elementTypes.Prepend(type).ToArray());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ErrorMemoryPackFormatter : IMemoryPackFormatter
|
||||
{
|
||||
readonly Type type;
|
||||
readonly string? message;
|
||||
|
||||
public ErrorMemoryPackFormatter(Type type)
|
||||
{
|
||||
this.type = type;
|
||||
this.message = null;
|
||||
}
|
||||
|
||||
public ErrorMemoryPackFormatter(Type type, string message)
|
||||
{
|
||||
this.type = type;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public void Serialize(ref MemoryPackWriter writer, ref object? value)
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
{
|
||||
Throw();
|
||||
}
|
||||
|
||||
public void Deserialize(ref MemoryPackReader reader, ref object? value)
|
||||
{
|
||||
Throw();
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
void Throw()
|
||||
{
|
||||
if (message != null)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowMessage(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryPackSerializationException.ThrowNotRegisteredInProvider(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ErrorMemoryPackFormatter<T> : MemoryPackFormatter<T>
|
||||
{
|
||||
readonly Exception? exception;
|
||||
readonly string? message;
|
||||
|
||||
public ErrorMemoryPackFormatter()
|
||||
{
|
||||
this.exception = null;
|
||||
this.message = null;
|
||||
}
|
||||
|
||||
public ErrorMemoryPackFormatter(Exception exception)
|
||||
{
|
||||
this.exception = exception;
|
||||
this.message = null;
|
||||
}
|
||||
|
||||
public ErrorMemoryPackFormatter(string message)
|
||||
{
|
||||
this.exception = null;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public override void Serialize(ref MemoryPackWriter writer, ref T? value)
|
||||
{
|
||||
Throw();
|
||||
}
|
||||
|
||||
public override void Deserialize(ref MemoryPackReader reader, ref T? value)
|
||||
{
|
||||
Throw();
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
void Throw()
|
||||
{
|
||||
if (exception != null)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowRegisterInProviderFailed(typeof(T), exception);
|
||||
}
|
||||
else if (message != null)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowMessage(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryPackSerializationException.ThrowNotRegisteredInProvider(typeof(T));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1200521b3b3b7344a1cfe3b1b58439a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,620 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using System.Buffers;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MemoryPack {
|
||||
|
||||
public ref partial struct MemoryPackReader
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanaged<T1>(out T1 value1)
|
||||
where T1 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanaged<T1, T2>(out T1 value1, out T2 value2)
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanaged<T1, T2, T3>(out T1 value1, out T2 value2, out T3 value3)
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged
|
||||
where T3 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanaged<T1, T2, T3, T4>(out T1 value1, out T2 value2, out T3 value3, out T4 value4)
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged
|
||||
where T3 : unmanaged
|
||||
where T4 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanaged<T1, T2, T3, T4, T5>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5)
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged
|
||||
where T3 : unmanaged
|
||||
where T4 : unmanaged
|
||||
where T5 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanaged<T1, T2, T3, T4, T5, T6>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6)
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged
|
||||
where T3 : unmanaged
|
||||
where T4 : unmanaged
|
||||
where T5 : unmanaged
|
||||
where T6 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanaged<T1, T2, T3, T4, T5, T6, T7>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7)
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged
|
||||
where T3 : unmanaged
|
||||
where T4 : unmanaged
|
||||
where T5 : unmanaged
|
||||
where T6 : unmanaged
|
||||
where T7 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8)
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged
|
||||
where T3 : unmanaged
|
||||
where T4 : unmanaged
|
||||
where T5 : unmanaged
|
||||
where T6 : unmanaged
|
||||
where T7 : unmanaged
|
||||
where T8 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8, T9>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8, out T9 value9)
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged
|
||||
where T3 : unmanaged
|
||||
where T4 : unmanaged
|
||||
where T5 : unmanaged
|
||||
where T6 : unmanaged
|
||||
where T7 : unmanaged
|
||||
where T8 : unmanaged
|
||||
where T9 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
value9 = Unsafe.ReadUnaligned<T9>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8, out T9 value9, out T10 value10)
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged
|
||||
where T3 : unmanaged
|
||||
where T4 : unmanaged
|
||||
where T5 : unmanaged
|
||||
where T6 : unmanaged
|
||||
where T7 : unmanaged
|
||||
where T8 : unmanaged
|
||||
where T9 : unmanaged
|
||||
where T10 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
value9 = Unsafe.ReadUnaligned<T9>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>()));
|
||||
value10 = Unsafe.ReadUnaligned<T10>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8, out T9 value9, out T10 value10, out T11 value11)
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged
|
||||
where T3 : unmanaged
|
||||
where T4 : unmanaged
|
||||
where T5 : unmanaged
|
||||
where T6 : unmanaged
|
||||
where T7 : unmanaged
|
||||
where T8 : unmanaged
|
||||
where T9 : unmanaged
|
||||
where T10 : unmanaged
|
||||
where T11 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
value9 = Unsafe.ReadUnaligned<T9>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>()));
|
||||
value10 = Unsafe.ReadUnaligned<T10>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>()));
|
||||
value11 = Unsafe.ReadUnaligned<T11>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8, out T9 value9, out T10 value10, out T11 value11, out T12 value12)
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged
|
||||
where T3 : unmanaged
|
||||
where T4 : unmanaged
|
||||
where T5 : unmanaged
|
||||
where T6 : unmanaged
|
||||
where T7 : unmanaged
|
||||
where T8 : unmanaged
|
||||
where T9 : unmanaged
|
||||
where T10 : unmanaged
|
||||
where T11 : unmanaged
|
||||
where T12 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
value9 = Unsafe.ReadUnaligned<T9>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>()));
|
||||
value10 = Unsafe.ReadUnaligned<T10>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>()));
|
||||
value11 = Unsafe.ReadUnaligned<T11>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>()));
|
||||
value12 = Unsafe.ReadUnaligned<T12>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8, out T9 value9, out T10 value10, out T11 value11, out T12 value12, out T13 value13)
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged
|
||||
where T3 : unmanaged
|
||||
where T4 : unmanaged
|
||||
where T5 : unmanaged
|
||||
where T6 : unmanaged
|
||||
where T7 : unmanaged
|
||||
where T8 : unmanaged
|
||||
where T9 : unmanaged
|
||||
where T10 : unmanaged
|
||||
where T11 : unmanaged
|
||||
where T12 : unmanaged
|
||||
where T13 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>() + Unsafe.SizeOf<T13>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
value9 = Unsafe.ReadUnaligned<T9>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>()));
|
||||
value10 = Unsafe.ReadUnaligned<T10>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>()));
|
||||
value11 = Unsafe.ReadUnaligned<T11>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>()));
|
||||
value12 = Unsafe.ReadUnaligned<T12>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>()));
|
||||
value13 = Unsafe.ReadUnaligned<T13>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8, out T9 value9, out T10 value10, out T11 value11, out T12 value12, out T13 value13, out T14 value14)
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged
|
||||
where T3 : unmanaged
|
||||
where T4 : unmanaged
|
||||
where T5 : unmanaged
|
||||
where T6 : unmanaged
|
||||
where T7 : unmanaged
|
||||
where T8 : unmanaged
|
||||
where T9 : unmanaged
|
||||
where T10 : unmanaged
|
||||
where T11 : unmanaged
|
||||
where T12 : unmanaged
|
||||
where T13 : unmanaged
|
||||
where T14 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>() + Unsafe.SizeOf<T13>() + Unsafe.SizeOf<T14>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
value9 = Unsafe.ReadUnaligned<T9>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>()));
|
||||
value10 = Unsafe.ReadUnaligned<T10>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>()));
|
||||
value11 = Unsafe.ReadUnaligned<T11>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>()));
|
||||
value12 = Unsafe.ReadUnaligned<T12>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>()));
|
||||
value13 = Unsafe.ReadUnaligned<T13>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>()));
|
||||
value14 = Unsafe.ReadUnaligned<T14>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>() + Unsafe.SizeOf<T13>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8, out T9 value9, out T10 value10, out T11 value11, out T12 value12, out T13 value13, out T14 value14, out T15 value15)
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged
|
||||
where T3 : unmanaged
|
||||
where T4 : unmanaged
|
||||
where T5 : unmanaged
|
||||
where T6 : unmanaged
|
||||
where T7 : unmanaged
|
||||
where T8 : unmanaged
|
||||
where T9 : unmanaged
|
||||
where T10 : unmanaged
|
||||
where T11 : unmanaged
|
||||
where T12 : unmanaged
|
||||
where T13 : unmanaged
|
||||
where T14 : unmanaged
|
||||
where T15 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>() + Unsafe.SizeOf<T13>() + Unsafe.SizeOf<T14>() + Unsafe.SizeOf<T15>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
value9 = Unsafe.ReadUnaligned<T9>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>()));
|
||||
value10 = Unsafe.ReadUnaligned<T10>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>()));
|
||||
value11 = Unsafe.ReadUnaligned<T11>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>()));
|
||||
value12 = Unsafe.ReadUnaligned<T12>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>()));
|
||||
value13 = Unsafe.ReadUnaligned<T13>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>()));
|
||||
value14 = Unsafe.ReadUnaligned<T14>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>() + Unsafe.SizeOf<T13>()));
|
||||
value15 = Unsafe.ReadUnaligned<T15>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>() + Unsafe.SizeOf<T13>() + Unsafe.SizeOf<T14>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void DangerousReadUnmanaged<T1>(out T1 value1)
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void DangerousReadUnmanaged<T1, T2>(out T1 value1, out T2 value2)
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void DangerousReadUnmanaged<T1, T2, T3>(out T1 value1, out T2 value2, out T3 value3)
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void DangerousReadUnmanaged<T1, T2, T3, T4>(out T1 value1, out T2 value2, out T3 value3, out T4 value4)
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void DangerousReadUnmanaged<T1, T2, T3, T4, T5>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5)
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void DangerousReadUnmanaged<T1, T2, T3, T4, T5, T6>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6)
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void DangerousReadUnmanaged<T1, T2, T3, T4, T5, T6, T7>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7)
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void DangerousReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8)
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void DangerousReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8, T9>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8, out T9 value9)
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
value9 = Unsafe.ReadUnaligned<T9>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void DangerousReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8, out T9 value9, out T10 value10)
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
value9 = Unsafe.ReadUnaligned<T9>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>()));
|
||||
value10 = Unsafe.ReadUnaligned<T10>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void DangerousReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8, out T9 value9, out T10 value10, out T11 value11)
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
value9 = Unsafe.ReadUnaligned<T9>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>()));
|
||||
value10 = Unsafe.ReadUnaligned<T10>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>()));
|
||||
value11 = Unsafe.ReadUnaligned<T11>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void DangerousReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8, out T9 value9, out T10 value10, out T11 value11, out T12 value12)
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
value9 = Unsafe.ReadUnaligned<T9>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>()));
|
||||
value10 = Unsafe.ReadUnaligned<T10>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>()));
|
||||
value11 = Unsafe.ReadUnaligned<T11>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>()));
|
||||
value12 = Unsafe.ReadUnaligned<T12>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void DangerousReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8, out T9 value9, out T10 value10, out T11 value11, out T12 value12, out T13 value13)
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>() + Unsafe.SizeOf<T13>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
value9 = Unsafe.ReadUnaligned<T9>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>()));
|
||||
value10 = Unsafe.ReadUnaligned<T10>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>()));
|
||||
value11 = Unsafe.ReadUnaligned<T11>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>()));
|
||||
value12 = Unsafe.ReadUnaligned<T12>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>()));
|
||||
value13 = Unsafe.ReadUnaligned<T13>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void DangerousReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8, out T9 value9, out T10 value10, out T11 value11, out T12 value12, out T13 value13, out T14 value14)
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>() + Unsafe.SizeOf<T13>() + Unsafe.SizeOf<T14>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
value9 = Unsafe.ReadUnaligned<T9>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>()));
|
||||
value10 = Unsafe.ReadUnaligned<T10>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>()));
|
||||
value11 = Unsafe.ReadUnaligned<T11>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>()));
|
||||
value12 = Unsafe.ReadUnaligned<T12>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>()));
|
||||
value13 = Unsafe.ReadUnaligned<T13>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>()));
|
||||
value14 = Unsafe.ReadUnaligned<T14>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>() + Unsafe.SizeOf<T13>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void DangerousReadUnmanaged<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(out T1 value1, out T2 value2, out T3 value3, out T4 value4, out T5 value5, out T6 value6, out T7 value7, out T8 value8, out T9 value9, out T10 value10, out T11 value11, out T12 value12, out T13 value13, out T14 value14, out T15 value15)
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>() + Unsafe.SizeOf<T13>() + Unsafe.SizeOf<T14>() + Unsafe.SizeOf<T15>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
value2 = Unsafe.ReadUnaligned<T2>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>()));
|
||||
value3 = Unsafe.ReadUnaligned<T3>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>()));
|
||||
value4 = Unsafe.ReadUnaligned<T4>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>()));
|
||||
value5 = Unsafe.ReadUnaligned<T5>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>()));
|
||||
value6 = Unsafe.ReadUnaligned<T6>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>()));
|
||||
value7 = Unsafe.ReadUnaligned<T7>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>()));
|
||||
value8 = Unsafe.ReadUnaligned<T8>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>()));
|
||||
value9 = Unsafe.ReadUnaligned<T9>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>()));
|
||||
value10 = Unsafe.ReadUnaligned<T10>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>()));
|
||||
value11 = Unsafe.ReadUnaligned<T11>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>()));
|
||||
value12 = Unsafe.ReadUnaligned<T12>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>()));
|
||||
value13 = Unsafe.ReadUnaligned<T13>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>()));
|
||||
value14 = Unsafe.ReadUnaligned<T14>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>() + Unsafe.SizeOf<T13>()));
|
||||
value15 = Unsafe.ReadUnaligned<T15>(ref Unsafe.Add(ref spanRef, Unsafe.SizeOf<T1>() + Unsafe.SizeOf<T2>() + Unsafe.SizeOf<T3>() + Unsafe.SizeOf<T4>() + Unsafe.SizeOf<T5>() + Unsafe.SizeOf<T6>() + Unsafe.SizeOf<T7>() + Unsafe.SizeOf<T8>() + Unsafe.SizeOf<T9>() + Unsafe.SizeOf<T10>() + Unsafe.SizeOf<T11>() + Unsafe.SizeOf<T12>() + Unsafe.SizeOf<T13>() + Unsafe.SizeOf<T14>()));
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5edf80b8ed9aae143b689d072859a209
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
930
AssetDependencyGraph/Plugins/MemoryPack.Core/MemoryPackReader.cs
Normal file
930
AssetDependencyGraph/Plugins/MemoryPack.Core/MemoryPackReader.cs
Normal file
@ -0,0 +1,930 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using System.Buffers;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
#if NET7_0_OR_GREATER
|
||||
using System.Text.Unicode;
|
||||
#endif
|
||||
|
||||
namespace MemoryPack {
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
using static GC;
|
||||
using static MemoryMarshal;
|
||||
#else
|
||||
using static MemoryPack.Internal.MemoryMarshalEx;
|
||||
#endif
|
||||
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public ref partial struct MemoryPackReader
|
||||
{
|
||||
ReadOnlySequence<byte> bufferSource;
|
||||
readonly long totalLength;
|
||||
#if NET7_0_OR_GREATER
|
||||
ref byte bufferReference;
|
||||
#else
|
||||
ReadOnlySpan<byte> bufferReference;
|
||||
#endif
|
||||
int bufferLength;
|
||||
byte[]? rentBuffer;
|
||||
int advancedCount;
|
||||
int consumed; // total length of consumed
|
||||
readonly MemoryPackReaderOptionalState optionalState;
|
||||
|
||||
public int Consumed => consumed;
|
||||
public long Remaining => totalLength - consumed;
|
||||
public MemoryPackReaderOptionalState OptionalState => optionalState;
|
||||
public MemoryPackSerializerOptions Options => optionalState.Options;
|
||||
|
||||
public MemoryPackReader(in ReadOnlySequence<byte> sequence, MemoryPackReaderOptionalState optionalState)
|
||||
{
|
||||
this.bufferSource = sequence.IsSingleSegment ? ReadOnlySequence<byte>.Empty : sequence;
|
||||
var span = sequence.FirstSpan;
|
||||
#if NET7_0_OR_GREATER
|
||||
this.bufferReference = ref MemoryMarshal.GetReference(span);
|
||||
#else
|
||||
this.bufferReference = span;
|
||||
#endif
|
||||
this.bufferLength = span.Length;
|
||||
this.advancedCount = 0;
|
||||
this.consumed = 0;
|
||||
this.rentBuffer = null;
|
||||
this.totalLength = sequence.Length;
|
||||
this.optionalState = optionalState;
|
||||
}
|
||||
|
||||
public MemoryPackReader(ReadOnlySpan<byte> buffer, MemoryPackReaderOptionalState optionalState)
|
||||
{
|
||||
this.bufferSource = ReadOnlySequence<byte>.Empty;
|
||||
#if NET7_0_OR_GREATER
|
||||
this.bufferReference = ref MemoryMarshal.GetReference(buffer);
|
||||
#else
|
||||
this.bufferReference = buffer;
|
||||
#endif
|
||||
this.bufferLength = buffer.Length;
|
||||
this.advancedCount = 0;
|
||||
this.consumed = 0;
|
||||
this.rentBuffer = null;
|
||||
this.totalLength = buffer.Length;
|
||||
this.optionalState = optionalState;
|
||||
}
|
||||
|
||||
// buffer operations
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref byte GetSpanReference(int sizeHint)
|
||||
{
|
||||
if (sizeHint <= bufferLength)
|
||||
{
|
||||
#if NET7_0_OR_GREATER
|
||||
return ref bufferReference;
|
||||
#else
|
||||
return ref MemoryMarshal.GetReference(bufferReference);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ref GetNextSpan(sizeHint);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
ref byte GetNextSpan(int sizeHint)
|
||||
{
|
||||
if (rentBuffer != null)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(rentBuffer);
|
||||
rentBuffer = null;
|
||||
}
|
||||
|
||||
if (Remaining == 0)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowSequenceReachedEnd();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
bufferSource = bufferSource.Slice(advancedCount);
|
||||
}
|
||||
catch (ArgumentOutOfRangeException)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowSequenceReachedEnd();
|
||||
}
|
||||
|
||||
advancedCount = 0;
|
||||
|
||||
if (sizeHint <= Remaining)
|
||||
{
|
||||
if (sizeHint <= bufferSource.FirstSpan.Length)
|
||||
{
|
||||
#if NET7_0_OR_GREATER
|
||||
bufferReference = ref MemoryMarshal.GetReference(bufferSource.FirstSpan);
|
||||
bufferLength = bufferSource.FirstSpan.Length;
|
||||
return ref bufferReference;
|
||||
#else
|
||||
bufferReference = bufferSource.FirstSpan;
|
||||
bufferLength = bufferSource.FirstSpan.Length;
|
||||
return ref MemoryMarshal.GetReference(bufferReference);
|
||||
#endif
|
||||
}
|
||||
|
||||
rentBuffer = ArrayPool<byte>.Shared.Rent(sizeHint);
|
||||
bufferSource.Slice(0, sizeHint).CopyTo(rentBuffer);
|
||||
var span = rentBuffer.AsSpan(0, sizeHint);
|
||||
#if NET7_0_OR_GREATER
|
||||
bufferReference = ref MemoryMarshal.GetReference(span);
|
||||
bufferLength = span.Length;
|
||||
return ref bufferReference;
|
||||
#else
|
||||
bufferReference = span;
|
||||
bufferLength = span.Length;
|
||||
return ref MemoryMarshal.GetReference(bufferReference);
|
||||
#endif
|
||||
}
|
||||
|
||||
MemoryPackSerializationException.ThrowSequenceReachedEnd();
|
||||
#if NET7_0_OR_GREATER
|
||||
return ref bufferReference; // dummy.
|
||||
#else
|
||||
return ref MemoryMarshal.GetReference(bufferReference);
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Advance(int count)
|
||||
{
|
||||
if (count == 0) return;
|
||||
|
||||
var rest = bufferLength - count;
|
||||
if (rest < 0)
|
||||
{
|
||||
if (TryAdvanceSequence(count))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bufferLength = rest;
|
||||
#if NET7_0_OR_GREATER
|
||||
bufferReference = ref Unsafe.Add(ref bufferReference, count);
|
||||
#else
|
||||
bufferReference = bufferReference.Slice(count);
|
||||
#endif
|
||||
advancedCount += count;
|
||||
consumed += count;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
bool TryAdvanceSequence(int count)
|
||||
{
|
||||
var rest = bufferSource.Length - count;
|
||||
if (rest < 0)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowInvalidAdvance();
|
||||
}
|
||||
|
||||
bufferSource = bufferSource.Slice(advancedCount + count);
|
||||
#if NET7_0_OR_GREATER
|
||||
bufferReference = ref MemoryMarshal.GetReference(bufferSource.FirstSpan);
|
||||
#else
|
||||
bufferReference = bufferSource.FirstSpan;
|
||||
#endif
|
||||
bufferLength = bufferSource.FirstSpan.Length;
|
||||
advancedCount = 0;
|
||||
consumed += count;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void GetRemainingSource(out ReadOnlySpan<byte> singleSource, out ReadOnlySequence<byte> remainingSource)
|
||||
{
|
||||
if (bufferSource.IsEmpty)
|
||||
{
|
||||
remainingSource = ReadOnlySequence<byte>.Empty;
|
||||
#if NET7_0_OR_GREATER
|
||||
singleSource = MemoryMarshal.CreateReadOnlySpan(ref bufferReference, bufferLength);
|
||||
#else
|
||||
singleSource = bufferReference;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bufferSource.IsSingleSegment)
|
||||
{
|
||||
remainingSource = ReadOnlySequence<byte>.Empty;
|
||||
singleSource = bufferSource.FirstSpan.Slice(advancedCount);
|
||||
return;
|
||||
}
|
||||
|
||||
singleSource = default;
|
||||
remainingSource = bufferSource.Slice(advancedCount);
|
||||
if (remainingSource.IsSingleSegment)
|
||||
{
|
||||
singleSource = remainingSource.FirstSpan;
|
||||
remainingSource = ReadOnlySequence<byte>.Empty;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Dispose()
|
||||
{
|
||||
if (rentBuffer != null)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(rentBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public IMemoryPackFormatter GetFormatter(Type type)
|
||||
{
|
||||
return MemoryPackFormatterProvider.GetFormatter(type);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public IMemoryPackFormatter<T> GetFormatter<T>()
|
||||
{
|
||||
return MemoryPackFormatterProvider.GetFormatter<T>();
|
||||
}
|
||||
|
||||
// read methods
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool TryReadObjectHeader(out byte memberCount)
|
||||
{
|
||||
memberCount = GetSpanReference(1);
|
||||
Advance(1);
|
||||
return memberCount != MemoryPackCode.NullObject;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool TryReadUnionHeader(out ushort tag)
|
||||
{
|
||||
var firstTag = GetSpanReference(1);
|
||||
Advance(1);
|
||||
if (firstTag < MemoryPackCode.WideTag)
|
||||
{
|
||||
tag = firstTag;
|
||||
return true;
|
||||
}
|
||||
else if (firstTag == MemoryPackCode.WideTag)
|
||||
{
|
||||
ReadUnmanaged(out tag);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
tag = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool TryReadCollectionHeader(out int length)
|
||||
{
|
||||
length = Unsafe.ReadUnaligned<int>(ref GetSpanReference(4));
|
||||
Advance(4);
|
||||
|
||||
// If collection-length is larger than buffer-length, it is invalid data.
|
||||
if (Remaining < length)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowInsufficientBufferUnless(length);
|
||||
}
|
||||
|
||||
return length != MemoryPackCode.NullCollection;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool PeekIsNull()
|
||||
{
|
||||
var code = GetSpanReference(1);
|
||||
return code == MemoryPackCode.NullObject;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool TryPeekObjectHeader(out byte memberCount)
|
||||
{
|
||||
memberCount = GetSpanReference(1);
|
||||
return memberCount != MemoryPackCode.NullObject;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool TryPeekUnionHeader(out ushort tag)
|
||||
{
|
||||
var firstTag = GetSpanReference(1);
|
||||
if (firstTag < MemoryPackCode.WideTag)
|
||||
{
|
||||
tag = firstTag;
|
||||
return true;
|
||||
}
|
||||
else if (firstTag == MemoryPackCode.WideTag)
|
||||
{
|
||||
ref var spanRef = ref GetSpanReference(sizeof(ushort) + 1); // skip firstTag
|
||||
tag = Unsafe.ReadUnaligned<ushort>(ref Unsafe.Add(ref spanRef, 1));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
tag = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool TryPeekCollectionHeader(out int length)
|
||||
{
|
||||
length = Unsafe.ReadUnaligned<int>(ref GetSpanReference(4));
|
||||
|
||||
// If collection-length is larger than buffer-length, it is invalid data.
|
||||
if (Remaining < length)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowInsufficientBufferUnless(length);
|
||||
}
|
||||
|
||||
return length != MemoryPackCode.NullCollection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// no validate collection size, be careful to use.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool DangerousTryReadCollectionHeader(out int length)
|
||||
{
|
||||
length = Unsafe.ReadUnaligned<int>(ref GetSpanReference(4));
|
||||
Advance(4);
|
||||
|
||||
return length != MemoryPackCode.NullCollection;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string? ReadString()
|
||||
{
|
||||
if (!TryReadCollectionHeader(out var length))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (length == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
return ReadUtf16(length);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ReadUtf8(length);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
string ReadUtf16(int length)
|
||||
{
|
||||
var byteCount = checked(length * 2);
|
||||
ref var src = ref GetSpanReference(byteCount);
|
||||
|
||||
var str = new string(MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As<byte, char>(ref src), length));
|
||||
|
||||
Advance(byteCount);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)] // non default, no inline
|
||||
string ReadUtf8(int utf8Length)
|
||||
{
|
||||
// (int ~utf8-byte-count, int utf16-length, utf8-bytes)
|
||||
// already read utf8 length, but it is complement.
|
||||
|
||||
utf8Length = ~utf8Length;
|
||||
|
||||
ref var spanRef = ref GetSpanReference(utf8Length + 4); // + read utf16 length
|
||||
|
||||
string str;
|
||||
var utf16Length = Unsafe.ReadUnaligned<int>(ref spanRef);
|
||||
|
||||
if (utf16Length <= 0)
|
||||
{
|
||||
var src = MemoryMarshal.CreateReadOnlySpan(ref Unsafe.Add(ref spanRef, 4), utf8Length);
|
||||
str = Encoding.UTF8.GetString(src);
|
||||
}
|
||||
else
|
||||
{
|
||||
// check malformed utf16Length
|
||||
var max = unchecked((Remaining + 1) * 3);
|
||||
if (max < 0) max = int.MaxValue;
|
||||
if (max < utf16Length)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowInsufficientBufferUnless(utf8Length);
|
||||
}
|
||||
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
// regular path, know decoded UTF16 length will gets faster decode result
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* p = &Unsafe.Add(ref spanRef, 4))
|
||||
{
|
||||
str = string.Create(utf16Length, ((IntPtr)p, utf8Length), static (dest, state) =>
|
||||
{
|
||||
var src = MemoryMarshal.CreateSpan(ref Unsafe.AsRef<byte>((byte*)state.Item1), state.Item2);
|
||||
var status = Utf8.ToUtf16(src, dest, out var bytesRead, out var charsWritten, replaceInvalidSequences: false);
|
||||
if (status != OperationStatus.Done)
|
||||
{
|
||||
MemoryPackSerializationException.ThrowFailedEncoding(status);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
#else
|
||||
var src = MemoryMarshal.CreateReadOnlySpan(ref Unsafe.Add(ref spanRef, 4), utf8Length);
|
||||
str = Encoding.UTF8.GetString(src);
|
||||
#endif
|
||||
}
|
||||
|
||||
Advance(utf8Length + 4);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public T1 ReadUnmanaged<T1>()
|
||||
where T1 : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T1>();
|
||||
ref var spanRef = ref GetSpanReference(size);
|
||||
var value1 = Unsafe.ReadUnaligned<T1>(ref spanRef);
|
||||
Advance(size);
|
||||
return value1;
|
||||
}
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadPackable<T>(ref T? value)
|
||||
where T : IMemoryPackable<T>
|
||||
{
|
||||
T.Deserialize(ref this, ref value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public T? ReadPackable<T>()
|
||||
where T : IMemoryPackable<T>
|
||||
{
|
||||
T? value = default;
|
||||
T.Deserialize(ref this, ref value);
|
||||
return value;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadPackable<T>(ref T? value)
|
||||
where T : IMemoryPackable<T>
|
||||
{
|
||||
ReadValue(ref value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public T? ReadPackable<T>()
|
||||
where T : IMemoryPackable<T>
|
||||
{
|
||||
return ReadValue<T>();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// non packable, get formatter dynamically.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadValue<T>(ref T? value)
|
||||
{
|
||||
GetFormatter<T>().Deserialize(ref this, ref value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public T? ReadValue<T>()
|
||||
{
|
||||
T? value = default;
|
||||
GetFormatter<T>().Deserialize(ref this, ref value);
|
||||
return value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadValue(Type type, ref object? value)
|
||||
{
|
||||
GetFormatter(type).Deserialize(ref this, ref value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public object? ReadValue(Type type)
|
||||
{
|
||||
object? value = default;
|
||||
GetFormatter(type).Deserialize(ref this, ref value);
|
||||
return value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadValueWithFormatter<TFormatter, T>(TFormatter formatter, ref T? value)
|
||||
where TFormatter : IMemoryPackFormatter<T>
|
||||
{
|
||||
formatter.Deserialize(ref this, ref value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public T? ReadValueWithFormatter<TFormatter, T>(TFormatter formatter)
|
||||
where TFormatter : IMemoryPackFormatter<T>
|
||||
{
|
||||
T? value = default;
|
||||
formatter.Deserialize(ref this, ref value);
|
||||
return value;
|
||||
}
|
||||
|
||||
#region ReadArray/Span
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public T?[]? ReadArray<T>()
|
||||
{
|
||||
T?[]? value = default;
|
||||
ReadArray(ref value);
|
||||
return value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadArray<T>(ref T?[]? value)
|
||||
{
|
||||
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T>())
|
||||
{
|
||||
DangerousReadUnmanagedArray(ref value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
value = Array.Empty<T>();
|
||||
return;
|
||||
}
|
||||
|
||||
// T[] support overwrite
|
||||
if (value == null || value.Length != length)
|
||||
{
|
||||
value = new T[length];
|
||||
}
|
||||
|
||||
var formatter = GetFormatter<T>();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
formatter.Deserialize(ref this, ref value[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadSpan<T>(ref Span<T?> value)
|
||||
{
|
||||
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T>())
|
||||
{
|
||||
DangerousReadUnmanagedSpan(ref value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = default;
|
||||
return;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
value = Array.Empty<T>();
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.Length != length)
|
||||
{
|
||||
value = new T[length];
|
||||
}
|
||||
|
||||
var formatter = GetFormatter<T>();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
formatter.Deserialize(ref this, ref value[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public T?[]? ReadPackableArray<T>()
|
||||
where T : IMemoryPackable<T>
|
||||
{
|
||||
T?[]? value = default;
|
||||
ReadPackableArray(ref value);
|
||||
return value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadPackableArray<T>(ref T?[]? value)
|
||||
where T : IMemoryPackable<T>
|
||||
{
|
||||
#if !NET7_0_OR_GREATER
|
||||
ReadArray(ref value);
|
||||
return;
|
||||
#else
|
||||
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T>())
|
||||
{
|
||||
DangerousReadUnmanagedArray(ref value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
value = Array.Empty<T>();
|
||||
return;
|
||||
}
|
||||
|
||||
// T[] support overwrite
|
||||
if (value == null || value.Length != length)
|
||||
{
|
||||
value = new T[length];
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
T.Deserialize(ref this, ref value[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadPackableSpan<T>(ref Span<T?> value)
|
||||
where T : IMemoryPackable<T>
|
||||
{
|
||||
#if !NET7_0_OR_GREATER
|
||||
ReadSpan(ref value);
|
||||
return;
|
||||
#else
|
||||
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T>())
|
||||
{
|
||||
DangerousReadUnmanagedSpan(ref value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = default;
|
||||
return;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
value = Array.Empty<T>();
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.Length != length)
|
||||
{
|
||||
value = new T[length];
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
T.Deserialize(ref this, ref value[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UnmanagedArray/Span
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public T[]? ReadUnmanagedArray<T>()
|
||||
where T : unmanaged
|
||||
{
|
||||
return DangerousReadUnmanagedArray<T>();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanagedArray<T>(ref T[]? value)
|
||||
where T : unmanaged
|
||||
{
|
||||
DangerousReadUnmanagedArray<T>(ref value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadUnmanagedSpan<T>(ref Span<T> value)
|
||||
where T : unmanaged
|
||||
{
|
||||
DangerousReadUnmanagedSpan<T>(ref value);
|
||||
}
|
||||
|
||||
// T: should be unamanged type
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe T[]? DangerousReadUnmanagedArray<T>()
|
||||
{
|
||||
if (!TryReadCollectionHeader(out var length))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (length == 0) return Array.Empty<T>();
|
||||
|
||||
var byteCount = length * Unsafe.SizeOf<T>();
|
||||
ref var src = ref GetSpanReference(byteCount);
|
||||
var dest = AllocateUninitializedArray<T>(length);
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<T, byte>(ref GetArrayDataReference(dest)), ref src, (uint)byteCount);
|
||||
Advance(byteCount);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe void DangerousReadUnmanagedArray<T>(ref T[]? value)
|
||||
{
|
||||
if (!TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
value = Array.Empty<T>();
|
||||
return;
|
||||
}
|
||||
|
||||
var byteCount = length * Unsafe.SizeOf<T>();
|
||||
ref var src = ref GetSpanReference(byteCount);
|
||||
|
||||
if (value == null || value.Length != length)
|
||||
{
|
||||
value = AllocateUninitializedArray<T>(length);
|
||||
}
|
||||
|
||||
ref var dest = ref Unsafe.As<T, byte>(ref GetArrayDataReference(value));
|
||||
Unsafe.CopyBlockUnaligned(ref dest, ref src, (uint)byteCount);
|
||||
|
||||
Advance(byteCount);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe void DangerousReadUnmanagedSpan<T>(ref Span<T> value)
|
||||
{
|
||||
if (!TryReadCollectionHeader(out var length))
|
||||
{
|
||||
value = default;
|
||||
return;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
value = Array.Empty<T>();
|
||||
return;
|
||||
}
|
||||
|
||||
var byteCount = length * Unsafe.SizeOf<T>();
|
||||
ref var src = ref GetSpanReference(byteCount);
|
||||
|
||||
if (value == null || value.Length != length)
|
||||
{
|
||||
value = AllocateUninitializedArray<T>(length);
|
||||
}
|
||||
|
||||
ref var dest = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value));
|
||||
Unsafe.CopyBlockUnaligned(ref dest, ref src, (uint)byteCount);
|
||||
|
||||
Advance(byteCount);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadSpanWithoutReadLengthHeader<T>(int length, ref Span<T?> value)
|
||||
{
|
||||
if (length == 0)
|
||||
{
|
||||
value = Array.Empty<T>();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T>())
|
||||
{
|
||||
if (value.Length != length)
|
||||
{
|
||||
value = AllocateUninitializedArray<T>(length);
|
||||
}
|
||||
|
||||
var byteCount = length * Unsafe.SizeOf<T>();
|
||||
ref var src = ref GetSpanReference(byteCount);
|
||||
ref var dest = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)!);
|
||||
Unsafe.CopyBlockUnaligned(ref dest, ref src, (uint)byteCount);
|
||||
|
||||
Advance(byteCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value.Length != length)
|
||||
{
|
||||
value = new T[length];
|
||||
}
|
||||
|
||||
var formatter = GetFormatter<T>();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
formatter.Deserialize(ref this, ref value[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadPackableSpanWithoutReadLengthHeader<T>(int length, ref Span<T?> value)
|
||||
where T : IMemoryPackable<T>
|
||||
{
|
||||
#if !NET7_0_OR_GREATER
|
||||
ReadSpanWithoutReadLengthHeader(length, ref value);
|
||||
return;
|
||||
#else
|
||||
if (length == 0)
|
||||
{
|
||||
value = Array.Empty<T>();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T>())
|
||||
{
|
||||
if (value.Length != length)
|
||||
{
|
||||
value = AllocateUninitializedArray<T>(length);
|
||||
}
|
||||
|
||||
var byteCount = length * Unsafe.SizeOf<T>();
|
||||
ref var src = ref GetSpanReference(byteCount);
|
||||
ref var dest = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)!);
|
||||
Unsafe.CopyBlockUnaligned(ref dest, ref src, (uint)byteCount);
|
||||
|
||||
Advance(byteCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value.Length != length)
|
||||
{
|
||||
value = new T[length];
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
T.Deserialize(ref this, ref value[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe void DangerousReadUnmanagedSpanView<T>(out bool isNull, out ReadOnlySpan<byte> view)
|
||||
{
|
||||
if (!TryReadCollectionHeader(out var length))
|
||||
{
|
||||
isNull = true;
|
||||
view = default;
|
||||
return;
|
||||
}
|
||||
|
||||
isNull = false;
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
view = Array.Empty<byte>();
|
||||
return;
|
||||
}
|
||||
|
||||
var byteCount = length * Unsafe.SizeOf<T>();
|
||||
ref var src = ref GetSpanReference(byteCount);
|
||||
|
||||
var span = MemoryMarshal.CreateReadOnlySpan(ref src, byteCount);
|
||||
|
||||
Advance(byteCount);
|
||||
view = span; // safe until call next GetSpanReference
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 27df744bfc004694c9598738f9d32cce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace MemoryPack {
|
||||
|
||||
public static class MemoryPackReaderOptionalStatePool
|
||||
{
|
||||
static readonly ConcurrentQueue<MemoryPackReaderOptionalState> queue = new ConcurrentQueue<MemoryPackReaderOptionalState>();
|
||||
|
||||
public static MemoryPackReaderOptionalState Rent(MemoryPackSerializerOptions? options)
|
||||
{
|
||||
if (!queue.TryDequeue(out var state))
|
||||
{
|
||||
state = new MemoryPackReaderOptionalState();
|
||||
}
|
||||
|
||||
state.Init(options);
|
||||
return state;
|
||||
}
|
||||
|
||||
internal static void Return(MemoryPackReaderOptionalState state)
|
||||
{
|
||||
state.Reset();
|
||||
queue.Enqueue(state);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MemoryPackReaderOptionalState : IDisposable
|
||||
{
|
||||
readonly Dictionary<uint, object> refToObject;
|
||||
public MemoryPackSerializerOptions Options { get; private set; }
|
||||
|
||||
internal MemoryPackReaderOptionalState()
|
||||
{
|
||||
refToObject = new Dictionary<uint, object>();
|
||||
Options = null!;
|
||||
}
|
||||
|
||||
internal void Init(MemoryPackSerializerOptions? options)
|
||||
{
|
||||
Options = options ?? MemoryPackSerializerOptions.Default;
|
||||
}
|
||||
|
||||
public object GetObjectReference(uint id)
|
||||
{
|
||||
if (refToObject.TryGetValue(id, out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
MemoryPackSerializationException.ThrowMessage("Object is not found in this reference id:" + id);
|
||||
return null!;
|
||||
}
|
||||
|
||||
public void AddObjectReference(uint id, object value)
|
||||
{
|
||||
if (!refToObject.TryAdd(id, value))
|
||||
{
|
||||
MemoryPackSerializationException.ThrowMessage("Object is already added, id:" + id);
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
refToObject.Clear();
|
||||
Options = null!;
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
MemoryPackReaderOptionalStatePool.Return(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a381067d43337845bd228a2207155da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,448 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
namespace MemoryPack {
|
||||
|
||||
// VarInt, first sbyte is value or typeCode
|
||||
|
||||
// 0~127 = unsigned byte value
|
||||
// -1~-120 = signed byte value
|
||||
// -121 = byte
|
||||
// -122 = sbyte
|
||||
// -123 = ushort
|
||||
// -124 = short
|
||||
// -125 = uint
|
||||
// -126 = int
|
||||
// -127 = ulong
|
||||
// -128 = long
|
||||
|
||||
internal static class VarIntCodes
|
||||
{
|
||||
public const byte MaxSingleValue = 127;
|
||||
public const sbyte MinSingleValue = -120;
|
||||
|
||||
public const sbyte Byte = -121;
|
||||
public const sbyte SByte = -122;
|
||||
public const sbyte UInt16 = -123;
|
||||
public const sbyte Int16 = -124;
|
||||
public const sbyte UInt32 = -125;
|
||||
public const sbyte Int32 = -126;
|
||||
public const sbyte UInt64 = -127;
|
||||
public const sbyte Int64 = -128;
|
||||
}
|
||||
|
||||
public ref partial struct MemoryPackWriter
|
||||
{
|
||||
public void WriteVarInt(byte x)
|
||||
{
|
||||
if (x <= VarIntCodes.MaxSingleValue)
|
||||
{
|
||||
WriteUnmanaged((sbyte)x);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.Byte, x);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteVarInt(sbyte x)
|
||||
{
|
||||
if (VarIntCodes.MinSingleValue <= x)
|
||||
{
|
||||
WriteUnmanaged(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.SByte, x);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteVarInt(ushort x)
|
||||
{
|
||||
if (x <= VarIntCodes.MaxSingleValue)
|
||||
{
|
||||
WriteUnmanaged((sbyte)x);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.UInt16, (UInt16)x);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteVarInt(short x)
|
||||
{
|
||||
if (0 <= x)
|
||||
{
|
||||
if (x <= VarIntCodes.MaxSingleValue) // same as sbyte.MaxValue
|
||||
{
|
||||
WriteUnmanaged((sbyte)x);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.Int16, (Int16)x);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (VarIntCodes.MinSingleValue <= x)
|
||||
{
|
||||
WriteUnmanaged((sbyte)x);
|
||||
}
|
||||
else if (sbyte.MinValue <= x)
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.SByte, (SByte)x);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.Int16, (Int16)x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteVarInt(uint x)
|
||||
{
|
||||
if (x <= VarIntCodes.MaxSingleValue)
|
||||
{
|
||||
WriteUnmanaged((sbyte)x);
|
||||
}
|
||||
else if (x <= ushort.MaxValue)
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.UInt16, (UInt16)x);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.UInt32, (UInt32)x);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteVarInt(int x)
|
||||
{
|
||||
if (0 <= x)
|
||||
{
|
||||
if (x <= VarIntCodes.MaxSingleValue) // same as sbyte.MaxValue
|
||||
{
|
||||
WriteUnmanaged((sbyte)x);
|
||||
}
|
||||
else if (x <= short.MaxValue)
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.Int16, (Int16)x);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.Int32, (Int32)x);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (VarIntCodes.MinSingleValue <= x)
|
||||
{
|
||||
WriteUnmanaged((sbyte)x);
|
||||
}
|
||||
else if (sbyte.MinValue <= x)
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.SByte, (SByte)x);
|
||||
}
|
||||
else if (short.MinValue <= x)
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.Int16, (Int16)x);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.Int32, (Int32)x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteVarInt(ulong x)
|
||||
{
|
||||
if (x <= VarIntCodes.MaxSingleValue)
|
||||
{
|
||||
WriteUnmanaged((sbyte)x);
|
||||
}
|
||||
else if (x <= ushort.MaxValue)
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.UInt16, (UInt16)x);
|
||||
}
|
||||
else if (x <= uint.MaxValue)
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.UInt32, (UInt32)x);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.UInt64, (UInt64)x);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteVarInt(long x)
|
||||
{
|
||||
if (0 <= x)
|
||||
{
|
||||
if (x <= VarIntCodes.MaxSingleValue) // same as sbyte.MaxValue
|
||||
{
|
||||
WriteUnmanaged((sbyte)x);
|
||||
}
|
||||
else if (x <= short.MaxValue)
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.Int16, (Int16)x);
|
||||
}
|
||||
else if (x <= int.MaxValue)
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.Int32, (Int32)x);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.Int64, (Int64)x);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (VarIntCodes.MinSingleValue <= x)
|
||||
{
|
||||
WriteUnmanaged((sbyte)x);
|
||||
}
|
||||
else if (sbyte.MinValue <= x)
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.SByte, (SByte)x);
|
||||
}
|
||||
else if (short.MinValue <= x)
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.Int16, (Int16)x);
|
||||
}
|
||||
else if (int.MinValue <= x)
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.Int32, (Int32)x);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteUnmanaged(VarIntCodes.Int64, (Int64)x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ref partial struct MemoryPackReader
|
||||
{
|
||||
public byte ReadVarIntByte()
|
||||
{
|
||||
ReadUnmanaged(out sbyte typeCode);
|
||||
|
||||
switch (typeCode)
|
||||
{
|
||||
case VarIntCodes.Byte:
|
||||
return ReadUnmanaged<byte>();
|
||||
case VarIntCodes.SByte:
|
||||
return checked((byte)ReadUnmanaged<sbyte>());
|
||||
case VarIntCodes.UInt16:
|
||||
return checked((byte)ReadUnmanaged<byte>());
|
||||
case VarIntCodes.Int16:
|
||||
return checked((byte)ReadUnmanaged<short>());
|
||||
case VarIntCodes.UInt32:
|
||||
return checked((byte)ReadUnmanaged<uint>());
|
||||
case VarIntCodes.Int32:
|
||||
return checked((byte)ReadUnmanaged<int>());
|
||||
case VarIntCodes.UInt64:
|
||||
return checked((byte)ReadUnmanaged<ulong>());
|
||||
case VarIntCodes.Int64:
|
||||
return checked((byte)ReadUnmanaged<long>());
|
||||
default:
|
||||
return checked((byte)typeCode);
|
||||
}
|
||||
}
|
||||
|
||||
public sbyte ReadVarIntSByte()
|
||||
{
|
||||
ReadUnmanaged(out sbyte typeCode);
|
||||
|
||||
switch (typeCode)
|
||||
{
|
||||
case VarIntCodes.Byte:
|
||||
return checked((sbyte)ReadUnmanaged<byte>());
|
||||
case VarIntCodes.SByte:
|
||||
return ReadUnmanaged<sbyte>();
|
||||
case VarIntCodes.UInt16:
|
||||
return checked((sbyte)ReadUnmanaged<ushort>());
|
||||
case VarIntCodes.Int16:
|
||||
return checked((sbyte)ReadUnmanaged<short>());
|
||||
case VarIntCodes.UInt32:
|
||||
return checked((sbyte)ReadUnmanaged<uint>());
|
||||
case VarIntCodes.Int32:
|
||||
return checked((sbyte)ReadUnmanaged<int>());
|
||||
case VarIntCodes.UInt64:
|
||||
return checked((sbyte)ReadUnmanaged<ulong>());
|
||||
case VarIntCodes.Int64:
|
||||
return checked((sbyte)ReadUnmanaged<long>());
|
||||
default:
|
||||
return typeCode;
|
||||
}
|
||||
}
|
||||
|
||||
public ushort ReadVarIntUInt16()
|
||||
{
|
||||
ReadUnmanaged(out sbyte typeCode);
|
||||
|
||||
switch (typeCode)
|
||||
{
|
||||
case VarIntCodes.Byte:
|
||||
return ReadUnmanaged<byte>();
|
||||
case VarIntCodes.SByte:
|
||||
return checked((ushort)ReadUnmanaged<sbyte>());
|
||||
case VarIntCodes.UInt16:
|
||||
return ReadUnmanaged<ushort>();
|
||||
case VarIntCodes.Int16:
|
||||
return checked((ushort)ReadUnmanaged<short>());
|
||||
case VarIntCodes.UInt32:
|
||||
return checked((ushort)ReadUnmanaged<uint>());
|
||||
case VarIntCodes.Int32:
|
||||
return checked((ushort)ReadUnmanaged<int>());
|
||||
case VarIntCodes.UInt64:
|
||||
return checked((ushort)ReadUnmanaged<ulong>());
|
||||
case VarIntCodes.Int64:
|
||||
return checked((ushort)ReadUnmanaged<long>());
|
||||
default:
|
||||
return checked((ushort)typeCode);
|
||||
}
|
||||
}
|
||||
|
||||
public short ReadVarIntInt16()
|
||||
{
|
||||
ReadUnmanaged(out sbyte typeCode);
|
||||
|
||||
switch (typeCode)
|
||||
{
|
||||
case VarIntCodes.Byte:
|
||||
return ReadUnmanaged<byte>();
|
||||
case VarIntCodes.SByte:
|
||||
return ReadUnmanaged<sbyte>();
|
||||
case VarIntCodes.UInt16:
|
||||
return checked((short)ReadUnmanaged<ushort>());
|
||||
case VarIntCodes.Int16:
|
||||
return ReadUnmanaged<short>();
|
||||
case VarIntCodes.UInt32:
|
||||
return checked((short)ReadUnmanaged<uint>());
|
||||
case VarIntCodes.Int32:
|
||||
return checked((short)ReadUnmanaged<int>());
|
||||
case VarIntCodes.UInt64:
|
||||
return checked((short)ReadUnmanaged<ulong>());
|
||||
case VarIntCodes.Int64:
|
||||
return checked((short)ReadUnmanaged<long>());
|
||||
default:
|
||||
return typeCode;
|
||||
}
|
||||
}
|
||||
|
||||
public uint ReadVarIntUInt32()
|
||||
{
|
||||
ReadUnmanaged(out sbyte typeCode);
|
||||
|
||||
switch (typeCode)
|
||||
{
|
||||
case VarIntCodes.Byte:
|
||||
return ReadUnmanaged<byte>();
|
||||
case VarIntCodes.SByte:
|
||||
return checked((uint)ReadUnmanaged<sbyte>());
|
||||
case VarIntCodes.UInt16:
|
||||
return ReadUnmanaged<ushort>();
|
||||
case VarIntCodes.Int16:
|
||||
return checked((uint)ReadUnmanaged<short>());
|
||||
case VarIntCodes.UInt32:
|
||||
return ReadUnmanaged<uint>();
|
||||
case VarIntCodes.Int32:
|
||||
return checked((uint)ReadUnmanaged<int>());
|
||||
case VarIntCodes.UInt64:
|
||||
return checked((uint)ReadUnmanaged<ulong>());
|
||||
case VarIntCodes.Int64:
|
||||
return checked((uint)ReadUnmanaged<long>());
|
||||
default:
|
||||
return checked((uint)typeCode);
|
||||
}
|
||||
}
|
||||
|
||||
public int ReadVarIntInt32()
|
||||
{
|
||||
ReadUnmanaged(out sbyte typeCode);
|
||||
|
||||
switch (typeCode)
|
||||
{
|
||||
case VarIntCodes.Byte:
|
||||
return ReadUnmanaged<byte>();
|
||||
case VarIntCodes.SByte:
|
||||
return ReadUnmanaged<sbyte>();
|
||||
case VarIntCodes.UInt16:
|
||||
return ReadUnmanaged<ushort>();
|
||||
case VarIntCodes.Int16:
|
||||
return ReadUnmanaged<short>();
|
||||
case VarIntCodes.UInt32:
|
||||
return checked((int)ReadUnmanaged<uint>());
|
||||
case VarIntCodes.Int32:
|
||||
return ReadUnmanaged<int>();
|
||||
case VarIntCodes.UInt64:
|
||||
return checked((int)ReadUnmanaged<ulong>());
|
||||
case VarIntCodes.Int64:
|
||||
return checked((int)ReadUnmanaged<long>());
|
||||
default:
|
||||
return typeCode;
|
||||
}
|
||||
}
|
||||
|
||||
public ulong ReadVarIntUInt64()
|
||||
{
|
||||
ReadUnmanaged(out sbyte typeCode);
|
||||
|
||||
switch (typeCode)
|
||||
{
|
||||
case VarIntCodes.Byte:
|
||||
return ReadUnmanaged<byte>();
|
||||
case VarIntCodes.SByte:
|
||||
return checked((ulong)ReadUnmanaged<sbyte>());
|
||||
case VarIntCodes.UInt16:
|
||||
return ReadUnmanaged<ushort>();
|
||||
case VarIntCodes.Int16:
|
||||
return checked((ulong)ReadUnmanaged<short>());
|
||||
case VarIntCodes.UInt32:
|
||||
return ReadUnmanaged<uint>();
|
||||
case VarIntCodes.Int32:
|
||||
return checked((ulong)ReadUnmanaged<int>());
|
||||
case VarIntCodes.UInt64:
|
||||
return ReadUnmanaged<ulong>();
|
||||
case VarIntCodes.Int64:
|
||||
return checked((ulong)ReadUnmanaged<long>());
|
||||
default:
|
||||
return checked((ulong)typeCode);
|
||||
}
|
||||
}
|
||||
|
||||
public long ReadVarIntInt64()
|
||||
{
|
||||
ReadUnmanaged(out sbyte typeCode);
|
||||
|
||||
switch (typeCode)
|
||||
{
|
||||
case VarIntCodes.Byte:
|
||||
return ReadUnmanaged<byte>();
|
||||
case VarIntCodes.SByte:
|
||||
return ReadUnmanaged<sbyte>();
|
||||
case VarIntCodes.UInt16:
|
||||
return ReadUnmanaged<ushort>();
|
||||
case VarIntCodes.Int16:
|
||||
return ReadUnmanaged<short>();
|
||||
case VarIntCodes.UInt32:
|
||||
return ReadUnmanaged<uint>();
|
||||
case VarIntCodes.Int32:
|
||||
return ReadUnmanaged<int>();
|
||||
case VarIntCodes.UInt64:
|
||||
return checked((long)ReadUnmanaged<ulong>());
|
||||
case VarIntCodes.Int64:
|
||||
return ReadUnmanaged<long>();
|
||||
default:
|
||||
return typeCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a312341bf29b42429b858550384dd1a
|
||||
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
Loading…
x
Reference in New Issue
Block a user