-
Notifications
You must be signed in to change notification settings - Fork 0
/
convert.go
136 lines (118 loc) · 2.27 KB
/
convert.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package jq
import (
"fmt"
"strconv"
"nikand.dev/go/cbor"
)
type (
Convert struct {
Type ConvertType
}
ConvertType Tag
)
const (
_ ConvertType = iota
ToBytes
ToString
ToInt
ToFloat
)
func NewConvert(to ConvertType) Convert {
return Convert{Type: to}
}
func (f Convert) ApplyTo(b *Buffer, off Off, next bool) (res Off, more bool, err error) {
if next {
return None, false, nil
}
br := b.Reader()
bw := b.Writer()
tag := br.Tag(off)
raw := br.TagRaw(off)
var typ cbor.Tag
switch f.Type {
case ToInt:
typ = cbor.Int
case ToBytes:
typ = cbor.Bytes
case ToString:
typ = cbor.String
}
switch f.Type {
case ToBytes, ToString:
switch {
case tag == typ:
res = off
case tag == cbor.String || tag == cbor.Bytes:
s := br.Bytes(off)
res = bw.TagBytes(typ, s)
case cbor.IsInt(raw) || cbor.IsFloat(raw):
var x any
res = bw.Off()
ww := bw.StringWriter(typ)
neg := csel(tag == cbor.Neg, "-", "")
switch tag {
case cbor.Int, cbor.Neg:
x = br.Unsigned(off)
default:
x = br.Float(off)
}
fmt.Fprintf(ww, "%s%v", neg, x)
default:
return None, false, NewTypeError(raw)
}
case ToInt:
switch {
case cbor.IsInt(raw):
res = off
case cbor.IsFloat(raw):
x := int64(br.Float(off))
res = bw.Int64(x)
case tag == cbor.Bytes, tag == cbor.String:
s := br.Bytes(off)
x, err := strconv.ParseInt(string(s), 10, 64)
if err != nil {
return None, false, err
}
res = bw.Int64(x)
default:
return None, false, NewTypeError(raw)
}
case ToFloat:
switch {
case cbor.IsFloat(raw):
res = off
case tag == cbor.Int:
x := br.Unsigned(off)
res = bw.Float(float64(x))
case tag == cbor.Neg:
x := br.Signed(off)
res = bw.Float(float64(x))
case tag == cbor.Bytes, tag == cbor.String:
s := br.Bytes(off)
x, err := strconv.ParseFloat(string(s), 64)
if err != nil {
return None, false, err
}
res = bw.Float(x)
default:
return None, false, NewTypeError(raw)
}
default:
return None, false, NewTypeError(typ)
}
return res, false, nil
}
func (f Convert) String() string {
switch f.Type {
case ToBytes:
return "toBytes"
case ToString:
return "toString"
case ToInt:
return "toInt"
case ToFloat:
return "toFloat"
default:
return fmt.Sprintf("%x", int(f.Type))
}
}