Skip to content

Commit b3492be

Browse files
committed
TryWrap / TryUnwrap API - returns false if destination buffer is too small
1 parent 2cee9c4 commit b3492be

File tree

4 files changed

+96
-1
lines changed

4 files changed

+96
-1
lines changed

src/ZstdSharp.Test/ZstdNetTests.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,29 @@ public void Decompress_throwsArgumentOutOfRangeException_onTooBigData(bool useDi
234234
}
235235
}
236236

237+
[Theory]
238+
[InlineData(false)]
239+
[InlineData(true)]
240+
public void Decompress_tryUnwrap_onTooBigData(bool useDictionary)
241+
{
242+
var data = GenerateSample();
243+
var dict = useDictionary ? BuildDictionary() : null;
244+
245+
byte[] compressed;
246+
using (var compressor = new Compressor())
247+
{
248+
compressor.LoadDictionary(dict);
249+
compressed = compressor.Wrap(data).ToArray();
250+
}
251+
252+
using (var decompressor = new Decompressor())
253+
{
254+
decompressor.LoadDictionary(dict);
255+
var dest = new byte[20];
256+
Assert.False(decompressor.TryUnwrap(compressed, dest, out _));
257+
}
258+
}
259+
237260
[Theory]
238261
[InlineData(false)]
239262
[InlineData(true)]
@@ -389,6 +412,21 @@ public void Compress_throwsDstSizeTooSmall_whenDestinationBufferIsTooSmall(bool
389412
Assert.Equal(ZSTD_ErrorCode.ZSTD_error_dstSize_tooSmall, ex.Code);
390413
}
391414

415+
[Theory]
416+
[InlineData(false)]
417+
[InlineData(true)]
418+
public void Compress_tryWrap_whenDestinationBufferIsTooSmall(bool useDictionary)
419+
{
420+
var data = GenerateSample();
421+
var dict = useDictionary ? BuildDictionary() : null;
422+
var compressed = new byte[20];
423+
const int offset = 4;
424+
425+
using var compressor = new Compressor();
426+
compressor.LoadDictionary(dict);
427+
Assert.False(compressor.TryWrap(data, compressed, offset, out _));
428+
}
429+
392430
[Theory]
393431
[InlineData(false)]
394432
[InlineData(true)]

src/ZstdSharp/Compressor.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,36 @@ public int Wrap(ArraySegment<byte> src, ArraySegment<byte> dest)
101101
public int Wrap(byte[] src, int srcOffset, int srcLength, byte[] dst, int dstOffset, int dstLength)
102102
=> Wrap(new ReadOnlySpan<byte>(src, srcOffset, srcLength), new Span<byte>(dst, dstOffset, dstLength));
103103

104+
public bool TryWrap(byte[] src, byte[] dest, int offset, out int written)
105+
=> TryWrap(src, new Span<byte>(dest, offset, dest.Length - offset), out written);
106+
107+
public bool TryWrap(ReadOnlySpan<byte> src, Span<byte> dest, out int written)
108+
{
109+
EnsureNotDisposed();
110+
fixed (byte* srcPtr = src)
111+
fixed (byte* destPtr = dest)
112+
{
113+
var returnValue =
114+
Methods.ZSTD_compress2(cctx, destPtr, (nuint) dest.Length, srcPtr, (nuint) src.Length);
115+
116+
if (returnValue == unchecked(0 - (nuint)ZSTD_ErrorCode.ZSTD_error_dstSize_tooSmall))
117+
{
118+
written = default;
119+
return false;
120+
}
121+
122+
returnValue.EnsureZstdSuccess();
123+
written = (int) returnValue;
124+
return true;
125+
}
126+
}
127+
128+
public bool TryWrap(ArraySegment<byte> src, ArraySegment<byte> dest, out int written)
129+
=> TryWrap((ReadOnlySpan<byte>)src, dest, out written);
130+
131+
public bool TryWrap(byte[] src, int srcOffset, int srcLength, byte[] dst, int dstOffset, int dstLength, out int written)
132+
=> TryWrap(new ReadOnlySpan<byte>(src, srcOffset, srcLength), new Span<byte>(dst, dstOffset, dstLength), out written);
133+
104134
private void ReleaseUnmanagedResources()
105135
{
106136
if (cctx != null)

src/ZstdSharp/Decompressor.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,33 @@ public int Unwrap(ReadOnlySpan<byte> src, Span<byte> dest)
9090
public int Unwrap(byte[] src, int srcOffset, int srcLength, byte[] dst, int dstOffset, int dstLength)
9191
=> Unwrap(new ReadOnlySpan<byte>(src, srcOffset, srcLength), new Span<byte>(dst, dstOffset, dstLength));
9292

93+
public bool TryUnwrap(byte[] src, byte[] dest, int offset, out int written)
94+
=> TryUnwrap(src, new Span<byte>(dest, offset, dest.Length - offset), out written);
95+
96+
public bool TryUnwrap(ReadOnlySpan<byte> src, Span<byte> dest, out int written)
97+
{
98+
EnsureNotDisposed();
99+
fixed (byte* srcPtr = src)
100+
fixed (byte* destPtr = dest)
101+
{
102+
var returnValue =
103+
Methods.ZSTD_decompressDCtx(dctx, destPtr, (nuint) dest.Length, srcPtr, (nuint) src.Length);
104+
105+
if (returnValue == unchecked(0 - (nuint)ZSTD_ErrorCode.ZSTD_error_dstSize_tooSmall))
106+
{
107+
written = default;
108+
return false;
109+
}
110+
111+
returnValue.EnsureZstdSuccess();
112+
written = (int) returnValue;
113+
return true;
114+
}
115+
}
116+
117+
public bool TryUnwrap(byte[] src, int srcOffset, int srcLength, byte[] dst, int dstOffset, int dstLength, out int written)
118+
=> TryUnwrap(new ReadOnlySpan<byte>(src, srcOffset, srcLength), new Span<byte>(dst, dstOffset, dstLength), out written);
119+
93120
private void ReleaseUnmanagedResources()
94121
{
95122
if (dctx != null)

src/ZstdSharp/ZstdSharp.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
4343
</PackageReference>
4444
<PackageReference Include="InlineIL.Fody" Version="1.7.0" PrivateAssets="all" />
45-
<PackageReference Include="InlineMethod.Fody" Version="0.5.1" PrivateAssets="all" />
45+
<PackageReference Include="InlineMethod.Fody" Version="0.6.0" PrivateAssets="all" />
4646
</ItemGroup>
4747

4848
</Project>

0 commit comments

Comments
 (0)