/
transaction_time_bounds.go
96 lines (81 loc) · 1.99 KB
/
transaction_time_bounds.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
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
package history
import (
"database/sql/driver"
"fmt"
"math"
"strings"
"github.com/TosinShada/stellar-core/support/errors"
"github.com/TosinShada/stellar-core/xdr"
"github.com/guregu/null"
)
// TimeBounds represents the time bounds of a Stellar transaction
type TimeBounds struct {
Null bool
Upper null.Int
Lower null.Int
}
// Scan implements the database/sql Scanner interface.
func (t *TimeBounds) Scan(src interface{}) error {
if src == nil {
*t = TimeBounds{Null: true}
return nil
}
var rangeText string
switch src := src.(type) {
case string:
rangeText = src
case []byte:
rangeText = string(src)
default:
return errors.Errorf("cannot scan %T", src)
}
rangeText = strings.TrimSpace(rangeText)
if len(rangeText) < 3 {
return errors.Errorf("range is invalid %s", rangeText)
}
inner := rangeText[1 : len(rangeText)-1]
parts := strings.Split(inner, ",")
if len(parts) != 2 {
return errors.Errorf("%s does not have 2 comma separated values", rangeText)
}
lower, upper := parts[0], parts[1]
if len(lower) > 0 {
if err := t.Lower.Scan(lower); err != nil {
return errors.Wrap(err, "cannot parse lower bound")
}
}
if len(upper) > 0 {
if err := t.Upper.Scan(upper); err != nil {
return errors.Wrap(err, "cannot parse upper bound")
}
}
return nil
}
// Value implements the database/sql/driver Valuer interface.
func (t TimeBounds) Value() (driver.Value, error) {
if t.Null {
return nil, nil
}
if !t.Upper.Valid {
return fmt.Sprintf("[%d,)", t.Lower.Int64), nil
}
return fmt.Sprintf("[%d, %d)", t.Lower.Int64, t.Upper.Int64), nil
}
func formatTimeBounds(timeBounds *xdr.TimeBounds) TimeBounds {
if timeBounds == nil {
return TimeBounds{Null: true}
}
if timeBounds.MaxTime == 0 {
return TimeBounds{
Lower: null.IntFrom(int64(timeBounds.MinTime)),
}
}
maxTime := timeBounds.MaxTime
if maxTime > math.MaxInt64 {
maxTime = math.MaxInt64
}
return TimeBounds{
Lower: null.IntFrom(int64(timeBounds.MinTime)),
Upper: null.IntFrom(int64(maxTime)),
}
}