-
Notifications
You must be signed in to change notification settings - Fork 1
/
path.go
61 lines (54 loc) · 1.38 KB
/
path.go
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
package josh
import "strconv"
// Type var constraint for all possible integer types.
type integer interface {
int | int8 | int16 | int32 | int64 |
uint | uint8 | uint16 | uint32 | uint64 | uintptr
}
// Get and parse an integer value for the named path wildcard in the URL.
//
// Do not use it with [Must]! Wrapping a nil *Error into [error]
// will make it non-nil.
func GetID[T integer](r Req, name string) (T, *Error) {
raw := r.PathValue(name)
var def T
if raw == "" {
return def, &Error{Detail: "path parameter " + name + " is required"}
}
bitSize := getBitSize[T]()
if isUnsigned[T]() {
parsed, err := strconv.ParseUint(raw, 10, bitSize)
if err != nil {
return def, &Error{Detail: "invalid path parameter " + name}
}
return T(parsed), nil
}
parsed, err := strconv.ParseInt(raw, 10, bitSize)
if err != nil {
return def, &Error{Detail: "invalid path parameter " + name}
}
return T(parsed), nil
}
// Get the size in bits of the value of the given type.
func getBitSize[T integer]() int {
var def T
switch any(def).(type) {
case int, uint, uintptr, int64, uint64:
return 64
case int8, uint8:
return 8
case int16, uint16:
return 16
default:
return 32
}
}
// Check if the given type is an unsigned integer.
func isUnsigned[T integer]() bool {
var def T
switch any(def).(type) {
case uint, uint8, uint16, uint32, uint64, uintptr:
return true
}
return false
}