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.

record.gno

1.65 Kb · 70 lines
 1package gnotif
 2
 3import (
 4	"strconv"
 5	"strings"
 6)
 7
 8const recordFields = 8
 9
10// record is a trigger, its target and its name as the registry stores them:
11// one string per trigger, because a tree holds a string inline and a struct
12// is one more stored object.
13type record struct {
14	Target string
15	Name   string
16	T      Trigger
17}
18
19func (r record) encode() string {
20	return packFields(r.Target, r.Name, r.T.Event, r.T.Filter, r.T.Param, r.T.Title, r.T.Body, r.T.Link)
21}
22
23// decodeRecord reads a string made by encode and panics on any other.
24func decodeRecord(v any) record {
25	f := unpackFields(v.(string), recordFields)
26	return record{
27		Target: f[0],
28		Name:   f[1],
29		T:      Trigger{Event: f[2], Filter: f[3], Param: f[4], Title: f[5], Body: f[6], Link: f[7]},
30	}
31}
32
33// packFields writes each field as its byte length, a colon and the field, so
34// a field may hold colons and digits.
35func packFields(fields ...string) string {
36	var b strings.Builder
37	for _, f := range fields {
38		b.WriteString(strconv.Itoa(len(f)) + ":" + f)
39	}
40	return b.String()
41}
42
43// unpackFields reads exactly n fields made by packFields and panics on any
44// other string.
45func unpackFields(s string, n int) []string {
46	fields := make([]string, n)
47	for i := range fields {
48		field, rest, ok := cutField(s)
49		if !ok {
50			panic("corrupt record")
51		}
52		fields[i], s = field, rest
53	}
54	if s != "" {
55		panic("corrupt record")
56	}
57	return fields
58}
59
60func cutField(s string) (field, rest string, ok bool) {
61	length, body, found := strings.Cut(s, ":")
62	if !found {
63		return "", "", false
64	}
65	n, err := strconv.Atoi(length)
66	if err != nil || n < 0 || n > len(body) {
67		return "", "", false
68	}
69	return body[:n], body[n:], true
70}