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

impl.gno

1.83 Kb · 70 lines
 1// Package impl is version 1 of the handler realm of the "API as data" upgrade
 2// pattern (pattern G; see ../../README.md).
 3//
 4// Three verbs: it ADDS one and keeps both of v0's untouched, which is what
 5// lets the facade accept it. Growing the API costs no new realm and no new
 6// signature at the permanent path.
 7package impl
 8
 9import (
10	"strings"
11
12	facade "gno.land/r/moul/x/upgrade/schema/facade/v0"
13)
14
15// schema is this version's whole API. One verb per line, name then parameters.
16const schema = `upper s
17repeat s n
18surround s left right`
19
20type handler struct{}
21
22func (handler) Schema() string { return schema }
23
24func (handler) Invoke(verb string, args []string) string {
25	switch verb {
26	case "upper":
27		return strings.ToUpper(args[0])
28	case "repeat":
29		return strings.Repeat(args[0], atoi(args[1]))
30	case "surround":
31		return args[1] + args[0] + args[2]
32	}
33	// Unreachable: the facade checked the verb against this schema first.
34	panic("unknown verb " + verb)
35}
36
37// atoi is hand-rolled to keep the failure message about the ARGUMENT rather
38// than about strconv, which is the whole difference a typed boundary would have
39// made here.
40func atoi(s string) int {
41	if s == "" {
42		panic("expected a number, got an empty argument")
43	}
44	n := 0
45	for _, c := range s {
46		if c < '0' || c > '9' {
47			panic("expected a number, got " + s)
48		}
49		n = n*10 + int(c-'0')
50		if n > 64 {
51			panic("refusing to repeat more than 64 times")
52		}
53	}
54	return n
55}
56
57// Instance exposes the singleton.
58func Instance() facade.Handler { return handler{} }
59
60// Path is this realm's own package path, the string the facade owner accepts.
61const Path = "gno.land/r/moul/x/upgrade/schema/impl/v1"
62
63func init(cur realm) {
64	facade.Propose(cross(cur), Instance())
65}
66
67// Propose re-nominates this handler, so a rollback needs no redeploy.
68func Propose(cur realm) {
69	facade.Propose(cross(cur), Instance())
70}