validation.gno
2.77 Kb · 114 lines
1package chunk
2
3import "strconv"
4
5// Validation helpers in this file are for value-level checks at public API boundaries.
6//
7// Add helpers here when they validate a parameter or payload value without
8// depending on mutable contract state or call flow. Good examples are world
9// field format, numeric range, CSV payload shape, and page/count limits.
10//
11// Do not add helpers here when the assertion depends on store contents,
12// ownership, permissions, freeze/migration state, uniqueness, or the order of a
13// specific operation. Keep those assertions close to the domain flow that owns
14// the state transition.
15//
16// As a rule of thumb: validation.gno owns "is this value shaped correctly?";
17// domain files and stores own "is this action allowed right now?" and
18// store-owned index invariants.
19
20// World field assertions.
21// Used by CreateWorld and UpdateWorld before constructing or mutating records.
22func assertWorldID(id uint32) {
23 if id == 0 {
24 panic("world id must be positive")
25 }
26}
27
28func assertBiomeName(biomeName string) {
29 if len(biomeName) == 0 {
30 panic("biome name cannot be empty")
31 }
32}
33
34func assertWorldName(name string) {
35 if len(name) == 0 {
36 panic("name cannot be empty")
37 }
38 if len(name) > 100 {
39 panic("name too long (max 100)")
40 }
41}
42
43func assertWorldSlug(slug string) {
44 if len(slug) == 0 {
45 panic("slug cannot be empty")
46 }
47
48 if len(slug) > 50 {
49 panic("slug too long (max 50)")
50 }
51
52 // Allowed characters: a-z, 0-9, hyphen, underscore
53 for _, ch := range slug {
54 if !((ch >= 'a' && ch <= 'z') ||
55 (ch >= '0' && ch <= '9') ||
56 ch == '-' || ch == '_') {
57 panic("slug contains invalid characters (allowed: a-z, 0-9, -, _)")
58 }
59 }
60
61 // Cannot start or end with hyphen
62 if slug[0] == '-' || slug[len(slug)-1] == '-' {
63 panic("slug cannot start or end with hyphen")
64 }
65}
66
67func mustParseWorldSeed(value string) int {
68 seed, err := strconv.Atoi(value)
69 if err != nil {
70 panic("invalid seed: " + value)
71 }
72 assertWorldSeed(seed)
73 return seed
74}
75
76func assertWorldSeed(seed int) {
77 if seed <= 0 {
78 panic("seed must be positive")
79 }
80}
81
82// Query limit assertions.
83// Used by public list and batch query entry points.
84func assertListLimit(field string, count int) {
85 if count > listLimit {
86 panic(field + " exceeds listLimit (max: " + strconv.Itoa(listLimit) + ")")
87 }
88}
89
90func assertListQueryCount(field string, count int) {
91 if count < 1 {
92 panic(field + " must be at least 1")
93 }
94 assertListLimit(field, count)
95}
96
97func assertListPageCount(page int, count int) {
98 if page < 1 {
99 panic("page must be at least 1")
100 }
101 assertListQueryCount("count", count)
102}
103
104func assertBatchLimit(field string, count int) {
105 if count > batchLimit {
106 panic(field + " exceeds batchLimit (max: " + strconv.Itoa(batchLimit) + ")")
107 }
108}
109
110func assertPositiveLimit(limit int) {
111 if limit < 1 {
112 panic("limit must be at least 1")
113 }
114}