gg.easy.airship 0.1.2136 → 0.1.2138
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Editor/Artifacts/AirshipLocalArtifactDatabase.cs +5 -1
- package/Editor/Artifacts/AirshipPrefabUtility.cs +9 -10
- package/Editor/TypescriptServices/Compiler/TypescriptCompilationService.cs +27 -3
- package/Editor/TypescriptServices/TypescriptServices.cs +1 -1
- package/Runtime/Code/Authentication/EasyAuthenticator.cs +5 -2
- package/Runtime/Code/Authentication/TransferData.cs +1 -0
- package/Runtime/Code/Luau/AirshipScript.cs +2 -0
- package/Runtime/Code/Luau/BinaryBlob.cs +4 -258
- package/Runtime/Code/LuauAPI/Bridge.cs +4 -0
- package/Runtime/Code/LuauAPI/ResourcesAPI.cs +1 -1
- package/Runtime/Code/Network/AirshipNetworkManager.cs +0 -2
- package/Runtime/Code/{RemoteConsole → Network}/ServerConsole.cs +159 -154
- package/Runtime/Code/{RemoteConsole → Network}/ServerConsole.cs.meta +2 -2
- package/Runtime/Code/Network/Simulation/AirshipSimulationManager.cs +13 -15
- package/Runtime/Code/Network/StateSystem/AirshipNetworkedStateManager.cs +11 -15
- package/Runtime/Code/Player/Character/MovementSystems/Character/CharacterMovement.cs +153 -16
- package/Runtime/Code/Player/Character/MovementSystems/Character/Structures/CharacterSnapshotData.cs +88 -19
- package/Runtime/Code/Player/PlayerInfo.cs +6 -2
- package/Runtime/Code/Player/PlayerManagerBridge.cs +3 -3
- package/Runtime/Code/Player/UserData.cs +1 -0
- package/Runtime/Code/TSCodeGen/TypeGenerator.cs +2 -1
- package/Runtime/Code/VoxelWorld/Airship.VoxelWorld.asmdef +2 -1
- package/Runtime/Code/VoxelWorld/VoxelCompressUtil.cs +26 -3
- package/Runtime/Code/VoxelWorld/VoxelWorld.cs +0 -17
- package/Runtime/Code/VoxelWorld/VoxelWorldChunk.cs +1 -1
- package/Runtime/Code/VoxelWorld/WorldSaveFile.cs +8 -6
- package/Runtime/Code/Zstd/Zstd.cs +125 -47
- package/Runtime/Code/Zstd/ZstdCompressStream.cs +147 -0
- package/Runtime/Code/Zstd/ZstdCompressStream.cs.meta +3 -0
- package/Runtime/Code/Zstd/ZstdDecompressStream.cs +196 -0
- package/Runtime/Code/Zstd/ZstdDecompressStream.cs.meta +3 -0
- package/Runtime/Code/Zstd/ZstdNative.cs +5 -5
- package/Runtime/Plugins/Android/libLuauPlugin.so +0 -0
- package/Runtime/Plugins/Linux/libLuauPlugin.so +0 -0
- package/Runtime/Plugins/Mac/LuauPlugin.bundle/Contents/Info.plist +1 -1
- package/Runtime/Plugins/Mac/LuauPlugin.bundle/Contents/MacOS/LuauPlugin +0 -0
- package/Runtime/Plugins/Windows/x64/LuauPlugin.dll +0 -0
- package/Runtime/Plugins/Windows/x64/LuauPlugin.pdb +0 -0
- package/Runtime/Plugins/iOS/LuauPluginIos.a +0 -0
- package/package.json +1 -1
- package/Runtime/Code/RemoteConsole/Airship.RemoteConsole.asmdef +0 -26
- package/Runtime/Code/RemoteConsole/Airship.RemoteConsole.asmdef.meta +0 -3
- package/Runtime/Code/RemoteConsole.meta +0 -3
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
using System;
|
|
2
|
-
using System.
|
|
3
|
-
|
|
2
|
+
using System.Buffers;
|
|
4
3
|
using static Code.Zstd.ZstdNative;
|
|
5
4
|
|
|
6
5
|
namespace Code.Zstd {
|
|
@@ -33,32 +32,85 @@ namespace Code.Zstd {
|
|
|
33
32
|
/// and <c>Zstd.MaxCompressionLevel</c>. Most use-cases should use <c>Zstd.DefaultCompressionLevel</c>.
|
|
34
33
|
/// </summary>
|
|
35
34
|
public byte[] Compress(byte[] data, int compressionLevel) {
|
|
36
|
-
return
|
|
35
|
+
return Compress(new ReadOnlySpan<byte>(data), compressionLevel);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// <summary>
|
|
39
|
+
/// Compress the data. The compression level can be between <c>Zstd.MinCompressionLevel</c>
|
|
40
|
+
/// and <c>Zstd.MaxCompressionLevel</c>. Most use-cases should use <c>Zstd.DefaultCompressionLevel</c>.
|
|
41
|
+
/// </summary>
|
|
42
|
+
public byte[] Compress(byte[] data, int start, int length, int compressionLevel) {
|
|
43
|
+
return Compress(new ReadOnlySpan<byte>(data, start, length), compressionLevel);
|
|
37
44
|
}
|
|
38
45
|
|
|
39
46
|
/// <summary>
|
|
40
47
|
/// Compress the data using the default compression level.
|
|
41
48
|
/// </summary>
|
|
42
49
|
public byte[] Compress(byte[] data) {
|
|
43
|
-
return
|
|
50
|
+
return Compress(new ReadOnlySpan<byte>(data));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// <summary>
|
|
54
|
+
/// Compress the data using the default compression level.
|
|
55
|
+
/// </summary>
|
|
56
|
+
public byte[] Compress(byte[] data, int start, int length) {
|
|
57
|
+
return Compress(new ReadOnlySpan<byte>(data, start, length));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/// <summary>
|
|
61
|
+
/// Compress the data using the default compression level.
|
|
62
|
+
/// </summary>
|
|
63
|
+
public byte[] Compress(ReadOnlySpan<byte> data) {
|
|
64
|
+
return Compress(data, DefaultCompressionLevel);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/// <summary>
|
|
68
|
+
/// Compress the data. The compression level can be between <c>Zstd.MinCompressionLevel</c>
|
|
69
|
+
/// and <c>Zstd.MaxCompressionLevel</c>. Most use-cases should use <c>Zstd.DefaultCompressionLevel</c>.
|
|
70
|
+
/// </summary>
|
|
71
|
+
public byte[] Compress(ReadOnlySpan<byte> data, int compressionLevel) {
|
|
72
|
+
return CompressData(data, compressionLevel, _ctx);
|
|
44
73
|
}
|
|
45
74
|
|
|
46
75
|
/// <summary>
|
|
47
76
|
/// Decompress the data.
|
|
48
77
|
/// </summary>
|
|
49
78
|
public byte[] Decompress(byte[] data) {
|
|
79
|
+
return Decompress(new ReadOnlySpan<byte>(data));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/// <summary>
|
|
83
|
+
/// Decompress the data.
|
|
84
|
+
/// </summary>
|
|
85
|
+
public byte[] Decompress(byte[] data, int start, int length) {
|
|
86
|
+
return Decompress(new ReadOnlySpan<byte>(data, start, length));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/// <summary>
|
|
90
|
+
/// Decompress the data.
|
|
91
|
+
/// </summary>
|
|
92
|
+
public byte[] Decompress(ReadOnlySpan<byte> data) {
|
|
50
93
|
return DecompressData(data, _ctx);
|
|
51
94
|
}
|
|
52
95
|
|
|
53
96
|
public void Dispose() {
|
|
97
|
+
Dispose(true);
|
|
98
|
+
GC.SuppressFinalize(this);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
protected virtual void Dispose(bool disposing) {
|
|
54
102
|
_ctx.Dispose();
|
|
55
103
|
}
|
|
56
104
|
|
|
105
|
+
~Zstd() {
|
|
106
|
+
Dispose(false);
|
|
107
|
+
}
|
|
108
|
+
|
|
57
109
|
/// <summary>
|
|
58
110
|
/// Compress the bytes. The compression level can be between <c>Zstd.MinCompressionLevel</c>
|
|
59
111
|
/// and <c>Zstd.MaxCompressionLevel</c>. Most use-cases should use <c>Zstd.DefaultCompressionLevel</c>.
|
|
60
112
|
/// </summary>
|
|
61
|
-
public static byte[] CompressData(byte
|
|
113
|
+
public static byte[] CompressData(ReadOnlySpan<byte> data, int compressionLevel, ZstdContext ctx = null) {
|
|
62
114
|
var bound = ZSTD_compressBound((ulong)data.Length);
|
|
63
115
|
if (ZSTD_isError(bound)) {
|
|
64
116
|
throw new ZstdException(bound);
|
|
@@ -72,33 +124,34 @@ namespace Code.Zstd {
|
|
|
72
124
|
/// <summary>
|
|
73
125
|
/// Decompress the bytes.
|
|
74
126
|
/// </summary>
|
|
75
|
-
public static byte[] DecompressData(byte
|
|
76
|
-
|
|
77
|
-
|
|
127
|
+
public static unsafe byte[] DecompressData(ReadOnlySpan<byte> data, ZstdContext ctx = null) {
|
|
128
|
+
ulong rSize;
|
|
129
|
+
fixed (byte* src = data) {
|
|
130
|
+
rSize = ZSTD_getFrameContentSize(new IntPtr(src), (ulong)data.Length);
|
|
131
|
+
}
|
|
78
132
|
if (ZSTD_isError(rSize)) {
|
|
79
|
-
dataHandle.Free();
|
|
80
133
|
throw new ZstdException(rSize);
|
|
81
134
|
}
|
|
82
135
|
byte[] decompressedData;
|
|
83
136
|
if (rSize <= MaxStackSize) {
|
|
84
|
-
decompressedData = DecompressWithStack(data,
|
|
137
|
+
decompressedData = DecompressWithStack(data, rSize, ctx);
|
|
85
138
|
} else {
|
|
86
|
-
decompressedData = DecompressWithHeap(data,
|
|
139
|
+
decompressedData = DecompressWithHeap(data, rSize, ctx);
|
|
87
140
|
}
|
|
88
|
-
dataHandle.Free();
|
|
89
141
|
return decompressedData;
|
|
90
142
|
}
|
|
91
143
|
|
|
92
|
-
private static unsafe byte[] DecompressWithStack(byte
|
|
144
|
+
private static unsafe byte[] DecompressWithStack(ReadOnlySpan<byte> data, ulong rSize, ZstdContext ctx) {
|
|
93
145
|
var decompressedData = stackalloc byte[(int)rSize];
|
|
94
146
|
ulong decompressedSize;
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
147
|
+
fixed (byte* src = data) {
|
|
148
|
+
if (ctx != null) {
|
|
149
|
+
decompressedSize = ZSTD_decompressDCtx(ctx.Dctx, new IntPtr(decompressedData), rSize, new IntPtr(src), (ulong)data.Length);
|
|
150
|
+
} else {
|
|
151
|
+
decompressedSize = ZSTD_decompress(new IntPtr(decompressedData), rSize, new IntPtr(src), (ulong)data.Length);
|
|
152
|
+
}
|
|
99
153
|
}
|
|
100
154
|
if (ZSTD_isError(decompressedSize)) {
|
|
101
|
-
dataHandle.Free();
|
|
102
155
|
throw new ZstdException(decompressedSize);
|
|
103
156
|
}
|
|
104
157
|
var decompressedBuffer = new byte[decompressedSize];
|
|
@@ -108,35 +161,36 @@ namespace Code.Zstd {
|
|
|
108
161
|
return decompressedBuffer;
|
|
109
162
|
}
|
|
110
163
|
|
|
111
|
-
private static byte[] DecompressWithHeap(byte
|
|
164
|
+
private static unsafe byte[] DecompressWithHeap(ReadOnlySpan<byte> data, ulong rSize, ZstdContext ctx) {
|
|
112
165
|
var allocDst = ctx == null || rSize > (ulong)ctx.ScratchBuffer.Length;
|
|
113
166
|
var decompressedData = allocDst ? new byte[rSize] : ctx.ScratchBuffer;
|
|
114
|
-
var dstHandle = GCHandle.Alloc(decompressedData, GCHandleType.Pinned);
|
|
115
167
|
ulong decompressedSize;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
168
|
+
fixed (byte* src = data) {
|
|
169
|
+
fixed (byte* dst = decompressedData) {
|
|
170
|
+
if (ctx != null) {
|
|
171
|
+
decompressedSize = ZSTD_decompressDCtx(ctx.Dctx, new IntPtr(dst), rSize, new IntPtr(src), (ulong)data.Length);
|
|
172
|
+
} else {
|
|
173
|
+
decompressedSize = ZSTD_decompress(new IntPtr(dst), rSize, new IntPtr(src), (ulong)data.Length);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
120
176
|
}
|
|
121
|
-
dstHandle.Free();
|
|
122
177
|
if (ZSTD_isError(decompressedSize)) {
|
|
123
|
-
dataHandle.Free();
|
|
124
178
|
throw new ZstdException(decompressedSize);
|
|
125
179
|
}
|
|
126
180
|
Array.Resize(ref decompressedData, (int)decompressedSize);
|
|
127
181
|
return decompressedData;
|
|
128
182
|
}
|
|
129
183
|
|
|
130
|
-
private static unsafe byte[] CompressWithStack(byte
|
|
184
|
+
private static unsafe byte[] CompressWithStack(ReadOnlySpan<byte> data, ulong bound, int compressionLevel, ZstdContext ctx) {
|
|
131
185
|
var dst = stackalloc byte[(int)bound];
|
|
132
|
-
var srcHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
|
133
186
|
ulong compressedSize;
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
187
|
+
fixed (byte* src = data) {
|
|
188
|
+
if (ctx != null) {
|
|
189
|
+
compressedSize = ZSTD_compressCCtx(ctx.Cctx, new IntPtr(dst), bound, new IntPtr(src), (ulong)data.Length, compressionLevel);
|
|
190
|
+
} else {
|
|
191
|
+
compressedSize = ZSTD_compress(new IntPtr(dst), bound, new IntPtr(src), (ulong)data.Length, compressionLevel);
|
|
192
|
+
}
|
|
138
193
|
}
|
|
139
|
-
srcHandle.Free();
|
|
140
194
|
if (ZSTD_isError(compressedSize)) {
|
|
141
195
|
throw new ZstdException(compressedSize);
|
|
142
196
|
}
|
|
@@ -147,40 +201,59 @@ namespace Code.Zstd {
|
|
|
147
201
|
return compressedBuffer;
|
|
148
202
|
}
|
|
149
203
|
|
|
150
|
-
private static byte[] CompressWithHeap(byte
|
|
204
|
+
private static unsafe byte[] CompressWithHeap(ReadOnlySpan<byte> data, ulong bound, int compressionLevel, ZstdContext ctx) {
|
|
151
205
|
var allocDst = ctx == null || bound > (ulong)ctx.ScratchBuffer.Length;
|
|
152
|
-
var
|
|
153
|
-
var dstHandle = GCHandle.Alloc(dst, GCHandleType.Pinned);
|
|
154
|
-
var srcHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
|
206
|
+
var dstBuf = allocDst ? new byte[bound] : ctx.ScratchBuffer;
|
|
155
207
|
ulong compressedSize;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
208
|
+
fixed (byte* src = data) {
|
|
209
|
+
fixed (byte* dst = dstBuf) {
|
|
210
|
+
if (ctx != null) {
|
|
211
|
+
compressedSize = ZSTD_compressCCtx(ctx.Cctx, new IntPtr(dst), bound, new IntPtr(src), (ulong)data.Length, compressionLevel);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
compressedSize = ZSTD_compress(new IntPtr(dst), bound, new IntPtr(src), (ulong)data.Length, compressionLevel);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
160
217
|
}
|
|
161
|
-
dstHandle.Free();
|
|
162
|
-
srcHandle.Free();
|
|
163
218
|
if (ZSTD_isError(compressedSize)) {
|
|
164
219
|
throw new ZstdException(compressedSize);
|
|
165
220
|
}
|
|
166
|
-
Array.Resize(ref
|
|
167
|
-
return
|
|
221
|
+
Array.Resize(ref dstBuf, (int)compressedSize);
|
|
222
|
+
return dstBuf;
|
|
168
223
|
}
|
|
169
224
|
}
|
|
170
225
|
|
|
171
|
-
public class ZstdContext : IDisposable {
|
|
226
|
+
public sealed class ZstdContext : IDisposable {
|
|
172
227
|
internal readonly byte[] ScratchBuffer;
|
|
173
228
|
|
|
174
229
|
internal readonly IntPtr Cctx;
|
|
175
230
|
internal readonly IntPtr Dctx;
|
|
231
|
+
|
|
232
|
+
private bool _disposed;
|
|
176
233
|
|
|
177
234
|
public ZstdContext(ulong scratchBufferSize) {
|
|
178
|
-
ScratchBuffer =
|
|
235
|
+
ScratchBuffer = ArrayPool<byte>.Shared.Rent((int)scratchBufferSize);
|
|
179
236
|
Cctx = ZSTD_createCCtx();
|
|
180
237
|
Dctx = ZSTD_createDCtx();
|
|
181
238
|
}
|
|
182
239
|
|
|
240
|
+
~ZstdContext() {
|
|
241
|
+
Dispose(false);
|
|
242
|
+
}
|
|
243
|
+
|
|
183
244
|
public void Dispose() {
|
|
245
|
+
Dispose(true);
|
|
246
|
+
GC.SuppressFinalize(this);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private void Dispose(bool disposing) {
|
|
250
|
+
if (_disposed) return;
|
|
251
|
+
_disposed = true;
|
|
252
|
+
|
|
253
|
+
if (disposing) {
|
|
254
|
+
ArrayPool<byte>.Shared.Return(ScratchBuffer);
|
|
255
|
+
}
|
|
256
|
+
|
|
184
257
|
ZSTD_freeCCtx(Cctx);
|
|
185
258
|
ZSTD_freeDCtx(Dctx);
|
|
186
259
|
}
|
|
@@ -189,4 +262,9 @@ namespace Code.Zstd {
|
|
|
189
262
|
public class ZstdException : Exception {
|
|
190
263
|
public ZstdException(ulong code) : base(ZSTD_getErrorName(code)) { }
|
|
191
264
|
}
|
|
265
|
+
|
|
266
|
+
public class ZstdStreamException : Exception {
|
|
267
|
+
public ZstdStreamException(string message) : base(message) { }
|
|
268
|
+
public ZstdStreamException(ulong code) : this(ZSTD_getErrorName(code)) { }
|
|
269
|
+
}
|
|
192
270
|
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Buffers;
|
|
3
|
+
using System.IO;
|
|
4
|
+
using System.Runtime.InteropServices;
|
|
5
|
+
using static Code.Zstd.ZstdNative;
|
|
6
|
+
|
|
7
|
+
namespace Code.Zstd {
|
|
8
|
+
/// <summary>
|
|
9
|
+
/// Provides methods for compressing streams using the zstd algorithm.
|
|
10
|
+
/// </summary>
|
|
11
|
+
public sealed class ZstdCompressStream : Stream {
|
|
12
|
+
public override bool CanRead => false;
|
|
13
|
+
public override bool CanSeek => false;
|
|
14
|
+
public override bool CanWrite => true;
|
|
15
|
+
public override long Length => _compressedStream.Length;
|
|
16
|
+
public override long Position { get; set; }
|
|
17
|
+
|
|
18
|
+
private readonly Stream _compressedStream;
|
|
19
|
+
private readonly bool _leaveOpen;
|
|
20
|
+
|
|
21
|
+
private IntPtr _cctx;
|
|
22
|
+
private GCHandle _outHandle;
|
|
23
|
+
private readonly byte[] _bufOut;
|
|
24
|
+
private readonly ulong _bufOutSize;
|
|
25
|
+
|
|
26
|
+
private bool _disposed;
|
|
27
|
+
|
|
28
|
+
/// <summary>
|
|
29
|
+
/// Constructs a new ZstdCompressionStream.
|
|
30
|
+
/// </summary>
|
|
31
|
+
/// <param name="compressedStream">The stream to which compressed data is written.</param>
|
|
32
|
+
/// <param name="leaveOpen">Optionally leave the <c>compressedStream</c> open after closing (defaults to <c>false</c>).</param>
|
|
33
|
+
public ZstdCompressStream(Stream compressedStream, bool leaveOpen = false) : this(compressedStream, Zstd.DefaultCompressionLevel, leaveOpen) { }
|
|
34
|
+
|
|
35
|
+
/// <summary>
|
|
36
|
+
/// Constructs a new ZstdCompressionStream.
|
|
37
|
+
/// </summary>
|
|
38
|
+
/// <param name="compressedStream">The stream to which compressed data is written.</param>
|
|
39
|
+
/// <param name="compressionLevel">The zstd compression level. This should be in the range of <c>Zstd.MinCompressionLevel</c> and <c>Zstd.MaxCompressionLevel</c>. Most use-cases should use <c>Zstd.DefaultCompressionLevel</c>.</param>
|
|
40
|
+
/// <param name="leaveOpen">Optionally leave the <c>compressedStream</c> open after closing (defaults to <c>false</c>).</param>
|
|
41
|
+
public ZstdCompressStream(Stream compressedStream, int compressionLevel, bool leaveOpen = false) {
|
|
42
|
+
_compressedStream = compressedStream;
|
|
43
|
+
_leaveOpen = leaveOpen;
|
|
44
|
+
|
|
45
|
+
_cctx = ZSTD_createCCtx();
|
|
46
|
+
|
|
47
|
+
_bufOutSize = ZSTD_CStreamOutSize();
|
|
48
|
+
_bufOut = ArrayPool<byte>.Shared.Rent((int)_bufOutSize);
|
|
49
|
+
|
|
50
|
+
_outHandle = GCHandle.Alloc(_bufOut, GCHandleType.Pinned);
|
|
51
|
+
|
|
52
|
+
ZSTD_CCtx_setParameter(_cctx, ZSTD_cParameter.ZSTD_c_compressionLevel, compressionLevel);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public override void Flush() {
|
|
56
|
+
var finished = false;
|
|
57
|
+
do {
|
|
58
|
+
var output = new ZSTD_outBuffer {
|
|
59
|
+
dst = _outHandle.AddrOfPinnedObject(),
|
|
60
|
+
size = _bufOutSize,
|
|
61
|
+
pos = 0,
|
|
62
|
+
};
|
|
63
|
+
var remaining = ZSTD_flushStream(_cctx, ref output);
|
|
64
|
+
if (ZSTD_isError(remaining)) {
|
|
65
|
+
throw new ZstdStreamException(remaining);
|
|
66
|
+
}
|
|
67
|
+
_compressedStream.Write(_bufOut, 0, (int)output.pos);
|
|
68
|
+
finished = remaining == 0;
|
|
69
|
+
} while (!finished);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public override int Read(byte[] buffer, int offset, int count) {
|
|
73
|
+
throw new NotSupportedException();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public override long Seek(long offset, SeekOrigin origin) {
|
|
77
|
+
throw new NotSupportedException();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public override void SetLength(long value) {
|
|
81
|
+
throw new NotSupportedException();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public override void Write(byte[] buffer, int offset, int count) {
|
|
85
|
+
WriteCore(new ReadOnlySpan<byte>(buffer, offset, count));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public override void Write(ReadOnlySpan<byte> buffer) {
|
|
89
|
+
WriteCore(buffer);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private unsafe void WriteCore(ReadOnlySpan<byte> buffer) {
|
|
93
|
+
fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) {
|
|
94
|
+
var input = new ZSTD_inBuffer {
|
|
95
|
+
src = (IntPtr)bufferPtr,
|
|
96
|
+
size = (ulong)buffer.Length,
|
|
97
|
+
pos = 0,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
do {
|
|
101
|
+
var output = new ZSTD_outBuffer {
|
|
102
|
+
dst = _outHandle.AddrOfPinnedObject(),
|
|
103
|
+
size = _bufOutSize,
|
|
104
|
+
pos = 0,
|
|
105
|
+
};
|
|
106
|
+
var ret = ZSTD_compressStream(_cctx, ref output, ref input);
|
|
107
|
+
if (ZSTD_isError(ret)) {
|
|
108
|
+
throw new ZstdStreamException(ret);
|
|
109
|
+
}
|
|
110
|
+
_compressedStream.Write(_bufOut, 0, (int)output.pos);
|
|
111
|
+
} while (input.pos != input.size);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
protected override void Dispose(bool disposing) {
|
|
116
|
+
base.Dispose(disposing);
|
|
117
|
+
if (disposing && !_disposed) {
|
|
118
|
+
var finished = false;
|
|
119
|
+
do {
|
|
120
|
+
var output = new ZSTD_outBuffer {
|
|
121
|
+
dst = _outHandle.AddrOfPinnedObject(),
|
|
122
|
+
size = _bufOutSize,
|
|
123
|
+
pos = 0,
|
|
124
|
+
};
|
|
125
|
+
var remaining = ZSTD_endStream(_cctx, ref output);
|
|
126
|
+
if (ZSTD_isError(remaining)) {
|
|
127
|
+
throw new ZstdStreamException(remaining);
|
|
128
|
+
}
|
|
129
|
+
_compressedStream.Write(_bufOut, 0, (int)output.pos);
|
|
130
|
+
finished = remaining == 0;
|
|
131
|
+
} while (!finished);
|
|
132
|
+
|
|
133
|
+
_outHandle.Free();
|
|
134
|
+
ArrayPool<byte>.Shared.Return(_bufOut);
|
|
135
|
+
|
|
136
|
+
if (!_leaveOpen) {
|
|
137
|
+
_compressedStream.Close();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
ZSTD_freeCCtx(_cctx);
|
|
142
|
+
_cctx = IntPtr.Zero;
|
|
143
|
+
|
|
144
|
+
_disposed = true;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Buffers;
|
|
3
|
+
using System.IO;
|
|
4
|
+
using System.Runtime.InteropServices;
|
|
5
|
+
using static Code.Zstd.ZstdNative;
|
|
6
|
+
|
|
7
|
+
namespace Code.Zstd {
|
|
8
|
+
/// <summary>
|
|
9
|
+
/// Provides methods for decompressing streams using the zstd algorithm.
|
|
10
|
+
/// </summary>
|
|
11
|
+
public sealed class ZstdDecompressStream : Stream {
|
|
12
|
+
public override bool CanRead => true;
|
|
13
|
+
public override bool CanSeek => false;
|
|
14
|
+
public override bool CanWrite => false;
|
|
15
|
+
public override long Length => _compressedStream.Length;
|
|
16
|
+
public override long Position { get; set; }
|
|
17
|
+
|
|
18
|
+
private readonly Stream _compressedStream;
|
|
19
|
+
private readonly bool _leaveOpen;
|
|
20
|
+
|
|
21
|
+
private IntPtr _dctx;
|
|
22
|
+
private GCHandle _outHandle;
|
|
23
|
+
private GCHandle _inHandle;
|
|
24
|
+
private readonly byte[] _bufOut;
|
|
25
|
+
private readonly byte[] _bufIn;
|
|
26
|
+
private readonly ulong _bufOutSize;
|
|
27
|
+
private readonly ulong _bufInSize;
|
|
28
|
+
|
|
29
|
+
private readonly MemoryStream _bufOutStream;
|
|
30
|
+
|
|
31
|
+
private int _currentBufOutOffset;
|
|
32
|
+
private int _currentBufIn;
|
|
33
|
+
|
|
34
|
+
private bool _disposed;
|
|
35
|
+
|
|
36
|
+
/// <summary>
|
|
37
|
+
/// Constructs a new ZstdDecompressionStream.
|
|
38
|
+
/// </summary>
|
|
39
|
+
/// <param name="compressedStream">The source stream from which compressed data is decompressed.</param>
|
|
40
|
+
/// <param name="leaveOpen">Optionally leave the <c>compressedStream</c> open after closing (defaults to <c>false</c>).</param>
|
|
41
|
+
public ZstdDecompressStream(Stream compressedStream, bool leaveOpen = false) {
|
|
42
|
+
_compressedStream = compressedStream;
|
|
43
|
+
_leaveOpen = leaveOpen;
|
|
44
|
+
|
|
45
|
+
_dctx = ZSTD_createDCtx();
|
|
46
|
+
|
|
47
|
+
_bufOutSize = ZSTD_DStreamOutSize();
|
|
48
|
+
_bufInSize = ZSTD_DStreamInSize();
|
|
49
|
+
|
|
50
|
+
_bufOut = ArrayPool<byte>.Shared.Rent((int)_bufOutSize);
|
|
51
|
+
_bufIn = ArrayPool<byte>.Shared.Rent((int)_bufInSize);
|
|
52
|
+
|
|
53
|
+
_outHandle = GCHandle.Alloc(_bufOut, GCHandleType.Pinned);
|
|
54
|
+
_inHandle = GCHandle.Alloc(_bufIn, GCHandleType.Pinned);
|
|
55
|
+
|
|
56
|
+
_bufOutStream = new MemoryStream((int)ZSTD_DStreamOutSize());
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public override void Flush() {
|
|
60
|
+
throw new NotSupportedException();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public override int Read(byte[] buffer, int offset, int count) {
|
|
64
|
+
return ReadCore(new Span<byte>(buffer, offset, count));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public override int Read(Span<byte> buffer) {
|
|
68
|
+
return ReadCore(buffer);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private int ReadCore(Span<byte> buffer) {
|
|
72
|
+
var read = 0;
|
|
73
|
+
var lastRet = 0ul;
|
|
74
|
+
var streamEmpty = false;
|
|
75
|
+
var bufferOffset = 0;
|
|
76
|
+
|
|
77
|
+
if (buffer.IsEmpty) {
|
|
78
|
+
throw new ZstdStreamException("Empty buffer");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
while (true) {
|
|
82
|
+
if (_bufOutStream.Length > 0) {
|
|
83
|
+
var len = Math.Min(buffer.Length, (int)(_bufOutStream.Length - _currentBufOutOffset));
|
|
84
|
+
_bufOutStream.Seek(_currentBufOutOffset, SeekOrigin.Begin);
|
|
85
|
+
var bufOutRead = _bufOutStream.Read(buffer.Slice(bufferOffset, len));
|
|
86
|
+
if (bufOutRead != len) {
|
|
87
|
+
throw new ZstdStreamException("Failed to read full amount into buffer");
|
|
88
|
+
}
|
|
89
|
+
_currentBufOutOffset += len;
|
|
90
|
+
bufferOffset += len;
|
|
91
|
+
read += len;
|
|
92
|
+
|
|
93
|
+
if (_currentBufOutOffset == _bufOutStream.Length) {
|
|
94
|
+
_currentBufOutOffset = 0;
|
|
95
|
+
_bufOutStream.Seek(0, SeekOrigin.Begin);
|
|
96
|
+
_bufOutStream.SetLength(0);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (len == buffer.Length) {
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (_bufOutStream.Length == 0) {
|
|
105
|
+
if (_currentBufIn == 0) {
|
|
106
|
+
var bytesFromStream = ReadInCompressedChunkFromStream();
|
|
107
|
+
streamEmpty = bytesFromStream == 0;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (!streamEmpty) {
|
|
111
|
+
lastRet = Decompress();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (streamEmpty && _bufOutStream.Length == 0) {
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (streamEmpty && _bufOutStream.Length == 0 && lastRet != 0) {
|
|
121
|
+
throw new ZstdStreamException($"EOF before end of stream: {lastRet}");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return read;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private ulong Decompress() {
|
|
128
|
+
var lastRet = 0ul;
|
|
129
|
+
|
|
130
|
+
var input = new ZSTD_inBuffer {
|
|
131
|
+
src = _inHandle.AddrOfPinnedObject(),
|
|
132
|
+
size = (ulong)_currentBufIn,
|
|
133
|
+
pos = 0,
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
while (input.pos < input.size) {
|
|
137
|
+
var output = new ZSTD_outBuffer {
|
|
138
|
+
dst = _outHandle.AddrOfPinnedObject(),
|
|
139
|
+
size = _bufOutSize,
|
|
140
|
+
pos = 0,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
lastRet = ZSTD_decompressStream(_dctx, ref output, ref input);
|
|
144
|
+
if (ZSTD_isError(lastRet)) {
|
|
145
|
+
throw new ZstdStreamException(lastRet);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
_bufOutStream.Write(_bufOut, 0, (int)output.pos);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
_currentBufIn = 0;
|
|
152
|
+
|
|
153
|
+
return lastRet;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private int ReadInCompressedChunkFromStream() {
|
|
157
|
+
var streamRead = 0;
|
|
158
|
+
if (_currentBufIn < (int)_bufInSize) {
|
|
159
|
+
streamRead = _compressedStream.Read(_bufIn, _currentBufIn, (int)_bufInSize - _currentBufIn);
|
|
160
|
+
_currentBufIn += streamRead;
|
|
161
|
+
}
|
|
162
|
+
return streamRead;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
public override long Seek(long offset, SeekOrigin origin) {
|
|
166
|
+
throw new NotSupportedException();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
public override void SetLength(long value) {
|
|
170
|
+
throw new NotSupportedException();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
public override void Write(byte[] buffer, int offset, int count) {
|
|
174
|
+
throw new NotSupportedException();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
protected override void Dispose(bool disposing) {
|
|
178
|
+
base.Dispose(disposing);
|
|
179
|
+
if (disposing && !_disposed) {
|
|
180
|
+
_outHandle.Free();
|
|
181
|
+
_inHandle.Free();
|
|
182
|
+
ArrayPool<byte>.Shared.Return(_bufOut);
|
|
183
|
+
ArrayPool<byte>.Shared.Return(_bufIn);
|
|
184
|
+
if (!_leaveOpen) {
|
|
185
|
+
_compressedStream.Close();
|
|
186
|
+
}
|
|
187
|
+
_bufOutStream.Dispose();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
ZSTD_freeDCtx(_dctx);
|
|
191
|
+
_dctx = IntPtr.Zero;
|
|
192
|
+
|
|
193
|
+
_disposed = true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
@@ -327,7 +327,7 @@ namespace Code.Zstd {
|
|
|
327
327
|
#else
|
|
328
328
|
[DllImport("LuauPlugin")]
|
|
329
329
|
#endif
|
|
330
|
-
internal static extern ulong ZSTD_compressStream2(IntPtr cctx, ZSTD_outBuffer output, ZSTD_inBuffer input, ZSTD_EndDirective endOp);
|
|
330
|
+
internal static extern ulong ZSTD_compressStream2(IntPtr cctx, ref ZSTD_outBuffer output, ref ZSTD_inBuffer input, ZSTD_EndDirective endOp);
|
|
331
331
|
|
|
332
332
|
#if UNITY_IPHONE
|
|
333
333
|
[DllImport("__Internal")]
|
|
@@ -355,21 +355,21 @@ namespace Code.Zstd {
|
|
|
355
355
|
#else
|
|
356
356
|
[DllImport("LuauPlugin")]
|
|
357
357
|
#endif
|
|
358
|
-
internal static extern ulong ZSTD_compressStream(IntPtr zcs, ZSTD_outBuffer output, ZSTD_inBuffer input);
|
|
358
|
+
internal static extern ulong ZSTD_compressStream(IntPtr zcs, ref ZSTD_outBuffer output, ref ZSTD_inBuffer input);
|
|
359
359
|
|
|
360
360
|
#if UNITY_IPHONE
|
|
361
361
|
[DllImport("__Internal")]
|
|
362
362
|
#else
|
|
363
363
|
[DllImport("LuauPlugin")]
|
|
364
364
|
#endif
|
|
365
|
-
internal static extern ulong ZSTD_flushStream(IntPtr zcs, ZSTD_outBuffer output);
|
|
365
|
+
internal static extern ulong ZSTD_flushStream(IntPtr zcs, ref ZSTD_outBuffer output);
|
|
366
366
|
|
|
367
367
|
#if UNITY_IPHONE
|
|
368
368
|
[DllImport("__Internal")]
|
|
369
369
|
#else
|
|
370
370
|
[DllImport("LuauPlugin")]
|
|
371
371
|
#endif
|
|
372
|
-
internal static extern ulong ZSTD_endStream(IntPtr zcs, ZSTD_outBuffer output);
|
|
372
|
+
internal static extern ulong ZSTD_endStream(IntPtr zcs, ref ZSTD_outBuffer output);
|
|
373
373
|
|
|
374
374
|
#if UNITY_IPHONE
|
|
375
375
|
[DllImport("__Internal")]
|
|
@@ -397,7 +397,7 @@ namespace Code.Zstd {
|
|
|
397
397
|
#else
|
|
398
398
|
[DllImport("LuauPlugin")]
|
|
399
399
|
#endif
|
|
400
|
-
internal static extern ulong ZSTD_decompressStream(IntPtr zds, ZSTD_outBuffer output, ZSTD_inBuffer input);
|
|
400
|
+
internal static extern ulong ZSTD_decompressStream(IntPtr zds, ref ZSTD_outBuffer output, ref ZSTD_inBuffer input);
|
|
401
401
|
|
|
402
402
|
#if UNITY_IPHONE
|
|
403
403
|
[DllImport("__Internal")]
|
|
Binary file
|
|
Binary file
|