Repository: dotnet/runtime
File: src/libraries/System.IO.Hashing/src/System/IO/Hashing/Adler32.cs (C#)

Code before:
            }

            uint hash = HashToUInt32(source);
            BinaryPrimitives.WriteUInt32LittleEndian(destination, hash);
            return Size;
        }

        /// <summary>
        /// Computes the Adler-32 hash of the provided data.
        /// </summary>
        /// <param name="source">The data to hash.</param>
        /// <returns>
        /// The computed Adler-32 hash.
        /// </returns>
        [CLSCompliant(false)]
        public static uint HashToUInt32(ReadOnlySpan<byte> source)
            => Update(InitialState, source);

        private const uint Base = 65521; // largest prime smaller than 65536
        private const int NMax = 5552;   // NMax is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1

        private static uint Update(uint adler, ReadOnlySpan<byte> buf)
        {
            if (buf.IsEmpty)
            {
                return 1u;
            }

            uint s1 = adler & 0xFFFF;
            uint s2 = (adler >> 16) & 0xFFFF;
            while (buf.Length > 0)
            {
                int k = buf.Length < NMax ? buf.Length : NMax;
                foreach (byte b in buf.Slice(0, k))
                {
                    s1 += b;
                    s2 += s1;
                }
                s1 %= Base;
                s2 %= Base;
                buf = buf.Slice(k);
            }

            return (s2 << 16) | s1;
        }
    }
}


Review comment (suggestion):
Is returning `1u` here for an empty buffer correct? `Append` is implemented as

```C#
public override void Append(ReadOnlySpan<byte> source) => _adler = Update(_adler, source);
```

So if I do

```C#
Adler32 hash = new();
hash.Append([1, 2, 3]);
hash.Append([]);
uint final = hash.GetCurrentHashAsUInt32();
```

The final hash will be 1. Is that expected?

I would expect returning `adler` would be the correct thing to do.

Code after:

            uint hash = HashToUInt32(source);
            BinaryPrimitives.WriteUInt32BigEndian(destination, hash);
            return Size;
        }

        /// <summary>
        /// Computes the Adler-32 hash of the provided data.
        /// </summary>
        /// <param name="source">The data to hash.</param>
        /// <returns>
        /// The computed Adler-32 hash.
        /// </returns>
        [CLSCompliant(false)]
        public static uint HashToUInt32(ReadOnlySpan<byte> source)
            => Update(InitialState, source);

        private static uint Update(uint adler, ReadOnlySpan<byte> buf)
        {
            if (buf.IsEmpty)
            {
                return adler;
            }

            return UpdateScalar(adler, buf);
        }

        private static uint UpdateScalar(uint adler, ReadOnlySpan<byte> buf)
        {
            const uint Base = 65521; // largest prime smaller than 65536
            const int NMax = 5552; // NMax is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1

            uint s1 = adler & 0xFFFF;
            uint s2 = (adler >> 16) & 0xFFFF;
            while (buf.Length > 0)
            {
                int k = buf.Length < NMax ? buf.Length : NMax;
                foreach (byte b in buf.Slice(0, k))
                {
                    s1 += b;
                    s2 += s1;
                }
                s1 %= Base;
                s2 %= Base;
                buf = buf.Slice(k);
            }

            return (s2 << 16) | s1;
        }
    }
}