This repository has been archived by the owner on Aug 2, 2023. It is now read-only.
/
state.go
107 lines (96 loc) · 2 KB
/
state.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
package packer
import (
"bytes"
"fmt"
)
type state struct {
out bytes.Buffer
opt []option
arg int
}
func newState(format string) (*state, error) {
var (
s = scan(format)
p = new(state)
)
L:
for {
switch opt := s.nextOpt(); opt.typ {
case optErr:
s.drain()
return nil, fmt.Errorf(opt.value)
case optEnd:
break L
default:
p.opt = append(p.opt, opt)
}
}
return p, nil
}
func (p *state) Option() Option {
if p.arg < 0 || p.arg >= len(p.opt) {
return nil
}
return p.opt[p.arg]
}
func (p *state) Unpack(values ...interface{}) (n int, err error) {
return 0, fmt.Errorf("pack.Unpack: TODO")
}
func (p *state) Pack(values ...interface{}) ([]byte, error) {
p.out.Reset()
p.arg = 0
for _, opt := range p.opt {
switch {
case opt.typ == optPad:
p.out.WriteByte(0)
continue
case p.arg >= len(values):
return nil, fmt.Errorf("bad argument #%d to 'pack'", p.arg)
default:
if err := p.packValue(opt, values[p.arg]); err != nil {
return nil, err
}
p.arg++
}
}
return p.out.Bytes(), nil
}
func (p *state) Size() (size int, err error) {
for i, opt := range p.opt {
if opt.typ == optVarLen || opt.typ == optPrefix {
err = fmt.Errorf("bad argument #%d to 'packsize' (variable-length format)", i)
break
}
size += int(opt.width)
}
return size, err
}
func (p *state) packValue(o option, v interface{}) error {
switch o.typ {
case optVarLen, optPrefix, optFixed:
return p.packString(o, v)
case optUint, optInt:
return p.packInt(o, v)
case optFloat:
return p.packFloat(o, v)
}
panic("unreachable")
}
func (p *state) packString(o option, v interface{}) error {
fmt.Println("pack: string")
// return p.pack(o, v)
return nil
}
func (p *state) packFloat(o option, v interface{}) error {
fmt.Println("pack: float")
// return p.pack(o, v)
return nil
}
func (p *state) packInt(o option, v interface{}) error {
// fmt.Printf("packInt (%t) => %T\n", o.typ == optUint, v)
if v, ok := v.(Packer); ok {
return v.Pack(p)
}
// return p.pack(o, v)
return nil
}