v / vlib / hash / adler32 / adler32.v
51 lines · 45 sloc · 1.45 KB · c410aee218fca542202f5601d77f214746dceb5f
Raw
1// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4
5// This is a pure V implementation of Adler-32 from RFC 1950.
6// Parameters: BASE=65521, init=1, output=(s2 << 16) | s1.
7module adler32
8
9// base is the largest prime smaller than 2^16, mandated by RFC 1950.
10pub const base = u32(65521)
11// nmax is the largest chunk size that keeps intermediate sums inside u32.
12// See RFC 1950 Appendix and zlib's adler32 implementation.
13pub const nmax = 5552
14
15// update_state updates an Adler-32 state with `data`.
16// For RFC-1950 compliant checksums, use state `1` for a new stream.
17@[direct_array_access]
18pub fn update_state(state u32, data []u8) u32 {
19 mut s1 := state & u32(0xffff)
20 mut s2 := state >> 16
21 mut pos := 0
22 for pos < data.len {
23 block_len := if data.len - pos > nmax { nmax } else { data.len - pos }
24 for _ in 0 .. block_len {
25 s1 += data[pos]
26 if s1 >= base {
27 s1 -= base
28 }
29 s2 += s1
30 pos++
31 }
32 s2 %= base
33 }
34 return (s2 << 16) | s1
35}
36
37// checksum returns the RFC-1950 Adler-32 checksum for `data`.
38pub fn checksum(data []u8) u32 {
39 return update_state(u32(1), data)
40}
41
42// update extends an existing Adler-32 checksum `adler` with `data`.
43// Use `adler = 1` for a fresh checksum.
44pub fn update(adler u32, data []u8) u32 {
45 return update_state(adler, data)
46}
47
48// sum is an alias for checksum.
49pub fn sum(data []u8) u32 {
50 return checksum(data)
51}
52