Repository navigation
Expand file tree
/
Copy pathresult.go
More file actions
101 lines (93 loc) · 3.09 KB
/
Copy pathresult.go
File metadata and controls
101 lines (93 loc) · 3.09 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
90
91
92
93
94
95
96
97
98
99
100
101
package fmtparse
import (
"fmt"
"time"
)
// Result holds the fields extracted by [Parse], [Search], or [FindAll].
//
// Fixed holds anonymous ({}) and positional field values in the order they
// appear in the format string. Named holds {name} field values, keyed by
// their top-level name; a dotted or indexed field ({a.b} or {a[b]}) produces
// a nested map[string]any under Named["a"].
type Result struct {
// Fixed holds values for every anonymous ({}) field, in left-to-right order.
Fixed []any
// Named holds values for every named ({name}) field. Dotted and indexed
// names ({a.b}, {a[b]}) are expanded into nested map[string]any values.
Named map[string]any
// Spans records the [start, end) byte offsets in the matched string for
// each field. Named fields are keyed by their full flat name (e.g. "a.b"
// or "a[b]", not expanded). Fixed fields are keyed by their decimal
// index ("0", "1", ...).
Spans map[string][2]int
}
func newResult() *Result {
return &Result{
Fixed: nil,
Named: map[string]any{},
Spans: map[string][2]int{},
}
}
// Get returns the named field's raw value and whether it was present.
func (r *Result) Get(name string) (any, bool) {
v, ok := r.Named[name]
return v, ok
}
// Int returns the named field's value as an int64. It returns an error if
// the field is absent or its underlying value is not an integer.
func (r *Result) Int(name string) (int64, error) {
v, ok := r.Named[name]
if !ok {
return 0, fmt.Errorf("fmtparse: no such field %q", name)
}
switch n := v.(type) {
case int64:
return n, nil
case int:
return int64(n), nil
}
return 0, fmt.Errorf("fmtparse: field %q is %T, not an integer", name, v)
}
// Float returns the named field's value as a float64. It returns an error
// if the field is absent or its underlying value is not a float.
func (r *Result) Float(name string) (float64, error) {
v, ok := r.Named[name]
if !ok {
return 0, fmt.Errorf("fmtparse: no such field %q", name)
}
switch n := v.(type) {
case float64:
return n, nil
case int64:
return float64(n), nil
case int:
return float64(n), nil
}
return 0, fmt.Errorf("fmtparse: field %q is %T, not a float", name, v)
}
// String returns the named field's value as a string. It returns an error
// if the field is absent. Non-string values are formatted with fmt.Sprint.
func (r *Result) String(name string) (string, error) {
v, ok := r.Named[name]
if !ok {
return "", fmt.Errorf("fmtparse: no such field %q", name)
}
if s, ok := v.(string); ok {
return s, nil
}
return fmt.Sprint(v), nil
}
// Time returns the named field's value as a time.Time. It returns an error
// if the field is absent or its underlying value is not a time.Time. Fields
// parsed with the "tt" (time-only) type carry the zero date (year 1, month
// January, day 1); every other date/time type carries a full date.
func (r *Result) Time(name string) (time.Time, error) {
v, ok := r.Named[name]
if !ok {
return time.Time{}, fmt.Errorf("fmtparse: no such field %q", name)
}
if t, ok := v.(time.Time); ok {
return t, nil
}
return time.Time{}, fmt.Errorf("fmtparse: field %q is %T, not a time.Time", name, v)
}