Repository navigation
Expand file tree
/
Copy pathnames.go
More file actions
89 lines (81 loc) · 2.22 KB
/
Copy pathnames.go
File metadata and controls
89 lines (81 loc) · 2.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// Copyright 2026 Hamed Yousefi
// SPDX-License-Identifier: MPL-2.0
package lockstep
const (
maxNodeLen = 64 // ACT-020
maxNameLen = 768 // ACT-310
)
// validNode reports whether s is a valid node name: 1 to 64 bytes from [A-Za-z0-9._-], starting
// with a letter or digit (ACT-020).
func validNode(s string) bool {
if len(s) == 0 || len(s) > maxNodeLen || !isAlnum(s[0]) {
return false
}
for i := 1; i < len(s); i++ {
if c := s[i]; !isAlnum(c) && c != '.' && c != '_' && c != '-' {
return false
}
}
return true
}
// validName reports whether s is a valid actor name: 1 to 768 bytes from [A-Za-z0-9._%-], neither
// "." nor ".." (ACT-310). The "$" of generated names is outside the set.
func validName(s string) bool {
if len(s) == 0 || len(s) > maxNameLen || s == "." || s == ".." {
return false
}
for i := 0; i < len(s); i++ {
if c := s[i]; !isAlnum(c) && c != '.' && c != '_' && c != '%' && c != '-' {
return false
}
}
return true
}
// validPath reports whether s is a well-formed actor path (ACT-510): "/" followed by one or more
// segments separated by single "/", with no trailing "/", where each segment is a valid name or
// "$" followed by a decimal number without leading zeros.
func validPath(s string) bool {
if len(s) < 2 || s[0] != '/' {
return false
}
rest := s[1:]
for {
seg, more, ok := cutSegment(rest)
if !validName(seg) && !validGenerated(seg) {
return false
}
if !ok {
return true
}
rest = more
}
}
// cutSegment splits s at its first "/". ok reports whether there was one; after is what follows.
func cutSegment(s string) (seg, after string, ok bool) {
for i := 0; i < len(s); i++ {
if s[i] == '/' {
return s[:i], s[i+1:], true
}
}
return s, "", false
}
// validGenerated reports whether s is "$" followed by a decimal number without leading zeros, the
// form of a generated name (ACT-320).
func validGenerated(s string) bool {
if len(s) < 2 || s[0] != '$' {
return false
}
digits := s[1:]
if digits[0] == '0' && len(digits) > 1 {
return false
}
for i := 0; i < len(digits); i++ {
if digits[i] < '0' || digits[i] > '9' {
return false
}
}
return true
}
func isAlnum(c byte) bool {
return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9'
}