1// Package base32demo is a small gnoweb demo of the base32 codec provided by the2// [p/moul/x/daily/base32](/p/moul/x/daily/base32/v0) library: it shows the RFC3// 4648 vectors alongside Crockford, and the forgiving decodes Crockford allows.4//5// It contains no codec logic of its own. Stateless, so Render is deterministic.6package base32demo78import (9 "strings"1011 "gno.land/p/moul/x/daily/base32/v0"12)1314// The RFC 4648 §10 vectors — every partial-group length.15var vectors = []string{"", "f", "fo", "foo", "foob", "fooba", "foobar"}1617// Render renders the demo for gnoweb.18//19// Render("") / Render("/") -> the vectors + Crockford forgiveness20// Render("/<text>") -> encode that text both ways21func Render(path string) string {22 var b strings.Builder23 b.WriteString("# Base32\n\n")24 b.WriteString("RFC 4648 and Crockford, demoing the ")25 b.WriteString("[`p/moul/x/daily/base32`](/p/moul/x/daily/base32/v0) library.\n\n")2627 if in := parseArg(path); in != "" {28 std, _ := base32.Encode(in)29 ck, _ := base32.EncodeCrockford(in)30 b.WriteString("## `")31 b.WriteString(in)32 b.WriteString("`\n\n- RFC 4648: `")33 b.WriteString(std)34 b.WriteString("`\n- Crockford: `")35 b.WriteString(ck)36 b.WriteString("`\n")37 return b.String()38 }3940 b.WriteString("| input | RFC 4648 | Crockford |\n|---|---|---|\n")41 for _, v := range vectors {42 std, _ := base32.Encode(v)43 ck, _ := base32.EncodeCrockford(v)44 b.WriteString("| ")45 if v == "" {46 b.WriteString("_(empty)_")47 } else {48 b.WriteString("`" + v + "`")49 }50 b.WriteString(" | `")51 b.WriteString(std)52 b.WriteString("` | `")53 b.WriteString(ck)54 b.WriteString("` |\n")55 }5657 b.WriteString("\n## Crockford forgives\n\n")58 enc, _ := base32.EncodeCrockford("hello")59 b.WriteString("`hello` encodes to `")60 b.WriteString(enc)61 b.WriteString("`, and all of these decode back to it:\n\n")62 variants := []string{enc, strings.ToLower(enc), enc[:2] + "-" + enc[2:]}63 for _, v := range variants {64 dec, err := base32.DecodeCrockford(v)65 b.WriteString("- `")66 b.WriteString(v)67 b.WriteString("` → ")68 if err == nil && dec == "hello" {69 b.WriteString("`hello` ✅")70 } else {71 b.WriteString("❌")72 }73 b.WriteString("\n")74 }75 b.WriteString("\n> Crockford folds case, reads `I`/`L` as `1` and `O` as `0`, and ")76 b.WriteString("ignores hyphens — so an identifier survives being read aloud and typed back. ")77 b.WriteString("`U` is left out of the alphabet on purpose.\n")78 return b.String()79}8081func parseArg(path string) string {82 s := strings.TrimSpace(path)83 s = strings.TrimPrefix(s, "/")84 if i := strings.IndexByte(s, '/'); i >= 0 {85 s = s[:i]86 }87 return s88}89Render(path string) string
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.