Initial project state: .NET reference, design, Rust port (M0+M1), evidence
rust / build / test / clippy / fmt (push) Has been cancelled

Layout:
- src/                    .NET 10 x64 reference: MxNativeCodec, MxNativeClient,
                          MxAsbClient, probes, tests, harnesses. Executable spec.
- design/                 Architectural plan for the Rust port (M0–M6), error
                          model, protocol invariants, risks (R1–R16), adversarial
                          review log (review.md).
- rust/                   Rust workspace. M0 skeleton + M1 codec parity.
                          mxaccess-codec: 215 unit tests + 2 cross-implementation
                          parity tests (byte-identical against .NET reference).
                          Other crates are M0 stubs awaiting M2+.
- captures/               Frida + netsh + pcap evidence per CLAUDE.md
                          ("captures are evidence, not throwaway logs").
- analysis/               Decompiled C# (frida/proxy/decompiled-*),
                          Ghidra exports for native DLLs (`exports/` only —
                          working state at `projects/` and AVEVA's input
                          binaries at `input/` are gitignored).
- docs/                   Reverse-engineering reference docs.
- tools/                  Setup-LiveProbeEnv.ps1 (Infisical credential fetcher),
                          Compute-Crc.ps1 (.NET parity helper).
- .github/workflows/      Rust CI: fmt + build + test + clippy on Windows.
- LICENSE                 MIT (Joseph Doherty, 2026).

Verified:
- cargo test --workspace → 217 passed (215 unit + 2 .NET parity), 0 failed
- cargo clippy --workspace -- -D warnings → clean
- cargo fmt --all -- --check → clean
- cargo publish --dry-run -p mxaccess-codec → packages cleanly

