1// Package ringlog is an on-chain port of Go's container/ring: a fixed-capacity2// circular message board where new posts overwrite the oldest entries once full.3package ringlog45import (6 "chain/runtime"7 "chain/runtime/unsafe"8 "strconv"9 "strings"10)1112// Cap is the maximum number of messages the ring buffer holds.13const Cap = 161415// Entry is a single posted message.16type Entry struct {17 Author address18 Message string19 Height int6420}2122var (23 buf [Cap]Entry // the ring storage24 head int // index of the next write slot25 count int // number of entries currently stored (0 ≤ count ≤ Cap)26)2728// Post adds a message to the ring buffer.29// Once Cap entries are stored, the oldest entry is overwritten.30func Post(msg string) {31 msg = strings.TrimSpace(msg)32 if len(msg) == 0 {33 panic("message cannot be empty")34 }35 if len(msg) > 280 {36 panic("message too long (max 280 chars)")37 }38 buf[head] = Entry{39 Author: unsafe.PreviousRealm().Address(),40 Message: msg,41 Height: runtime.ChainHeight(),42 }43 head = (head + 1) % Cap44 if count < Cap {45 count++46 }47}4849// Entries returns all stored messages in chronological order (oldest first).50func Entries() []Entry {51 if count == 0 {52 return nil53 }54 result := make([]Entry, count)55 oldest := (head - count + Cap) % Cap56 for i := 0; i < count; i++ {57 result[i] = buf[(oldest+i)%Cap]58 }59 return result60}6162// Len returns the number of messages currently stored.63func Len() int { return count }6465// Render displays the ring buffer as a Markdown page.66func Render(path string) string {67 var sb strings.Builder6869 sb.WriteString("# RingLog\n\n")70 sb.WriteString("> A ring-buffer message board (capacity: **")71 sb.WriteString(strconv.Itoa(Cap))72 sb.WriteString("**). New messages overwrite the oldest once the buffer is full.\n\n")7374 if count == 0 {75 sb.WriteString("*No messages yet. Call `Post(msg)` to add one.*\n")76 return sb.String()77 }7879 sb.WriteString("| # | Author | Block | Message |\n")80 sb.WriteString("|---|--------|-------|---------|\n")8182 entries := Entries()83 for i, e := range entries {84 sb.WriteString("| ")85 sb.WriteString(strconv.Itoa(i + 1))86 sb.WriteString(" | `")87 sb.WriteString(shorten(e.Author.String()))88 sb.WriteString("` | ")89 sb.WriteString(strconv.FormatInt(e.Height, 10))90 sb.WriteString(" | ")91 sb.WriteString(e.Message)92 sb.WriteString(" |\n")93 }9495 sb.WriteString("\n*Showing ")96 sb.WriteString(strconv.Itoa(count))97 sb.WriteString(" of ")98 sb.WriteString(strconv.Itoa(Cap))99 sb.WriteString(" slots used.*\n")100101 return sb.String()102}103104// shorten trims a long address for display.105func shorten(s string) string {106 if len(s) <= 14 {107 return s108 }109 return s[:6] + "…" + s[len(s)-6:]110}111Entries() []gno.land/r/moul/x/daily/ringlog/v0.Entry
Len() int
Post(msg string)
Render(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.