1// Package bidimapdemo is a small gnoweb demo of the bidirectional map provided2// by the [p/moul/x/daily/bidimap](/p/moul/x/daily/bidimap/v0) library: it shows3// the reverse lookup and what happens when a binding is displaced.4//5// It contains no map logic of its own. Stateless, so Render is deterministic —6// which is precisely what the library is for.7package bidimapdemo89import (10 "strconv"11 "strings"1213 "gno.land/p/moul/x/daily/bidimap/v0"14)1516// Render renders the demo for gnoweb.17func Render(path string) string {18 var b strings.Builder19 b.WriteString("# Bidirectional Map\n\n")20 b.WriteString("Unique in both directions, demoing the ")21 b.WriteString("[`p/moul/x/daily/bidimap`](/p/moul/x/daily/bidimap/v0) library.\n\n")2223 m := bidimap.New()24 m.Put("alice", "admin")25 m.Put("bob", "auditor")26 m.Put("carol", "treasurer")2728 b.WriteString("## Roles\n\n")29 b.WriteString(table(m))3031 b.WriteString("\n## Both directions are O(1)\n\n")32 v, _ := m.Get("bob")33 k, _ := m.GetKey("treasurer")34 b.WriteString("- `Get(\"bob\")` → `" + v + "`\n")35 b.WriteString("- `GetKey(\"treasurer\")` → `" + k + "` — the reverse index, not a scan\n\n")3637 b.WriteString("## Displacing a binding\n\n")38 b.WriteString("Both sides are unique, so giving `alice` the `auditor` role cannot ")39 b.WriteString("simply be written — `bob` already holds it, and `alice` already holds ")40 b.WriteString("`admin`. `Put` **replaces**, and reports what it displaced:\n\n")41 evicted, _ := m.Put("alice", "auditor")42 b.WriteString("| displaced key | displaced value |\n|---|---|\n")43 for _, p := range evicted {44 b.WriteString("| `" + p[0] + "` | `" + p[1] + "` |\n")45 }46 b.WriteString("\n" + table(m))47 b.WriteString("\n`bob` is now unassigned and the `admin` role is vacant — one call, ")48 b.WriteString("both indexes still agreeing.\n\n")4950 b.WriteString("## Refusing instead\n\n")51 b.WriteString("`PutUnique` makes the other choice: it declines rather than displace.\n\n")52 ok := m.PutUnique("dave", "auditor")53 b.WriteString("- `PutUnique(\"dave\", \"auditor\")` → `" + strconv.FormatBool(ok) + "` — the role is taken\n")54 ok = m.PutUnique("dave", "secretary")55 b.WriteString("- `PutUnique(\"dave\", \"secretary\")` → `" + strconv.FormatBool(ok) + "` — both sides free\n\n")56 b.WriteString(table(m))5758 b.WriteString("\n> Keys come back **sorted**, never in map order: gno map iteration ")59 b.WriteString("order is unspecified, and a page built from one can differ between ")60 b.WriteString("nodes — a consensus bug, not a cosmetic one.\n")61 return b.String()62}6364func table(m *bidimap.BiMap) string {65 var b strings.Builder66 b.WriteString("| person | role |\n|---|---|\n")67 m.Iterate(func(k, v string) bool {68 b.WriteString("| `" + k + "` | `" + v + "` |\n")69 return false70 })71 return b.String()72}73Render(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.