// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package adler32 implements the Adler-32 checksum. // // It is defined in RFC 1950: // // Adler-32 is composed of two sums accumulated per byte: s1 is // the sum of all bytes, s2 is the sum of all s1 values. Both sums // are done modulo 65521. s1 is initialized to 1, s2 to zero. The // Adler-32 checksum is stored as s2*65536 + s1 in most- // significant-byte first (network) order.
package adler32 import ( ) const ( // mod is the largest prime that is less than 65536. mod = 65521 // nmax is the largest n such that // 255 * n * (n+1) / 2 + (n+1) * (mod-1) <= 2^32-1. // It is mentioned in RFC 1950 (search for "5552"). nmax = 5552 ) // The size of an Adler-32 checksum in bytes. const Size = 4 // digest represents the partial evaluation of a checksum. // The low 16 bits are s1, the high 16 bits are s2. type digest uint32 func ( *digest) () { * = 1 } // New returns a new hash.Hash32 computing the Adler-32 checksum. Its // Sum method will lay the value out in big-endian byte order. The // returned Hash32 also implements [encoding.BinaryMarshaler] and // [encoding.BinaryUnmarshaler] to marshal and unmarshal the internal // state of the hash. func () hash.Hash32 { := new(digest) .Reset() return } func ( *digest) () int { return Size } func ( *digest) () int { return 4 } const ( magic = "adl\x01" marshaledSize = len(magic) + 4 ) func ( *digest) () ([]byte, error) { := make([]byte, 0, marshaledSize) = append(, magic...) = appendUint32(, uint32(*)) return , nil } func ( *digest) ( []byte) error { if len() < len(magic) || string([:len(magic)]) != magic { return errors.New("hash/adler32: invalid hash state identifier") } if len() != marshaledSize { return errors.New("hash/adler32: invalid hash state size") } * = digest(readUint32([len(magic):])) return nil } // appendUint32 is semantically the same as [binary.BigEndian.AppendUint32] // We copied this function because we can not import "encoding/binary" here. func appendUint32( []byte, uint32) []byte { return append(, byte(>>24), byte(>>16), byte(>>8), byte(), ) } // readUint32 is semantically the same as [binary.BigEndian.Uint32] // We copied this function because we can not import "encoding/binary" here. func readUint32( []byte) uint32 { _ = [3] return uint32([3]) | uint32([2])<<8 | uint32([1])<<16 | uint32([0])<<24 } // Add p to the running checksum d. func update( digest, []byte) digest { , := uint32(&0xffff), uint32(>>16) for len() > 0 { var []byte if len() > nmax { , = [:nmax], [nmax:] } for len() >= 4 { += uint32([0]) += += uint32([1]) += += uint32([2]) += += uint32([3]) += = [4:] } for , := range { += uint32() += } %= mod %= mod = } return digest(<<16 | ) } func ( *digest) ( []byte) ( int, error) { * = update(*, ) return len(), nil } func ( *digest) () uint32 { return uint32(*) } func ( *digest) ( []byte) []byte { := uint32(*) return append(, byte(>>24), byte(>>16), byte(>>8), byte()) } // Checksum returns the Adler-32 checksum of data. func ( []byte) uint32 { return uint32(update(1, )) }