From 5f988127a8bc567f44dc1de0ea7844632e584b48 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 2 Apr 2024 12:52:28 -0700 Subject: [PATCH 1/4] Use singular helper when creating checksumsw --- .../Workspace/Solution/Checksum_Factory.cs | 72 ++++++------------- 1 file changed, 20 insertions(+), 52 deletions(-) diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/Checksum_Factory.cs b/src/Workspaces/Core/Portable/Workspace/Solution/Checksum_Factory.cs index d269819d14acf..17749b5ccb731 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/Checksum_Factory.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/Checksum_Factory.cs @@ -55,25 +55,15 @@ public static Checksum Create(Stream stream) return From(hash); } - public static Checksum Create(T @object, Action writeObject) - { - using var stream = SerializableBytes.CreateWritableStream(); - - using (var objectWriter = new ObjectWriter(stream, leaveOpen: true)) - { - writeObject(@object, objectWriter); - } - - stream.Position = 0; - return Create(stream); - } - public static Checksum Create(Checksum checksum1, Checksum checksum2) => Create(stackalloc[] { checksum1, checksum2 }); public static Checksum Create(Checksum checksum1, Checksum checksum2, Checksum checksum3) => Create(stackalloc[] { checksum1, checksum2, checksum3 }); + public static Checksum Create(Checksum checksum1, Checksum checksum2, Checksum checksum3, Checksum checksum4) + => Create(stackalloc[] { checksum1, checksum2, checksum3, checksum4 }); + public static Checksum Create(ReadOnlySpan hashes) { Span destination = stackalloc byte[XXHash128SizeBytes]; @@ -82,68 +72,46 @@ public static Checksum Create(ReadOnlySpan hashes) } public static Checksum Create(ArrayBuilder checksums) - { - using var stream = SerializableBytes.CreateWritableStream(); - - using (var writer = new ObjectWriter(stream, leaveOpen: true)) + => Create(checksums, static (checksums, writer) => { foreach (var checksum in checksums) checksum.WriteTo(writer); - } - - stream.Position = 0; - return Create(stream); - } + }); public static Checksum Create(ImmutableArray checksums) - { - using var stream = SerializableBytes.CreateWritableStream(); - - using (var writer = new ObjectWriter(stream, leaveOpen: true)) + => Create(checksums, static (checksums, writer) => { foreach (var checksum in checksums) checksum.WriteTo(writer); - } - - stream.Position = 0; - return Create(stream); - } + }); public static Checksum Create(ImmutableArray bytes) - { - using var stream = SerializableBytes.CreateWritableStream(); - - using (var writer = new ObjectWriter(stream, leaveOpen: true)) + => Create(bytes, static (bytes, writer) => { - for (var i = 0; i < bytes.Length; i++) - writer.WriteByte(bytes[i]); - } - - stream.Position = 0; - return Create(stream); - } + foreach (var b in bytes) + writer.WriteByte(b); + }); public static Checksum Create(T value, ISerializerService serializer) { - using var stream = SerializableBytes.CreateWritableStream(); using var context = new SolutionReplicationContext(); - using (var objectWriter = new ObjectWriter(stream, leaveOpen: true)) - { - serializer.Serialize(value!, objectWriter, context, CancellationToken.None); - } - - stream.Position = 0; - return Create(stream); + return Create( + (value, serializer, context), + static (tuple, writer) => + { + var (value, serializer, context) = tuple; + serializer.Serialize(value!, writer, context, CancellationToken.None); + }); } - public static Checksum Create(ParseOptions value, ISerializerService serializer) + public static Checksum Create(T value, Action writeTo) { using var stream = SerializableBytes.CreateWritableStream(); using (var objectWriter = new ObjectWriter(stream, leaveOpen: true)) { - serializer.SerializeParseOptions(value, objectWriter); + writeTo(value, objectWriter); } stream.Position = 0; From 0afa747a0838d22f25b258172a4173c5aa022074 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 2 Apr 2024 12:53:57 -0700 Subject: [PATCH 2/4] Use singular helper when creating checksumsw --- .../Workspace/Solution/Checksum_Factory.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/Checksum_Factory.cs b/src/Workspaces/Core/Portable/Workspace/Solution/Checksum_Factory.cs index 17749b5ccb731..95519835568d7 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/Checksum_Factory.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/Checksum_Factory.cs @@ -55,6 +55,19 @@ public static Checksum Create(Stream stream) return From(hash); } + public static Checksum Create(T @object, Action writeObject) + { + using var stream = SerializableBytes.CreateWritableStream(); + + using (var objectWriter = new ObjectWriter(stream, leaveOpen: true)) + { + writeObject(@object, objectWriter); + } + + stream.Position = 0; + return Create(stream); + } + public static Checksum Create(Checksum checksum1, Checksum checksum2) => Create(stackalloc[] { checksum1, checksum2 }); @@ -104,17 +117,4 @@ public static Checksum Create(T value, ISerializerService serializer) serializer.Serialize(value!, writer, context, CancellationToken.None); }); } - - public static Checksum Create(T value, Action writeTo) - { - using var stream = SerializableBytes.CreateWritableStream(); - - using (var objectWriter = new ObjectWriter(stream, leaveOpen: true)) - { - writeTo(value, objectWriter); - } - - stream.Position = 0; - return Create(stream); - } } From 3b0fe274bf3556d61ba724521d0d90a31b8fc3e1 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 2 Apr 2024 12:55:45 -0700 Subject: [PATCH 3/4] Downstream --- src/Workspaces/Core/Portable/Serialization/SerializerService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Workspaces/Core/Portable/Serialization/SerializerService.cs b/src/Workspaces/Core/Portable/Serialization/SerializerService.cs index de2be0884f347..e52f664c6694e 100644 --- a/src/Workspaces/Core/Portable/Serialization/SerializerService.cs +++ b/src/Workspaces/Core/Portable/Serialization/SerializerService.cs @@ -205,7 +205,7 @@ private IOptionsSerializationService GetOptionsSerializationService(string langu => _lazyLanguageSerializationService.GetOrAdd(languageName, n => _workspaceServices.GetLanguageServices(n).GetRequiredService()); public Checksum CreateParseOptionsChecksum(ParseOptions value) - => Checksum.Create(value, this); + => Checksum.Create((value, @this: this), static (tuple, writer) => tuple.@this.SerializeParseOptions(tuple.value, writer)); } // TODO: convert this to sub class rather than using enum with if statement. From 307d04aa1e4061c85f72527c64822d72fbb9e907 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 2 Apr 2024 13:02:26 -0700 Subject: [PATCH 4/4] Add test --- src/Workspaces/CoreTest/ChecksumTests.cs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/Workspaces/CoreTest/ChecksumTests.cs b/src/Workspaces/CoreTest/ChecksumTests.cs index e56f177d1092f..fe1abf9386512 100644 --- a/src/Workspaces/CoreTest/ChecksumTests.cs +++ b/src/Workspaces/CoreTest/ChecksumTests.cs @@ -49,6 +49,30 @@ public void ValidateChecksumFromSpanSameAsChecksumFromBytes2() Assert.NotEqual(checksum3, checksumA); } + [Fact] + public void ValidateChecksumFromSpanSameAsChecksumFromBytes3() + { + var checksum1 = Checksum.Create("Goo"); + var checksum2 = Checksum.Create("Bar"); + var checksum3 = Checksum.Create("Baz"); + var checksum4 = Checksum.Create("Quux"); + + var checksumA = Checksum.Create(checksum1, checksum2, checksum3, checksum4); + + // Running this test on multiple target frameworks with the same expectation ensures the results match + Assert.Equal(Checksum.FromBase64String("vva1KeNW7vz7PNnIyM3K6g=="), checksumA); + + Assert.NotEqual(checksum1, checksum2); + Assert.NotEqual(checksum2, checksum3); + Assert.NotEqual(checksum3, checksum4); + Assert.NotEqual(checksum4, checksum1); + + Assert.NotEqual(checksum1, checksumA); + Assert.NotEqual(checksum2, checksumA); + Assert.NotEqual(checksum3, checksumA); + Assert.NotEqual(checksum4, checksumA); + } + [Fact] public void ValidateChecksumFromSpanSameAsChecksumFromBytes10() {