crc32demo.gno
2.16 Kb · 66 lines
1// Package crc32demo is a small gnoweb demo of the CRC-32 checksum provided by
2// the [p/moul/x/daily/crc32](/p/moul/x/daily/crc32/v0) library: it checksums a
3// few strings and shows that a one-character change moves the result
4// completely.
5//
6// It contains no checksum logic of its own. Stateless, so Render is
7// deterministic.
8package crc32demo
9
10import (
11 "strings"
12
13 "gno.land/p/g1magld5ptgzaktqcexxq0pgq5lmdf0kz6re8hlv/md/v0"
14 "gno.land/p/g1magld5ptgzaktqcexxq0pgq5lmdf0kz6re8hlv/x/daily/crc32/v0"
15)
16
17var samples = []string{"", "a", "abc", "123456789", "hello world", "hello worle"}
18
19// Render renders the demo for gnoweb.
20//
21// Render("") / Render("/") -> the samples table
22// Render("/<text>") -> checksum that text
23func Render(path string) string {
24 var b strings.Builder
25 b.WriteString("# CRC-32\n\n")
26 b.WriteString("The IEEE checksum behind zip, gzip and PNG, demoing the ")
27 b.WriteString("[`p/moul/x/daily/crc32`](/p/moul/x/daily/crc32/v0) library.\n\n")
28
29 if in := parseArg(path); in != "" {
30 b.WriteString("## " + md.InlineCode(in))
31 b.WriteString("\n\n`")
32 b.WriteString(crc32.ChecksumHex(in))
33 b.WriteString("`\n")
34 return b.String()
35 }
36
37 b.WriteString("| input | crc32 |\n|---|---|\n")
38 for _, s := range samples {
39 b.WriteString("| ")
40 if s == "" {
41 b.WriteString("_(empty)_")
42 } else {
43 //gnovet:ignore render-path-in-code-span s ranges over a fixed sample list, never over the URL path
44 b.WriteString("`" + s + "`")
45 }
46 b.WriteString(" | `")
47 b.WriteString(crc32.ChecksumHex(s))
48 b.WriteString("` |\n")
49 }
50 b.WriteString("\n`123456789` → `cbf43926` is the standard CRC-32 check value, ")
51 b.WriteString("so this table doubles as a conformance test.\n\n")
52 b.WriteString("> The last two rows differ by one letter and share no digits: ")
53 b.WriteString("that avalanche is the point.\n\n")
54 b.WriteString("> A CRC detects **accidents**, not tampering — it is linear, so a ")
55 b.WriteString("matching message is easy to craft. Never authenticate with it.\n")
56 return b.String()
57}
58
59func parseArg(path string) string {
60 s := strings.TrimSpace(path)
61 s = strings.TrimPrefix(s, "/")
62 if i := strings.IndexByte(s, '/'); i >= 0 {
63 s = s[:i]
64 }
65 return s
66}