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

rledemo.gno

2.59 Kb · 99 lines
 1// Package rledemo is a small gnoweb demo of the run-length codec provided by
 2// the [p/moul/x/daily/rle](/p/moul/x/daily/rle/v0) library: it encodes a few
 3// sample strings, round-trips them, and reports the size ratio — including the
 4// case where the "compression" makes things bigger.
 5//
 6// It contains no codec logic of its own. Stateless, so Render is deterministic.
 7package rledemo
 8
 9import (
10	"strconv"
11	"strings"
12
13	"gno.land/p/moul/x/daily/rle/v0"
14)
15
16// samples are picked to show both outcomes: runny data compresses, data
17// without runs expands.
18var samples = []string{
19	"aaaaaaaaaabbbbbbbbbb",
20	"aaabbc",
21	"abcdef",
22}
23
24// Render renders the demo for gnoweb.
25//
26//	Render("")        / Render("/") -> the samples table
27//	Render("/<text>")               -> encode that text
28func Render(path string) string {
29	var b strings.Builder
30	b.WriteString("# Run-Length Encoding\n\n")
31	b.WriteString("`<count><char>` pairs, demoing the ")
32	b.WriteString("[`p/moul/x/daily/rle`](/p/moul/x/daily/rle/v0) library.\n\n")
33
34	if in := parseArg(path); in != "" {
35		return b.String() + one(in)
36	}
37
38	b.WriteString("| input | encoded | size | round-trips |\n|---|---|---|---|\n")
39	for _, s := range samples {
40		enc, err := rle.Encode(s)
41		if err != nil {
42			continue
43		}
44		dec, _ := rle.Decode(enc)
45		b.WriteString("| `")
46		b.WriteString(s)
47		b.WriteString("` | `")
48		b.WriteString(enc)
49		b.WriteString("` | ")
50		b.WriteString(strconv.Itoa(rle.Ratio(s, enc)))
51		b.WriteString("% | ")
52		if dec == s {
53			b.WriteString("✅")
54		} else {
55			b.WriteString("❌")
56		}
57		b.WriteString(" |\n")
58	}
59	b.WriteString("\n> Over 100% means the encoding made the data **bigger**. ")
60	b.WriteString("RLE only wins on runny input, and `abcdef` is the honest counter-example.\n\n")
61	b.WriteString("> Append text to the path to encode it — digits are rejected, ")
62	b.WriteString("since they would be ambiguous with a run count.\n")
63	return b.String()
64}
65
66func one(in string) string {
67	var b strings.Builder
68	b.WriteString("## `")
69	b.WriteString(in)
70	b.WriteString("`\n\n")
71	enc, err := rle.Encode(in)
72	if err != nil {
73		b.WriteString("_")
74		b.WriteString(err.Error())
75		b.WriteString("_\n")
76		return b.String()
77	}
78	dec, _ := rle.Decode(enc)
79	b.WriteString("- encoded: `")
80	b.WriteString(enc)
81	b.WriteString("`\n- size: **")
82	b.WriteString(strconv.Itoa(rle.Ratio(in, enc)))
83	b.WriteString("%**\n- round-trips: ")
84	if dec == in {
85		b.WriteString("✅\n")
86	} else {
87		b.WriteString("❌\n")
88	}
89	return b.String()
90}
91
92func parseArg(path string) string {
93	s := strings.TrimSpace(path)
94	s = strings.TrimPrefix(s, "/")
95	if i := strings.IndexByte(s, '/'); i >= 0 {
96		s = s[:i]
97	}
98	return s
99}