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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

rledemo.gno

2.88 Kb · 100 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/g1magld5ptgzaktqcexxq0pgq5lmdf0kz6re8hlv/md/v0"
 14	"gno.land/p/g1magld5ptgzaktqcexxq0pgq5lmdf0kz6re8hlv/x/daily/rle/v0"
 15)
 16
 17// samples are picked to show both outcomes: runny data compresses, data
 18// without runs expands.
 19var samples = []string{
 20	"aaaaaaaaaabbbbbbbbbb",
 21	"aaabbc",
 22	"abcdef",
 23}
 24
 25// Render renders the demo for gnoweb.
 26//
 27//	Render("")        / Render("/") -> the samples table
 28//	Render("/<text>")               -> encode that text
 29func Render(path string) string {
 30	var b strings.Builder
 31	b.WriteString("# Run-Length Encoding\n\n")
 32	b.WriteString("`<count><char>` pairs, demoing the ")
 33	b.WriteString("[`p/moul/x/daily/rle`](/p/moul/x/daily/rle/v0) library.\n\n")
 34
 35	if in := parseArg(path); in != "" {
 36		return b.String() + one(in)
 37	}
 38
 39	b.WriteString("| input | encoded | size | round-trips |\n|---|---|---|---|\n")
 40	for _, s := range samples {
 41		enc, err := rle.Encode(s)
 42		if err != nil {
 43			continue
 44		}
 45		dec, _ := rle.Decode(enc)
 46		b.WriteString("| `")
 47		b.WriteString(s)
 48		b.WriteString("` | `")
 49		b.WriteString(enc)
 50		b.WriteString("` | ")
 51		b.WriteString(strconv.Itoa(rle.Ratio(s, enc)))
 52		b.WriteString("% | ")
 53		if dec == s {
 54			b.WriteString("✅")
 55		} else {
 56			b.WriteString("❌")
 57		}
 58		b.WriteString(" |\n")
 59	}
 60	b.WriteString("\n> Over 100% means the encoding made the data **bigger**. ")
 61	b.WriteString("RLE only wins on runny input, and `abcdef` is the honest counter-example.\n\n")
 62	b.WriteString("> Append text to the path to encode it — digits are rejected, ")
 63	b.WriteString("since they would be ambiguous with a run count.\n")
 64	return b.String()
 65}
 66
 67// one encodes a caller's text. The encoder runs first, so a rejected input is
 68// never echoed, and an accepted one still goes through md.InlineCode: rle
 69// accepts a backtick, and its encoding carries it through.
 70func one(in string) string {
 71	var b strings.Builder
 72	enc, err := rle.Encode(in)
 73	if err != nil {
 74		b.WriteString("_")
 75		b.WriteString(err.Error())
 76		b.WriteString("_\n")
 77		return b.String()
 78	}
 79	b.WriteString("## " + md.InlineCode(in) + "\n\n")
 80	dec, _ := rle.Decode(enc)
 81	b.WriteString("- encoded: " + md.InlineCode(enc))
 82	b.WriteString("\n- size: **")
 83	b.WriteString(strconv.Itoa(rle.Ratio(in, enc)))
 84	b.WriteString("%**\n- round-trips: ")
 85	if dec == in {
 86		b.WriteString("✅\n")
 87	} else {
 88		b.WriteString("❌\n")
 89	}
 90	return b.String()
 91}
 92
 93func parseArg(path string) string {
 94	s := strings.TrimSpace(path)
 95	s = strings.TrimPrefix(s, "/")
 96	if i := strings.IndexByte(s, '/'); i >= 0 {
 97		s = s[:i]
 98	}
 99	return s
100}