52 lines
1.5 KiB
V
52 lines
1.5 KiB
V
// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
|
|
// Use of this source code is governed by an MIT license
|
|
// that can be found in the LICENSE file.
|
|
|
|
// This is a pure V implementation of Adler-32 from RFC 1950.
|
|
// Parameters: BASE=65521, init=1, output=(s2 << 16) | s1.
|
|
module adler32
|
|
|
|
// base is the largest prime smaller than 2^16, mandated by RFC 1950.
|
|
pub const base = u32(65521)
|
|
// nmax is the largest chunk size that keeps intermediate sums inside u32.
|
|
// See RFC 1950 Appendix and zlib's adler32 implementation.
|
|
pub const nmax = 5552
|
|
|
|
// update_state updates an Adler-32 state with `data`.
|
|
// For RFC-1950 compliant checksums, use state `1` for a new stream.
|
|
@[direct_array_access]
|
|
pub fn update_state(state u32, data []u8) u32 {
|
|
mut s1 := state & u32(0xffff)
|
|
mut s2 := state >> 16
|
|
mut pos := 0
|
|
for pos < data.len {
|
|
block_len := if data.len - pos > nmax { nmax } else { data.len - pos }
|
|
for _ in 0 .. block_len {
|
|
s1 += data[pos]
|
|
if s1 >= base {
|
|
s1 -= base
|
|
}
|
|
s2 += s1
|
|
pos++
|
|
}
|
|
s2 %= base
|
|
}
|
|
return (s2 << 16) | s1
|
|
}
|
|
|
|
// checksum returns the RFC-1950 Adler-32 checksum for `data`.
|
|
pub fn checksum(data []u8) u32 {
|
|
return update_state(u32(1), data)
|
|
}
|
|
|
|
// update extends an existing Adler-32 checksum `adler` with `data`.
|
|
// Use `adler = 1` for a fresh checksum.
|
|
pub fn update(adler u32, data []u8) u32 {
|
|
return update_state(adler, data)
|
|
}
|
|
|
|
// sum is an alias for checksum.
|
|
pub fn sum(data []u8) u32 {
|
|
return checksum(data)
|
|
}
|