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.
Files changed (43) hide show
  1. package/Editor/Artifacts/AirshipLocalArtifactDatabase.cs +5 -1
  2. package/Editor/Artifacts/AirshipPrefabUtility.cs +9 -10
  3. package/Editor/TypescriptServices/Compiler/TypescriptCompilationService.cs +27 -3
  4. package/Editor/TypescriptServices/TypescriptServices.cs +1 -1
  5. package/Runtime/Code/Authentication/EasyAuthenticator.cs +5 -2
  6. package/Runtime/Code/Authentication/TransferData.cs +1 -0
  7. package/Runtime/Code/Luau/AirshipScript.cs +2 -0
  8. package/Runtime/Code/Luau/BinaryBlob.cs +4 -258
  9. package/Runtime/Code/LuauAPI/Bridge.cs +4 -0
  10. package/Runtime/Code/LuauAPI/ResourcesAPI.cs +1 -1
  11. package/Runtime/Code/Network/AirshipNetworkManager.cs +0 -2
  12. package/Runtime/Code/{RemoteConsole → Network}/ServerConsole.cs +159 -154
  13. package/Runtime/Code/{RemoteConsole → Network}/ServerConsole.cs.meta +2 -2
  14. package/Runtime/Code/Network/Simulation/AirshipSimulationManager.cs +13 -15
  15. package/Runtime/Code/Network/StateSystem/AirshipNetworkedStateManager.cs +11 -15
  16. package/Runtime/Code/Player/Character/MovementSystems/Character/CharacterMovement.cs +153 -16
  17. package/Runtime/Code/Player/Character/MovementSystems/Character/Structures/CharacterSnapshotData.cs +88 -19
  18. package/Runtime/Code/Player/PlayerInfo.cs +6 -2
  19. package/Runtime/Code/Player/PlayerManagerBridge.cs +3 -3
  20. package/Runtime/Code/Player/UserData.cs +1 -0
  21. package/Runtime/Code/TSCodeGen/TypeGenerator.cs +2 -1
  22. package/Runtime/Code/VoxelWorld/Airship.VoxelWorld.asmdef +2 -1
  23. package/Runtime/Code/VoxelWorld/VoxelCompressUtil.cs +26 -3
  24. package/Runtime/Code/VoxelWorld/VoxelWorld.cs +0 -17
  25. package/Runtime/Code/VoxelWorld/VoxelWorldChunk.cs +1 -1
  26. package/Runtime/Code/VoxelWorld/WorldSaveFile.cs +8 -6
  27. package/Runtime/Code/Zstd/Zstd.cs +125 -47
  28. package/Runtime/Code/Zstd/ZstdCompressStream.cs +147 -0
  29. package/Runtime/Code/Zstd/ZstdCompressStream.cs.meta +3 -0
  30. package/Runtime/Code/Zstd/ZstdDecompressStream.cs +196 -0
  31. package/Runtime/Code/Zstd/ZstdDecompressStream.cs.meta +3 -0
  32. package/Runtime/Code/Zstd/ZstdNative.cs +5 -5
  33. package/Runtime/Plugins/Android/libLuauPlugin.so +0 -0
  34. package/Runtime/Plugins/Linux/libLuauPlugin.so +0 -0
  35. package/Runtime/Plugins/Mac/LuauPlugin.bundle/Contents/Info.plist +1 -1
  36. package/Runtime/Plugins/Mac/LuauPlugin.bundle/Contents/MacOS/LuauPlugin +0 -0
  37. package/Runtime/Plugins/Windows/x64/LuauPlugin.dll +0 -0
  38. package/Runtime/Plugins/Windows/x64/LuauPlugin.pdb +0 -0
  39. package/Runtime/Plugins/iOS/LuauPluginIos.a +0 -0
  40. package/package.json +1 -1
  41. package/Runtime/Code/RemoteConsole/Airship.RemoteConsole.asmdef +0 -26
  42. package/Runtime/Code/RemoteConsole/Airship.RemoteConsole.asmdef.meta +0 -3
  43. package/Runtime/Code/RemoteConsole.meta +0 -3
@@ -1,6 +1,5 @@
1
1
  using System;
2
- using System.Runtime.InteropServices;
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 CompressData(data, compressionLevel, _ctx);
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 CompressData(data, DefaultCompressionLevel, _ctx);
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[] data, int compressionLevel, ZstdContext ctx = null) {
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[] data, ZstdContext ctx = null) {
76
- var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
77
- var rSize = ZSTD_getFrameContentSize(dataHandle.AddrOfPinnedObject(), (ulong)data.Length);
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, dataHandle, rSize, ctx);
137
+ decompressedData = DecompressWithStack(data, rSize, ctx);
85
138
  } else {
86
- decompressedData = DecompressWithHeap(data, dataHandle, rSize, ctx);
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[] data, GCHandle dataHandle, ulong rSize, ZstdContext ctx) {
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
- if (ctx != null) {
96
- decompressedSize = ZSTD_decompressDCtx(ctx.Dctx, new IntPtr(decompressedData), rSize, dataHandle.AddrOfPinnedObject(), (ulong)data.Length);
97
- } else {
98
- decompressedSize = ZSTD_decompress(new IntPtr(decompressedData), rSize, dataHandle.AddrOfPinnedObject(), (ulong)data.Length);
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[] data, GCHandle dataHandle, ulong rSize, ZstdContext ctx) {
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
- if (ctx != null) {
117
- decompressedSize = ZSTD_decompressDCtx(ctx.Dctx, dstHandle.AddrOfPinnedObject(), rSize, dataHandle.AddrOfPinnedObject(), (ulong)data.Length);
118
- } else {
119
- decompressedSize = ZSTD_decompress(dstHandle.AddrOfPinnedObject(), rSize, dataHandle.AddrOfPinnedObject(), (ulong)data.Length);
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[] data, ulong bound, int compressionLevel, ZstdContext ctx) {
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
- if (ctx != null) {
135
- compressedSize = ZSTD_compressCCtx(ctx.Cctx, new IntPtr(dst), bound, srcHandle.AddrOfPinnedObject(), (ulong)data.Length, compressionLevel);
136
- } else {
137
- compressedSize = ZSTD_compress(new IntPtr(dst), bound, srcHandle.AddrOfPinnedObject(), (ulong)data.Length, compressionLevel);
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[] data, ulong bound, int compressionLevel, ZstdContext ctx) {
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 dst = allocDst ? new byte[bound] : ctx.ScratchBuffer;
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
- if (ctx != null) {
157
- compressedSize = ZSTD_compressCCtx(ctx.Cctx, dstHandle.AddrOfPinnedObject(), bound, srcHandle.AddrOfPinnedObject(), (ulong)data.Length, compressionLevel);
158
- } else {
159
- compressedSize = ZSTD_compress(dstHandle.AddrOfPinnedObject(), bound, srcHandle.AddrOfPinnedObject(), (ulong)data.Length, compressionLevel);
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 dst, (int)compressedSize);
167
- return dst;
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 = new byte[scratchBufferSize];
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,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 104c04ecb4754bbbb6d840b586afa217
3
+ timeCreated: 1748324334
@@ -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
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 17b1cf21ff70448ba38b34ea9f3428c1
3
+ timeCreated: 1748328585
@@ -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")]
@@ -3,7 +3,7 @@
3
3
  <plist version="1.0">
4
4
  <dict>
5
5
  <key>BuildMachineOSBuild</key>
6
- <string>23H527</string>
6
+ <string>23H626</string>
7
7
  <key>CFBundleDevelopmentRegion</key>
8
8
  <string>en</string>
9
9
  <key>CFBundleExecutable</key>