Excluded from history (see .gitignore):
- **/bin, **/obj, **/target — build artifacts
- analysis/ghidra/projects/ — Ghidra working state (regenerable)
- analysis/ghidra/input/ — AVEVA proprietary DLLs (vendor IP)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-05-05 06:21:00 -04:00
parent 43733699b0
commit fe2a6db786
3849 changed files with 352975 additions and 0 deletions
@@ -0,0 +1,45 @@
using System;
namespace Invensys.Compression;
internal class AACopyEncoder
{
private const int PaddingSize = 5;
private const int MaxUncompressedBlockSize = 65536;
public void GetBlock(AADeflateInput input, AAOutputBuffer output, bool isFinal)
{
int num = 0;
if (input != null)
{
num = Math.Min(input.Count, output.FreeBytes - 5 - output.BitsInBuffer);
if (num > 65531)
{
num = 65531;
}
}
if (isFinal)
{
output.WriteBits(3, 1u);
}
else
{
output.WriteBits(3, 0u);
}
output.FlushBits();
WriteLenNLen((ushort)num, output);
if (input != null && num > 0)
{
output.WriteBytes(input.Buffer, input.StartIndex, num);
input.ConsumeBytes(num);
}
}
private void WriteLenNLen(ushort len, AAOutputBuffer output)
{
output.WriteUInt16(len);
ushort value = (ushort)(~len);
output.WriteUInt16(value);
}
}
@@ -0,0 +1,73 @@
namespace Invensys.Compression;
internal class AADeflateInput
{
internal struct InputState
{
internal int count;
internal int startIndex;
}
private byte[] buffer;
private int count;
private int startIndex;
internal byte[] Buffer
{
get
{
return buffer;
}
set
{
buffer = value;
}
}
internal int Count
{
get
{
return count;
}
set
{
count = value;
}
}
internal int StartIndex
{
get
{
return startIndex;
}
set
{
startIndex = value;
}
}
internal void ConsumeBytes(int n)
{
startIndex += n;
count -= n;
}
internal InputState DumpState()
{
InputState result = default(InputState);
result.count = count;
result.startIndex = startIndex;
return result;
}
internal void RestoreState(InputState state)
{
count = state.count;
startIndex = state.startIndex;
}
}
@@ -0,0 +1,400 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Security.Permissions;
using System.Threading;
namespace Invensys.Compression;
public class AADeflateStream : Stream
{
internal delegate void AsyncWriteDelegate(byte[] array, int offset, int count, bool isAsync);
internal const int DefaultBufferSize = 8192;
private Stream _stream;
private CompressionMode _mode;
private bool _leaveOpen;
private AADeflaterManaged deflater;
private byte[] buffer;
private int asyncOperations;
private readonly AsyncCallback m_CallBack;
private readonly AsyncWriteDelegate m_AsyncWriterDelegate;
private bool wroteBytes;
public Stream BaseStream => _stream;
public override bool CanRead
{
get
{
if (_stream == null)
{
return false;
}
if (_mode == CompressionMode.Decompress)
{
return _stream.CanRead;
}
return false;
}
}
public override bool CanWrite
{
get
{
if (_stream == null)
{
return false;
}
if (_mode == CompressionMode.Compress)
{
return _stream.CanWrite;
}
return false;
}
}
public override bool CanSeek => false;
public override long Length
{
get
{
throw new NotSupportedException();
}
}
public override long Position
{
get
{
throw new NotSupportedException();
}
set
{
throw new NotSupportedException();
}
}
public AADeflateStream(Stream stream, CompressionMode mode)
: this(stream, mode, leaveOpen: false)
{
}
public AADeflateStream(Stream stream, CompressionMode mode, bool leaveOpen)
{
if (stream == null)
{
throw new ArgumentNullException("stream");
}
if (CompressionMode.Compress != mode && mode != CompressionMode.Decompress)
{
throw new ArgumentException("mode");
}
_stream = stream;
_mode = mode;
_leaveOpen = leaveOpen;
switch (_mode)
{
case CompressionMode.Decompress:
throw new ArgumentException("CompressionMode.Decompress - Unsupported");
case CompressionMode.Compress:
if (!_stream.CanWrite)
{
throw new ArgumentException("stream");
}
deflater = new AADeflaterManaged();
m_AsyncWriterDelegate = InternalWrite;
m_CallBack = WriteCallback;
break;
}
buffer = new byte[8192];
}
public override void Flush()
{
EnsureNotDisposed();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override int Read(byte[] array, int offset, int count)
{
throw new ArgumentException("Read - Unsupported");
}
private void ValidateParameters(byte[] array, int offset, int count)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
if (offset < 0)
{
throw new ArgumentOutOfRangeException("offset");
}
if (count < 0)
{
throw new ArgumentOutOfRangeException("count");
}
if (array.Length - offset < count)
{
throw new ArgumentException();
}
}
private void EnsureNotDisposed()
{
if (_stream == null)
{
throw new ObjectDisposedException(string.Empty);
}
}
private void EnsureDecompressionMode()
{
if (_mode != CompressionMode.Decompress)
{
throw new InvalidOperationException();
}
}
private void EnsureCompressionMode()
{
if (_mode != CompressionMode.Compress)
{
throw new InvalidOperationException();
}
}
[HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
public override IAsyncResult BeginRead(byte[] array, int offset, int count, AsyncCallback asyncCallback, object asyncState)
{
throw new ArgumentException("BeginRead - Unsupported");
}
private void ReadCallback(IAsyncResult baseStreamResult)
{
throw new ArgumentException("ReadCallback - Unsupported");
}
public override int EndRead(IAsyncResult asyncResult)
{
EnsureDecompressionMode();
CheckEndXxxxLegalStateAndParams(asyncResult);
DeflateStreamAsyncResult deflateStreamAsyncResult = (DeflateStreamAsyncResult)asyncResult;
AwaitAsyncResultCompletion(deflateStreamAsyncResult);
if (deflateStreamAsyncResult.Result is Exception ex)
{
throw ex;
}
return (int)deflateStreamAsyncResult.Result;
}
public override void Write(byte[] array, int offset, int count)
{
EnsureCompressionMode();
ValidateParameters(array, offset, count);
EnsureNotDisposed();
InternalWrite(array, offset, count, isAsync: false);
}
internal void InternalWrite(byte[] array, int offset, int count, bool isAsync)
{
DoMaintenance(array, offset, count);
WriteDeflaterOutput(isAsync);
deflater.SetInput(array, offset, count);
WriteDeflaterOutput(isAsync);
}
private void WriteDeflaterOutput(bool isAsync)
{
while (!deflater.NeedsInput())
{
int deflateOutput = deflater.GetDeflateOutput(buffer);
if (deflateOutput > 0)
{
DoWrite(buffer, 0, deflateOutput, isAsync);
}
}
}
private void DoWrite(byte[] array, int offset, int count, bool isAsync)
{
if (isAsync)
{
IAsyncResult asyncResult = _stream.BeginWrite(array, offset, count, null, null);
_stream.EndWrite(asyncResult);
}
else
{
_stream.Write(array, offset, count);
}
}
private void DoMaintenance(byte[] array, int offset, int count)
{
if (count > 0)
{
wroteBytes = true;
}
}
private void PurgeBuffers(bool disposing)
{
if (!disposing || _stream == null)
{
return;
}
Flush();
if (_mode != CompressionMode.Compress || !wroteBytes)
{
return;
}
WriteDeflaterOutput(isAsync: false);
bool flag;
do
{
flag = deflater.Finish(buffer, out var bytesRead);
if (bytesRead > 0)
{
DoWrite(buffer, 0, bytesRead, isAsync: false);
}
}
while (!flag);
}
protected override void Dispose(bool disposing)
{
try
{
PurgeBuffers(disposing);
}
finally
{
try
{
if (disposing && !_leaveOpen && _stream != null)
{
_stream.Close();
}
}
finally
{
_stream = null;
try
{
}
finally
{
base.Dispose(disposing);
}
}
}
}
[HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
public override IAsyncResult BeginWrite(byte[] array, int offset, int count, AsyncCallback asyncCallback, object asyncState)
{
EnsureCompressionMode();
if (asyncOperations != 0)
{
throw new InvalidOperationException();
}
ValidateParameters(array, offset, count);
EnsureNotDisposed();
Interlocked.Increment(ref asyncOperations);
try
{
DeflateStreamAsyncResult deflateStreamAsyncResult = new DeflateStreamAsyncResult(this, asyncState, asyncCallback, array, offset, count);
deflateStreamAsyncResult.isWrite = true;
m_AsyncWriterDelegate.BeginInvoke(array, offset, count, isAsync: true, m_CallBack, deflateStreamAsyncResult);
deflateStreamAsyncResult.m_CompletedSynchronously &= deflateStreamAsyncResult.IsCompleted;
return deflateStreamAsyncResult;
}
catch
{
Interlocked.Decrement(ref asyncOperations);
throw;
}
}
private void WriteCallback(IAsyncResult asyncResult)
{
DeflateStreamAsyncResult deflateStreamAsyncResult = (DeflateStreamAsyncResult)asyncResult.AsyncState;
deflateStreamAsyncResult.m_CompletedSynchronously &= asyncResult.CompletedSynchronously;
try
{
m_AsyncWriterDelegate.EndInvoke(asyncResult);
}
catch (Exception result)
{
deflateStreamAsyncResult.InvokeCallback(result);
return;
}
deflateStreamAsyncResult.InvokeCallback(null);
}
public override void EndWrite(IAsyncResult asyncResult)
{
EnsureCompressionMode();
CheckEndXxxxLegalStateAndParams(asyncResult);
DeflateStreamAsyncResult deflateStreamAsyncResult = (DeflateStreamAsyncResult)asyncResult;
AwaitAsyncResultCompletion(deflateStreamAsyncResult);
if (deflateStreamAsyncResult.Result is Exception ex)
{
throw ex;
}
}
private void CheckEndXxxxLegalStateAndParams(IAsyncResult asyncResult)
{
if (asyncOperations != 1)
{
throw new InvalidOperationException();
}
if (asyncResult == null)
{
throw new ArgumentNullException("asyncResult");
}
EnsureNotDisposed();
if (!(asyncResult is DeflateStreamAsyncResult))
{
throw new ArgumentNullException("asyncResult");
}
}
private void AwaitAsyncResultCompletion(DeflateStreamAsyncResult asyncResult)
{
try
{
if (!asyncResult.IsCompleted)
{
asyncResult.AsyncWaitHandle.WaitOne();
}
}
finally
{
Interlocked.Decrement(ref asyncOperations);
asyncResult.Close();
}
}
}
@@ -0,0 +1,188 @@
using System;
namespace Invensys.Compression;
internal class AADeflaterManaged : IDisposable
{
private enum DeflaterState
{
NotStarted,
SlowDownForIncompressible1,
SlowDownForIncompressible2,
StartingSmallData,
CompressThenCheck,
CheckingForIncompressible,
HandlingSmallData
}
private const int MinBlockSize = 256;
private const int MaxHeaderFooterGoo = 120;
private const int CleanCopySize = 8072;
private const double BadCompressionThreshold = 1.0;
private AAFastEncoder deflateEncoder;
private AACopyEncoder copyEncoder;
private AADeflateInput input;
private AAOutputBuffer output;
private DeflaterState processingState;
private AADeflateInput inputFromHistory;
internal AADeflaterManaged()
{
deflateEncoder = new AAFastEncoder();
copyEncoder = new AACopyEncoder();
input = new AADeflateInput();
output = new AAOutputBuffer();
processingState = DeflaterState.NotStarted;
}
public bool NeedsInput()
{
if (input.Count == 0)
{
return deflateEncoder.BytesInHistory == 0;
}
return false;
}
public void SetInput(byte[] inputBuffer, int startIndex, int count)
{
input.Buffer = inputBuffer;
input.Count = count;
input.StartIndex = startIndex;
if (count > 0 && count < 256)
{
switch (processingState)
{
case DeflaterState.NotStarted:
case DeflaterState.CheckingForIncompressible:
processingState = DeflaterState.StartingSmallData;
break;
case DeflaterState.CompressThenCheck:
processingState = DeflaterState.HandlingSmallData;
break;
}
}
}
public int GetDeflateOutput(byte[] outputBuffer)
{
output.UpdateBuffer(outputBuffer);
switch (processingState)
{
case DeflaterState.NotStarted:
{
AADeflateInput.InputState state3 = input.DumpState();
AAOutputBuffer.BufferState state4 = output.DumpState();
deflateEncoder.GetBlockHeader(output);
deflateEncoder.GetCompressedData(input, output);
if (!UseCompressed(deflateEncoder.LastCompressionRatio))
{
input.RestoreState(state3);
output.RestoreState(state4);
copyEncoder.GetBlock(input, output, isFinal: false);
FlushInputWindows();
processingState = DeflaterState.CheckingForIncompressible;
}
else
{
processingState = DeflaterState.CompressThenCheck;
}
break;
}
case DeflaterState.CompressThenCheck:
deflateEncoder.GetCompressedData(input, output);
if (!UseCompressed(deflateEncoder.LastCompressionRatio))
{
processingState = DeflaterState.SlowDownForIncompressible1;
inputFromHistory = deflateEncoder.UnprocessedInput;
}
break;
case DeflaterState.SlowDownForIncompressible1:
deflateEncoder.GetBlockFooter(output);
processingState = DeflaterState.SlowDownForIncompressible2;
goto case DeflaterState.SlowDownForIncompressible2;
case DeflaterState.SlowDownForIncompressible2:
if (inputFromHistory.Count > 0)
{
copyEncoder.GetBlock(inputFromHistory, output, isFinal: false);
}
if (inputFromHistory.Count == 0)
{
deflateEncoder.FlushInput();
processingState = DeflaterState.CheckingForIncompressible;
}
break;
case DeflaterState.CheckingForIncompressible:
{
AADeflateInput.InputState state = input.DumpState();
AAOutputBuffer.BufferState state2 = output.DumpState();
deflateEncoder.GetBlock(input, output, 8072);
if (!UseCompressed(deflateEncoder.LastCompressionRatio))
{
input.RestoreState(state);
output.RestoreState(state2);
copyEncoder.GetBlock(input, output, isFinal: false);
FlushInputWindows();
}
break;
}
case DeflaterState.StartingSmallData:
deflateEncoder.GetBlockHeader(output);
processingState = DeflaterState.HandlingSmallData;
goto case DeflaterState.HandlingSmallData;
case DeflaterState.HandlingSmallData:
deflateEncoder.GetCompressedData(input, output);
break;
}
return output.BytesWritten;
}
public bool Finish(byte[] outputBuffer, out int bytesRead)
{
if (processingState == DeflaterState.NotStarted)
{
bytesRead = 0;
return true;
}
output.UpdateBuffer(outputBuffer);
if (processingState == DeflaterState.CompressThenCheck || processingState == DeflaterState.HandlingSmallData || processingState == DeflaterState.SlowDownForIncompressible1)
{
deflateEncoder.GetBlockFooter(output);
}
WriteFinal();
bytesRead = output.BytesWritten;
return true;
}
void IDisposable.Dispose()
{
}
protected void Dispose(bool disposing)
{
}
private bool UseCompressed(double ratio)
{
return ratio <= 1.0;
}
private void FlushInputWindows()
{
deflateEncoder.FlushInput();
}
private void WriteFinal()
{
copyEncoder.GetBlock(null, output, isFinal: true);
}
}
@@ -0,0 +1,156 @@
using System;
namespace Invensys.Compression;
internal class AAFastEncoder
{
private AAFastEncoderWindow inputWindow;
private AAMatch currentMatch;
private double lastCompressionRatio;
internal int BytesInHistory => inputWindow.BytesAvailable;
internal AADeflateInput UnprocessedInput => inputWindow.UnprocessedInput;
internal double LastCompressionRatio => lastCompressionRatio;
public AAFastEncoder()
{
inputWindow = new AAFastEncoderWindow();
currentMatch = new AAMatch();
}
internal void FlushInput()
{
inputWindow.FlushWindow();
}
internal void GetBlock(AADeflateInput input, AAOutputBuffer output, int maxBytesToCopy)
{
WriteDeflatePreamble(output);
GetCompressedOutput(input, output, maxBytesToCopy);
WriteEndOfBlock(output);
}
internal void GetCompressedData(AADeflateInput input, AAOutputBuffer output)
{
GetCompressedOutput(input, output, -1);
}
internal void GetBlockHeader(AAOutputBuffer output)
{
WriteDeflatePreamble(output);
}
internal void GetBlockFooter(AAOutputBuffer output)
{
WriteEndOfBlock(output);
}
private void GetCompressedOutput(AADeflateInput input, AAOutputBuffer output, int maxBytesToCopy)
{
int bytesWritten = output.BytesWritten;
int num = 0;
int num2 = BytesInHistory + input.Count;
do
{
int num3 = ((input.Count < inputWindow.FreeWindowSpace) ? input.Count : inputWindow.FreeWindowSpace);
if (maxBytesToCopy >= 1)
{
num3 = Math.Min(num3, maxBytesToCopy - num);
}
if (num3 > 0)
{
inputWindow.CopyBytes(input.Buffer, input.StartIndex, num3);
input.ConsumeBytes(num3);
num += num3;
}
GetCompressedOutput(output);
}
while (SafeToWriteTo(output) && InputAvailable(input) && (maxBytesToCopy < 1 || num < maxBytesToCopy));
int num4 = output.BytesWritten - bytesWritten;
int num5 = BytesInHistory + input.Count;
int num6 = num2 - num5;
if (num4 != 0)
{
lastCompressionRatio = (double)num4 / (double)num6;
}
}
private void GetCompressedOutput(AAOutputBuffer output)
{
while (inputWindow.BytesAvailable > 0 && SafeToWriteTo(output))
{
inputWindow.GetNextSymbolOrMatch(currentMatch);
if (currentMatch.State == AAMatchState.HasSymbol)
{
WriteChar(currentMatch.Symbol, output);
continue;
}
if (currentMatch.State == AAMatchState.HasMatch)
{
WriteMatch(currentMatch.Length, currentMatch.Position, output);
continue;
}
WriteChar(currentMatch.Symbol, output);
WriteMatch(currentMatch.Length, currentMatch.Position, output);
}
}
private bool InputAvailable(AADeflateInput input)
{
if (input.Count <= 0)
{
return BytesInHistory > 0;
}
return true;
}
private bool SafeToWriteTo(AAOutputBuffer output)
{
return output.FreeBytes > 16;
}
private void WriteEndOfBlock(AAOutputBuffer output)
{
uint num = AAFastEncoderStatics.FastEncoderLiteralCodeInfo[256];
int n = (int)(num & 0x1F);
output.WriteBits(n, num >> 5);
}
internal static void WriteMatch(int matchLen, int matchPos, AAOutputBuffer output)
{
uint num = AAFastEncoderStatics.FastEncoderLiteralCodeInfo[254 + matchLen];
int num2 = (int)(num & 0x1F);
if (num2 <= 16)
{
output.WriteBits(num2, num >> 5);
}
else
{
output.WriteBits(16, (num >> 5) & 0xFFFF);
output.WriteBits(num2 - 16, num >> 21);
}
num = AAFastEncoderStatics.FastEncoderDistanceCodeInfo[AAFastEncoderStatics.GetSlot(matchPos)];
output.WriteBits((int)(num & 0xF), num >> 8);
int num3 = (int)((num >> 4) & 0xF);
if (num3 != 0)
{
output.WriteBits(num3, (uint)matchPos & AAFastEncoderStatics.BitMask[num3]);
}
}
internal static void WriteChar(byte b, AAOutputBuffer output)
{
uint num = AAFastEncoderStatics.FastEncoderLiteralCodeInfo[b];
output.WriteBits((int)(num & 0x1F), num >> 5);
}
internal static void WriteDeflatePreamble(AAOutputBuffer output)
{
output.WriteBytes(AAFastEncoderStatics.FastEncoderTreeStructureData, 0, AAFastEncoderStatics.FastEncoderTreeStructureData.Length);
output.WriteBits(9, 34u);
}
}
@@ -0,0 +1,186 @@
namespace Invensys.Compression;
internal static class AAFastEncoderStatics
{
internal static readonly byte[] FastEncoderTreeStructureData;
internal static readonly byte[] BFinalFastEncoderTreeStructureData;
internal static readonly uint[] FastEncoderLiteralCodeInfo;
internal static readonly uint[] FastEncoderDistanceCodeInfo;
internal static readonly uint[] BitMask;
internal static readonly byte[] ExtraLengthBits;
internal static readonly byte[] ExtraDistanceBits;
internal const int NumChars = 256;
internal const int NumLengthBaseCodes = 29;
internal const int NumDistBaseCodes = 30;
internal const uint FastEncoderPostTreeBitBuf = 34u;
internal const int FastEncoderPostTreeBitCount = 9;
internal const uint NoCompressionHeader = 0u;
internal const int NoCompressionHeaderBitCount = 3;
internal const uint BFinalNoCompressionHeader = 1u;
internal const int BFinalNoCompressionHeaderBitCount = 3;
internal const int MaxCodeLen = 16;
private static byte[] distLookup;
static AAFastEncoderStatics()
{
FastEncoderTreeStructureData = new byte[98]
{
236, 189, 7, 96, 28, 73, 150, 37, 38, 47,
109, 202, 123, 127, 74, 245, 74, 215, 224, 116,
161, 8, 128, 96, 19, 36, 216, 144, 64, 16,
236, 193, 136, 205, 230, 146, 236, 29, 105, 71,
35, 41, 171, 42, 129, 202, 101, 86, 101, 93,
102, 22, 64, 204, 237, 157, 188, 247, 222, 123,
239, 189, 247, 222, 123, 239, 189, 247, 186, 59,
157, 78, 39, 247, 223, 255, 63, 92, 102, 100,
1, 108, 246, 206, 74, 218, 201, 158, 33, 128,
170, 200, 31, 63, 126, 124, 31, 63
};
BFinalFastEncoderTreeStructureData = new byte[98]
{
237, 189, 7, 96, 28, 73, 150, 37, 38, 47,
109, 202, 123, 127, 74, 245, 74, 215, 224, 116,
161, 8, 128, 96, 19, 36, 216, 144, 64, 16,
236, 193, 136, 205, 230, 146, 236, 29, 105, 71,
35, 41, 171, 42, 129, 202, 101, 86, 101, 93,
102, 22, 64, 204, 237, 157, 188, 247, 222, 123,
239, 189, 247, 222, 123, 239, 189, 247, 186, 59,
157, 78, 39, 247, 223, 255, 63, 92, 102, 100,
1, 108, 246, 206, 74, 218, 201, 158, 33, 128,
170, 200, 31, 63, 126, 124, 31, 63
};
FastEncoderLiteralCodeInfo = new uint[513]
{
55278u, 317422u, 186350u, 448494u, 120814u, 382958u, 251886u, 514030u, 14318u, 51180u,
294u, 276462u, 145390u, 407534u, 79854u, 341998u, 210926u, 473070u, 47086u, 309230u,
178158u, 440302u, 112622u, 374766u, 243694u, 505838u, 30702u, 292846u, 161774u, 423918u,
6125u, 96238u, 1318u, 358382u, 9194u, 116716u, 227310u, 489454u, 137197u, 25578u,
2920u, 3817u, 23531u, 5098u, 1127u, 7016u, 3175u, 12009u, 1896u, 5992u,
3944u, 7913u, 8040u, 16105u, 21482u, 489u, 232u, 8681u, 4585u, 4328u,
12777u, 13290u, 2280u, 63470u, 325614u, 6376u, 2537u, 1256u, 10729u, 5352u,
6633u, 29674u, 56299u, 3304u, 15339u, 194542u, 14825u, 3050u, 1513u, 19434u,
9705u, 10220u, 5609u, 13801u, 3561u, 11242u, 75756u, 48107u, 456686u, 129006u,
42988u, 31723u, 391150u, 64491u, 260078u, 522222u, 4078u, 806u, 615u, 2663u,
1639u, 1830u, 7400u, 744u, 3687u, 166u, 108524u, 11753u, 1190u, 359u,
2407u, 678u, 1383u, 71661u, 1702u, 422u, 1446u, 3431u, 4840u, 2792u,
7657u, 6888u, 2027u, 202733u, 26604u, 38893u, 169965u, 266222u, 135150u, 397294u,
69614u, 331758u, 200686u, 462830u, 36846u, 298990u, 167918u, 430062u, 102382u, 364526u,
233454u, 495598u, 20462u, 282606u, 151534u, 413678u, 85998u, 348142u, 217070u, 479214u,
53230u, 315374u, 184302u, 446446u, 118766u, 380910u, 249838u, 511982u, 12270u, 274414u,
143342u, 405486u, 77806u, 339950u, 208878u, 471022u, 45038u, 307182u, 176110u, 438254u,
110574u, 372718u, 241646u, 503790u, 28654u, 290798u, 159726u, 421870u, 94190u, 356334u,
225262u, 487406u, 61422u, 323566u, 192494u, 454638u, 126958u, 389102u, 258030u, 520174u,
8174u, 270318u, 139246u, 401390u, 73710u, 335854u, 204782u, 466926u, 40942u, 303086u,
172014u, 434158u, 106478u, 368622u, 237550u, 499694u, 24558u, 286702u, 155630u, 417774u,
90094u, 352238u, 221166u, 483310u, 57326u, 319470u, 188398u, 450542u, 122862u, 385006u,
253934u, 516078u, 16366u, 278510u, 147438u, 409582u, 81902u, 344046u, 212974u, 475118u,
49134u, 311278u, 180206u, 442350u, 114670u, 376814u, 245742u, 507886u, 32750u, 294894u,
163822u, 425966u, 98286u, 104429u, 235501u, 22509u, 360430u, 153581u, 229358u, 88045u,
491502u, 219117u, 65518u, 327662u, 196590u, 458734u, 131054u, 132u, 3u, 388u,
68u, 324u, 197u, 709u, 453u, 966u, 1990u, 38u, 1062u, 935u,
2983u, 1959u, 4007u, 551u, 1575u, 2599u, 3623u, 104u, 2152u, 4200u,
6248u, 873u, 4969u, 9065u, 13161u, 1770u, 9962u, 18154u, 26346u, 5867u,
14059u, 22251u, 30443u, 38635u, 46827u, 55019u, 63211u, 15852u, 32236u, 48620u,
65004u, 81388u, 97772u, 114156u, 130540u, 27629u, 60397u, 93165u, 125933u, 158701u,
191469u, 224237u, 257005u, 1004u, 17388u, 33772u, 50156u, 66540u, 82924u, 99308u,
115692u, 7150u, 39918u, 72686u, 105454u, 138222u, 170990u, 203758u, 236526u, 269294u,
302062u, 334830u, 367598u, 400366u, 433134u, 465902u, 498670u, 92144u, 223216u, 354288u,
485360u, 616432u, 747504u, 878576u, 1009648u, 1140720u, 1271792u, 1402864u, 1533936u, 1665008u,
1796080u, 1927152u, 2058224u, 34799u, 100335u, 165871u, 231407u, 296943u, 362479u, 428015u,
493551u, 559087u, 624623u, 690159u, 755695u, 821231u, 886767u, 952303u, 1017839u, 59376u,
190448u, 321520u, 452592u, 583664u, 714736u, 845808u, 976880u, 1107952u, 1239024u, 1370096u,
1501168u, 1632240u, 1763312u, 1894384u, 2025456u, 393203u, 917491u, 1441779u, 1966067u, 2490355u,
3014643u, 3538931u, 4063219u, 4587507u, 5111795u, 5636083u, 6160371u, 6684659u, 7208947u, 7733235u,
8257523u, 8781811u, 9306099u, 9830387u, 10354675u, 10878963u, 11403251u, 11927539u, 12451827u, 12976115u,
13500403u, 14024691u, 14548979u, 15073267u, 15597555u, 16121843u, 16646131u, 262131u, 786419u, 1310707u,
1834995u, 2359283u, 2883571u, 3407859u, 3932147u, 4456435u, 4980723u, 5505011u, 6029299u, 6553587u,
7077875u, 7602163u, 8126451u, 8650739u, 9175027u, 9699315u, 10223603u, 10747891u, 11272179u, 11796467u,
12320755u, 12845043u, 13369331u, 13893619u, 14417907u, 14942195u, 15466483u, 15990771u, 16515059u, 524275u,
1048563u, 1572851u, 2097139u, 2621427u, 3145715u, 3670003u, 4194291u, 4718579u, 5242867u, 5767155u,
6291443u, 6815731u, 7340019u, 7864307u, 8388595u, 8912883u, 9437171u, 9961459u, 10485747u, 11010035u,
11534323u, 12058611u, 12582899u, 13107187u, 13631475u, 14155763u, 14680051u, 15204339u, 15728627u, 16252915u,
16777203u, 124913u, 255985u, 387057u, 518129u, 649201u, 780273u, 911345u, 1042417u, 1173489u,
1304561u, 1435633u, 1566705u, 1697777u, 1828849u, 1959921u, 2090993u, 2222065u, 2353137u, 2484209u,
2615281u, 2746353u, 2877425u, 3008497u, 3139569u, 3270641u, 3401713u, 3532785u, 3663857u, 3794929u,
3926001u, 4057073u, 18411u
};
FastEncoderDistanceCodeInfo = new uint[32]
{
3846u, 130826u, 261899u, 524043u, 65305u, 16152u, 48936u, 32552u, 7991u, 24375u,
3397u, 12102u, 84u, 7509u, 2148u, 869u, 1140u, 4981u, 3204u, 644u,
2708u, 1684u, 3748u, 420u, 2484u, 2997u, 1476u, 7109u, 2005u, 6101u,
0u, 256u
};
BitMask = new uint[16]
{
0u, 1u, 3u, 7u, 15u, 31u, 63u, 127u, 255u, 511u,
1023u, 2047u, 4095u, 8191u, 16383u, 32767u
};
ExtraLengthBits = new byte[29]
{
0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
4, 4, 4, 4, 5, 5, 5, 5, 0
};
ExtraDistanceBits = new byte[32]
{
0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
0, 0
};
distLookup = new byte[512];
int num = 0;
int i;
for (i = 0; i < 16; i++)
{
for (int j = 0; j < 1 << (int)ExtraDistanceBits[i]; j++)
{
distLookup[num++] = (byte)i;
}
}
num >>= 7;
for (; i < 30; i++)
{
for (int k = 0; k < 1 << ExtraDistanceBits[i] - 7; k++)
{
distLookup[256 + num++] = (byte)i;
}
}
}
internal static int GetSlot(int pos)
{
return distLookup[(pos < 256) ? pos : (256 + (pos >> 7))];
}
public static uint BitReverse(uint code, int length)
{
uint num = 0u;
do
{
num |= code & 1;
num <<= 1;
code >>= 1;
}
while (--length > 0);
return num >> 1;
}
}
@@ -0,0 +1,285 @@
using System;
using System.Diagnostics;
namespace Invensys.Compression;
internal class AAFastEncoderWindow
{
private byte[] window;
private int bufPos;
private int bufEnd;
private const int FastEncoderHashShift = 4;
private const int FastEncoderHashtableSize = 2048;
private const int FastEncoderHashMask = 2047;
private const int FastEncoderWindowSize = 8192;
private const int FastEncoderWindowMask = 8191;
private const int FastEncoderMatch3DistThreshold = 16384;
internal const int MaxMatch = 258;
internal const int MinMatch = 3;
private const int SearchDepth = 32;
private const int GoodLength = 4;
private const int NiceLength = 32;
private const int LazyMatchThreshold = 6;
private ushort[] prev;
private ushort[] lookup;
public int BytesAvailable => bufEnd - bufPos;
public AADeflateInput UnprocessedInput => new AADeflateInput
{
Buffer = window,
StartIndex = bufPos,
Count = bufEnd - bufPos
};
public int FreeWindowSpace => 16384 - bufEnd;
public AAFastEncoderWindow()
{
ResetWindow();
}
public void FlushWindow()
{
ResetWindow();
}
private void ResetWindow()
{
window = new byte[16646];
prev = new ushort[8450];
lookup = new ushort[2048];
bufPos = 8192;
bufEnd = bufPos;
}
public void CopyBytes(byte[] inputBuffer, int startIndex, int count)
{
Array.Copy(inputBuffer, startIndex, window, bufEnd, count);
bufEnd += count;
}
public void MoveWindows()
{
Array.Copy(window, bufPos - 8192, window, 0, 8192);
for (int i = 0; i < 2048; i++)
{
int num = lookup[i] - 8192;
if (num <= 0)
{
lookup[i] = 0;
}
else
{
lookup[i] = (ushort)num;
}
}
for (int i = 0; i < 8192; i++)
{
long num2 = (long)prev[i] - 8192L;
if (num2 <= 0)
{
prev[i] = 0;
}
else
{
prev[i] = (ushort)num2;
}
}
bufPos = 8192;
bufEnd = bufPos;
}
private uint HashValue(uint hash, byte b)
{
return (hash << 4) ^ b;
}
private uint InsertString(ref uint hash)
{
hash = HashValue(hash, window[bufPos + 2]);
uint num = lookup[hash & 0x7FF];
lookup[hash & 0x7FF] = (ushort)bufPos;
prev[bufPos & 0x1FFF] = (ushort)num;
return num;
}
private void InsertStrings(ref uint hash, int matchLen)
{
if (bufEnd - bufPos <= matchLen)
{
bufPos += matchLen - 1;
return;
}
while (--matchLen > 0)
{
InsertString(ref hash);
bufPos++;
}
}
internal bool GetNextSymbolOrMatch(AAMatch match)
{
uint hash = HashValue(0u, window[bufPos]);
hash = HashValue(hash, window[bufPos + 1]);
int matchPos = 0;
int num;
if (bufEnd - bufPos <= 3)
{
num = 0;
}
else
{
int num2 = (int)InsertString(ref hash);
if (num2 != 0)
{
num = FindMatch(num2, out matchPos, 32, 32);
if (bufPos + num > bufEnd)
{
num = bufEnd - bufPos;
}
}
else
{
num = 0;
}
}
if (num < 3)
{
match.State = AAMatchState.HasSymbol;
match.Symbol = window[bufPos];
bufPos++;
}
else
{
bufPos++;
if (num <= 6)
{
int matchPos2 = 0;
int num3 = (int)InsertString(ref hash);
int num4;
if (num3 != 0)
{
num4 = FindMatch(num3, out matchPos2, (num < 4) ? 32 : 8, 32);
if (bufPos + num4 > bufEnd)
{
num4 = bufEnd - bufPos;
}
}
else
{
num4 = 0;
}
if (num4 > num)
{
match.State = AAMatchState.HasSymbolAndMatch;
match.Symbol = window[bufPos - 1];
match.Position = matchPos2;
match.Length = num4;
bufPos++;
num = num4;
InsertStrings(ref hash, num);
}
else
{
match.State = AAMatchState.HasMatch;
match.Position = matchPos;
match.Length = num;
num--;
bufPos++;
InsertStrings(ref hash, num);
}
}
else
{
match.State = AAMatchState.HasMatch;
match.Position = matchPos;
match.Length = num;
InsertStrings(ref hash, num);
}
}
if (bufPos == 16384)
{
MoveWindows();
}
return true;
}
private int FindMatch(int search, out int matchPos, int searchDepth, int niceLength)
{
int num = 0;
int num2 = 0;
int num3 = bufPos - 8192;
byte b = window[bufPos];
while (search > num3)
{
if (window[search + num] == b)
{
int i;
for (i = 0; i < 258 && window[bufPos + i] == window[search + i]; i++)
{
}
if (i > num)
{
num = i;
num2 = search;
if (i > 32)
{
break;
}
b = window[bufPos + i];
}
}
if (--searchDepth == 0)
{
break;
}
search = prev[search & 0x1FFF];
}
matchPos = bufPos - num2 - 1;
if (num == 3 && matchPos >= 16384)
{
return 0;
}
return num;
}
[Conditional("DEBUG")]
private void VerifyHashes()
{
for (int i = 0; i < 2048; i++)
{
ushort num = lookup[i];
while (num != 0 && bufPos - num < 8192)
{
ushort num2 = prev[num & 0x1FFF];
if (bufPos - num2 >= 8192)
{
break;
}
num = num2;
}
}
}
private uint RecalculateHash(int position)
{
return (uint)(((window[position] << 8) ^ (window[position + 1] << 4) ^ window[position + 2]) & 0x7FF);
}
}
@@ -0,0 +1,60 @@
namespace Invensys.Compression;
internal class AAMatch
{
private AAMatchState state;
private int pos;
private int len;
private byte symbol;
internal AAMatchState State
{
get
{
return state;
}
set
{
state = value;
}
}
internal int Position
{
get
{
return pos;
}
set
{
pos = value;
}
}
internal int Length
{
get
{
return len;
}
set
{
len = value;
}
}
internal byte Symbol
{
get
{
return symbol;
}
set
{
symbol = value;
}
}
}
@@ -0,0 +1,8 @@
namespace Invensys.Compression;
internal enum AAMatchState
{
HasSymbol,
HasMatch,
HasSymbolAndMatch
}
@@ -0,0 +1,113 @@
using System;
namespace Invensys.Compression;
internal class AAOutputBuffer
{
internal struct BufferState
{
internal int pos;
internal uint bitBuf;
internal int bitCount;
}
private byte[] byteBuffer;
private int pos;
private uint bitBuf;
private int bitCount;
internal int BytesWritten => pos;
internal int FreeBytes => byteBuffer.Length - pos;
internal int BitsInBuffer => bitCount / 8 + 1;
internal void UpdateBuffer(byte[] output)
{
byteBuffer = output;
pos = 0;
}
internal void WriteUInt16(ushort value)
{
byteBuffer[pos++] = (byte)value;
byteBuffer[pos++] = (byte)(value >> 8);
}
internal void WriteBits(int n, uint bits)
{
bitBuf |= bits << bitCount;
bitCount += n;
if (bitCount >= 16)
{
byteBuffer[pos++] = (byte)bitBuf;
byteBuffer[pos++] = (byte)(bitBuf >> 8);
bitCount -= 16;
bitBuf >>= 16;
}
}
internal void FlushBits()
{
while (bitCount >= 8)
{
byteBuffer[pos++] = (byte)bitBuf;
bitCount -= 8;
bitBuf >>= 8;
}
if (bitCount > 0)
{
byteBuffer[pos++] = (byte)bitBuf;
bitBuf = 0u;
bitCount = 0;
}
}
internal void WriteBytes(byte[] byteArray, int offset, int count)
{
if (bitCount == 0)
{
Array.Copy(byteArray, offset, byteBuffer, pos, count);
pos += count;
}
else
{
WriteBytesUnaligned(byteArray, offset, count);
}
}
private void WriteBytesUnaligned(byte[] byteArray, int offset, int count)
{
for (int i = 0; i < count; i++)
{
byte b = byteArray[offset + i];
WriteByteUnaligned(b);
}
}
private void WriteByteUnaligned(byte b)
{
WriteBits(8, b);
}
internal BufferState DumpState()
{
BufferState result = default(BufferState);
result.pos = pos;
result.bitBuf = bitBuf;
result.bitCount = bitCount;
return result;
}
internal void RestoreState(BufferState state)
{
pos = state.pos;
bitBuf = state.bitBuf;
bitCount = state.bitCount;
}
}
@@ -0,0 +1,106 @@
using System;
using System.Threading;
namespace Invensys.Compression;
internal class DeflateStreamAsyncResult : IAsyncResult
{
public byte[] buffer;
public int offset;
public int count;
public bool isWrite;
private object m_AsyncObject;
private object m_AsyncState;
private AsyncCallback m_AsyncCallback;
private object m_Result;
internal bool m_CompletedSynchronously;
private int m_InvokedCallback;
private int m_Completed;
private object m_Event;
public object AsyncState => m_AsyncState;
public WaitHandle AsyncWaitHandle
{
get
{
int completed = m_Completed;
if (m_Event == null)
{
Interlocked.CompareExchange(ref m_Event, new ManualResetEvent(completed != 0), null);
}
ManualResetEvent manualResetEvent = (ManualResetEvent)m_Event;
if (completed == 0 && m_Completed != 0)
{
manualResetEvent.Set();
}
return manualResetEvent;
}
}
public bool CompletedSynchronously => m_CompletedSynchronously;
public bool IsCompleted => m_Completed != 0;
internal object Result => m_Result;
public DeflateStreamAsyncResult(object asyncObject, object asyncState, AsyncCallback asyncCallback, byte[] buffer, int offset, int count)
{
this.buffer = buffer;
this.offset = offset;
this.count = count;
m_CompletedSynchronously = true;
m_AsyncObject = asyncObject;
m_AsyncState = asyncState;
m_AsyncCallback = asyncCallback;
}
internal void Close()
{
if (m_Event != null)
{
((ManualResetEvent)m_Event).Close();
}
}
internal void InvokeCallback(bool completedSynchronously, object result)
{
Complete(completedSynchronously, result);
}
internal void InvokeCallback(object result)
{
Complete(result);
}
private void Complete(bool completedSynchronously, object result)
{
m_CompletedSynchronously = completedSynchronously;
Complete(result);
}
private void Complete(object result)
{
m_Result = result;
Interlocked.Increment(ref m_Completed);
if (m_Event != null)
{
((ManualResetEvent)m_Event).Set();
}
if (Interlocked.Increment(ref m_InvokedCallback) == 1 && m_AsyncCallback != null)
{
m_AsyncCallback(this);
}
}
}