Kind Pure package
Name v0
Namespace moul / gnopm
Exported functions n/a — not supported for pure packages by the node (vm/qfuncs)
Module gno.land/p/moul/gnopm/v0
gno 0.9 pkgpath.gno gno
⧉
1 package gnopm 2 3 import "strings" 4 5 // Parsing a gno package path far enough to know who owns it. 6 // 7 // A path is "<domain>/<kind>/<namespace>/<name...>", optionally ending in a 8 not supported for pure packages by the node (vm/qfuncs)
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
// "/vN" version element: "gno.land/p/moul/md/v1", "gno.land/r/sys/users",
9 // "gno.land/r/g1abc.../scratch/v0". The namespace is the third element and it
10 // is the whole reason this file exists: it decides whether a claim comes from
11 // the party that controls the path or from a stranger, which is the strongest
12 // signal the registry can offer about a claim it can never itself verify.
13
14 // SplitPkgPath breaks a package path into its domain, kind ("p" or "r"),
15 // namespace and the remainder. ok is false for anything that is not shaped like
16 // a publishable gno path.
17 func SplitPkgPath(s string ) (domain, kind, ns, rest string , ok bool ) {
18 if !ValidPkgPath(s) {
19 return "" , "" , "" , "" , false
20 }
21 parts := strings.Split(s, "/" )
22 return parts[ 0 ], parts[ 1 ], parts[ 2 ], strings.Join(parts[ 3 :], "/" ), true
23 }
24
25 // Namespace returns the owning namespace of a package path, or "" if the path
26 // is not one.
27 func Namespace(s string ) string {
28 _, _, ns, _, ok := SplitPkgPath(s)
29 if !ok {
30 return ""
31 }
32 return ns
33 }
34
35 // Version returns the trailing "vN" element of a package path, or "" when the
36 // path carries none. Absent is legal and is not an error: gnoweb serves
37 // gno.land/u/<name> by calling the realm at exactly /r/<name>/home, so that one
38 // path can never carry a version.
39 func Version(s string ) string {
40 parts := strings.Split(s, "/" )
41 if len(parts) < 4 {
42 return ""
43 }
44 last := parts[len(parts)- 1 ]
45 if len(last) < 2 || last[ 0 ] != 'v' {
46 return ""
47 }
48 for i := 1 ; i < len(last); i++ {
49 if last[i] < '0' || last[i] > '9' {
50 return ""
51 }
52 }
53 return last
54 }
55
56 // ValidPkgPath reports whether s is shaped like a publishable gno package path.
57 //
58 // It does NOT say the path exists on any chain, and cannot: a realm has no way
59 // to ask whether some other path was ever deployed. That gap is the registry's
60 // central honesty problem and is documented on Registry.
61 func ValidPkgPath(s string ) bool {
62 if s == "" || len(s) > MaxPkgPathLen {
63 return false
64 }
65 if strings.HasPrefix(s, "/" ) || strings.HasSuffix(s, "/" ) || strings.Contains(s, "//" ) {
66 return false
67 }
68 parts := strings.Split(s, "/" )
69 if len(parts) < 4 {
70 return false
71 }
72 // The domain, which is a host and so must carry a dot.
73 if !strings.Contains(parts[ 0 ], "." ) {
74 return false
75 }
76 if parts[ 1 ] != "p" && parts[ 1 ] != "r" {
77 return false
78 }
79 for _, p := range parts {
80 if p == "" || p == "." || p == ".." {
81 return false
82 }
83 for i := 0 ; i < len(p); i++ {
84 if !pathByteOK(p[i]) {
85 return false
86 }
87 }
88 }
89 return true
90 }
91
92 // AddressNamespace reports whether ns is shaped like a gno bech32 address, the
93 // namespace every account owns without registering anything. A caller still
94 // has to check it is the claimant's own address; this only says which of the
95 // two ownership rules applies.
96 func AddressNamespace(ns string ) bool {
97 if len(ns) != 40 || !strings.HasPrefix(ns, "g1" ) {
98 return false
99 }
100 for i := 2 ; i < len(ns); i++ {
101 if !strings.ContainsRune(bech32Charset, rune (ns[i])) {
102 return false
103 }
104 }
105 return true
106 }
107
108 // bech32Charset is bech32's data alphabet: lowercase alphanumerics minus the
109 // four characters it drops to avoid transcription errors (1, b, i, o).
110 const bech32Charset = "023456789acdefghjklmnpqrstuvwxyz"
111