Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

base32demo.gno

2.59 Kb · 88 lines
 1// Package base32demo is a small gnoweb demo of the base32 codec provided by the
 2// [p/moul/x/daily/base32](/p/moul/x/daily/base32/v0) library: it shows the RFC
 3// 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 base32demo
 7
 8import (
 9	"strings"
10
11	"gno.land/p/moul/x/daily/base32/v0"
12)
13
14// The RFC 4648 §10 vectors — every partial-group length.
15var vectors = []string{"", "f", "fo", "foo", "foob", "fooba", "foobar"}
16
17// Render renders the demo for gnoweb.
18//
19//	Render("")       / Render("/") -> the vectors + Crockford forgiveness
20//	Render("/<text>")              -> encode that text both ways
21func Render(path string) string {
22	var b strings.Builder
23	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")
26
27	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	}
39
40	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	}
56
57	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}
80
81func 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 s
88}