Skip to content

Commit 83f23b8

Browse files
committed
.
1 parent 6e53766 commit 83f23b8

5 files changed

Lines changed: 31 additions & 97 deletions

File tree

src/DeterministicIoPackaging/DeterministicIoPackaging.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<ItemGroup>
66
<PackageReference Include="Polyfill" PrivateAssets="all" />
77
<PackageReference Include="ProjectDefaults" PrivateAssets="all" />
8+
<PackageReference Include="System.IO.Hashing" />
89
<PackageReference Include="Microsoft.Sbom.Targets" PrivateAssets="all" Condition="'$(CI)' == 'true'" />
910
</ItemGroup>
1011
<ItemGroup Condition="'$(TargetFramework)' == 'net472' OR '$(TargetFramework)' == 'net48'">

src/DeterministicIoPackaging/PngNormalizer.cs

Lines changed: 13 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Buffers.Binary;
2+
using System.IO.Hashing;
23

34
namespace DeterministicIoPackaging;
45

@@ -23,7 +24,7 @@ public static async Task NormalizeAsync(Stream source, Stream target, Cancel can
2324

2425
static void Normalize(byte[] data, int dataLength, Stream target)
2526
{
26-
target.Write(pngSignature, 0, pngSignature.Length);
27+
target.Write(pngSignature);
2728

2829
var idatData = new MemoryStream();
2930
var preIdatChunks = new List<byte[]>();
@@ -66,7 +67,7 @@ static void Normalize(byte[] data, int dataLength, Stream target)
6667

6768
foreach (var chunk in preIdatChunks)
6869
{
69-
target.Write(chunk, 0, chunk.Length);
70+
target.Write(chunk);
7071
}
7172

7273
if (idatData.Length > 0)
@@ -87,7 +88,7 @@ static void Normalize(byte[] data, int dataLength, Stream target)
8788
{
8889
using (var zlibStream = new ZLibStream(compressOutput, CompressionLevel.Optimal, leaveOpen: true))
8990
{
90-
zlibStream.Write(decompressed, 0, decompressed.Length);
91+
zlibStream.Write(decompressed);
9192
}
9293

9394
newIdatData = compressOutput.ToArray();
@@ -98,50 +99,23 @@ static void Normalize(byte[] data, int dataLength, Stream target)
9899

99100
foreach (var chunk in postIdatChunks)
100101
{
101-
target.Write(chunk, 0, chunk.Length);
102+
target.Write(chunk);
102103
}
103104
}
104105

105106
static void WriteChunk(Stream target, byte[] type, byte[] data)
106107
{
107108
var header = new byte[4];
108109
BinaryPrimitives.WriteInt32BigEndian(header, data.Length);
109-
target.Write(header, 0, 4);
110-
target.Write(type, 0, 4);
111-
target.Write(data, 0, data.Length);
112-
113-
var crc = 0xFFFFFFFF;
114-
for (var i = 0; i < 4; i++)
115-
{
116-
crc = crc32Table[(crc ^ type[i]) & 0xFF] ^ (crc >> 8);
117-
}
118-
119-
for (var i = 0; i < data.Length; i++)
120-
{
121-
crc = crc32Table[(crc ^ data[i]) & 0xFF] ^ (crc >> 8);
122-
}
110+
target.Write(header);
111+
target.Write(type);
112+
target.Write(data);
123113

114+
var crc = new Crc32();
115+
crc.Append(type);
116+
crc.Append(data);
124117
var crcBytes = new byte[4];
125-
BinaryPrimitives.WriteUInt32BigEndian(crcBytes, crc ^ 0xFFFFFFFF);
126-
target.Write(crcBytes, 0, 4);
127-
}
128-
129-
static readonly uint[] crc32Table = GenerateCrc32Table();
130-
131-
static uint[] GenerateCrc32Table()
132-
{
133-
var table = new uint[256];
134-
for (uint i = 0; i < 256; i++)
135-
{
136-
var crc = i;
137-
for (var j = 0; j < 8; j++)
138-
{
139-
crc = (crc & 1) != 0 ? 0xEDB88320 ^ (crc >> 1) : crc >> 1;
140-
}
141-
142-
table[i] = crc;
143-
}
144-
145-
return table;
118+
BinaryPrimitives.WriteUInt32BigEndian(crcBytes, crc.GetCurrentHashAsUInt32());
119+
target.Write(crcBytes);
146120
}
147121
}

src/Directory.Packages.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<PackageVersion Include="ProjectDefaults" Version="1.0.172" />
1313
<PackageVersion Include="ProjectFiles" Version="1.0.0" />
1414
<PackageVersion Include="System.IO.Compression" Version="4.3.0" />
15+
<PackageVersion Include="System.IO.Hashing" Version="9.0.4" />
1516
<PackageVersion Include="System.Memory" Version="4.6.3" />
1617
<PackageVersion Include="System.Buffers" Version="4.6.1" />
1718
<PackageVersion Include="Verify" Version="31.13.2" />

src/Tests/GlobalUsings.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
global using DeterministicIoPackaging;
33
global using System.Buffers.Binary;
44
global using System.IO.Compression;
5+
global using System.IO.Hashing;
56
global using Polyfills;

src/Tests/PngNormalizerTests.cs

Lines changed: 15 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public void PackageConvertNormalizesPng()
8282
{
8383
var entry = archive.CreateEntry("word/media/image1.png");
8484
using var entryStream = entry.Open();
85-
entryStream.Write(png, 0, png.Length);
85+
entryStream.Write(png);
8686
}
8787

8888
zipSource.Position = 0;
@@ -94,7 +94,7 @@ public void PackageConvertNormalizesPng()
9494
{
9595
var entry = archive.CreateEntry("word/media/image1.png");
9696
using var entryStream = entry.Open();
97-
entryStream.Write(png2, 0, png2.Length);
97+
entryStream.Write(png2);
9898
}
9999

100100
zipSource2.Position = 0;
@@ -133,7 +133,7 @@ static void AssertValidPng(byte[] data)
133133
var type = Encoding.ASCII.GetString(data, offset + 4, 4);
134134
var totalSize = 12 + length;
135135

136-
var expectedCrc = ComputeCrc32(data.AsSpan(offset + 4, 4 + length));
136+
var expectedCrc = Crc32.HashToUInt32(data.AsSpan(offset + 4, 4 + length));
137137
var actualCrc = BinaryPrimitives.ReadUInt32BigEndian(data.AsSpan(offset + 8 + length));
138138
Assert.That(actualCrc, Is.EqualTo(expectedCrc), $"CRC mismatch for chunk {type}");
139139

@@ -180,7 +180,7 @@ static void AssertValidPng(byte[] data)
180180
static byte[] BuildPng(CompressionLevel level)
181181
{
182182
using var ms = new MemoryStream();
183-
ms.Write(pngSignature, 0, pngSignature.Length);
183+
ms.Write(pngSignature);
184184

185185
var ihdrData = new byte[13];
186186
BinaryPrimitives.WriteInt32BigEndian(ihdrData.AsSpan(0), 2); // width
@@ -204,7 +204,7 @@ static byte[] BuildPng(CompressionLevel level)
204204
static byte[] BuildPngWithSplitIdat()
205205
{
206206
using var ms = new MemoryStream();
207-
ms.Write(pngSignature, 0, pngSignature.Length);
207+
ms.Write(pngSignature);
208208

209209
var ihdrData = new byte[13];
210210
BinaryPrimitives.WriteInt32BigEndian(ihdrData.AsSpan(0), 2);
@@ -231,7 +231,7 @@ static byte[] BuildPngWithSplitIdat()
231231
static byte[] BuildPngWithTextChunk(string keyword, string text)
232232
{
233233
using var ms = new MemoryStream();
234-
ms.Write(pngSignature, 0, pngSignature.Length);
234+
ms.Write(pngSignature);
235235

236236
var ihdrData = new byte[13];
237237
BinaryPrimitives.WriteInt32BigEndian(ihdrData.AsSpan(0), 1);
@@ -259,7 +259,7 @@ static byte[] ZlibCompress(byte[] data, CompressionLevel level)
259259
using var output = new MemoryStream();
260260
using (var zlib = new ZLibStream(output, level, leaveOpen: true))
261261
{
262-
zlib.Write(data, 0, data.Length);
262+
zlib.Write(data);
263263
}
264264

265265
return output.ToArray();
@@ -269,59 +269,16 @@ static void WriteChunk(Stream stream, byte[] type, byte[] data)
269269
{
270270
var header = new byte[4];
271271
BinaryPrimitives.WriteInt32BigEndian(header, data.Length);
272-
stream.Write(header, 0, 4);
273-
stream.Write(type, 0, 4);
274-
stream.Write(data, 0, data.Length);
272+
stream.Write(header);
273+
stream.Write(type);
274+
stream.Write(data);
275275

276-
var crc = ComputeCrc32(type, data);
276+
var crc = new Crc32();
277+
crc.Append(type);
278+
crc.Append(data);
277279
var crcBytes = new byte[4];
278-
BinaryPrimitives.WriteUInt32BigEndian(crcBytes, crc);
279-
stream.Write(crcBytes, 0, 4);
280+
BinaryPrimitives.WriteUInt32BigEndian(crcBytes, crc.GetCurrentHashAsUInt32());
281+
stream.Write(crcBytes);
280282
}
281283

282-
static uint ComputeCrc32(ReadOnlySpan<byte> data)
283-
{
284-
var crc = 0xFFFFFFFF;
285-
foreach (var b in data)
286-
{
287-
crc = crc32Table[(crc ^ b) & 0xFF] ^ (crc >> 8);
288-
}
289-
290-
return crc ^ 0xFFFFFFFF;
291-
}
292-
293-
static uint ComputeCrc32(byte[] type, byte[] data)
294-
{
295-
var crc = 0xFFFFFFFF;
296-
foreach (var b in type)
297-
{
298-
crc = crc32Table[(crc ^ b) & 0xFF] ^ (crc >> 8);
299-
}
300-
301-
foreach (var b in data)
302-
{
303-
crc = crc32Table[(crc ^ b) & 0xFF] ^ (crc >> 8);
304-
}
305-
306-
return crc ^ 0xFFFFFFFF;
307-
}
308-
309-
static readonly uint[] crc32Table = GenerateCrc32Table();
310-
311-
static uint[] GenerateCrc32Table()
312-
{
313-
var table = new uint[256];
314-
for (uint i = 0; i < 256; i++)
315-
{
316-
var crc = i;
317-
for (var j = 0; j < 8; j++)
318-
{
319-
crc = (crc & 1) != 0 ? 0xEDB88320 ^ (crc >> 1) : crc >> 1;
320-
}
321-
322-
table[i] = crc;
323-
}
324-
325-
return table;
326-
}
327284
}

0 commit comments

Comments
 (0)