Initial project state: .NET reference, design, Rust port (M0+M1), evidence
rust / build / test / clippy / fmt (push) Has been cancelled
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:
+156
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user