Skip to content

Commit 6f6de8e

Browse files
committed
Add a package for transaction serialization
encoding/transaction can be used to serialize Steem transactions.
1 parent 16b9ff0 commit 6f6de8e

File tree

3 files changed

+143
-0
lines changed

3 files changed

+143
-0
lines changed

encoding/transaction/encoder.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package transaction
2+
3+
import (
4+
// Stdlib
5+
"encoding/binary"
6+
"io"
7+
"strings"
8+
9+
// Vendor
10+
"github.com/pkg/errors"
11+
)
12+
13+
type Encoder struct {
14+
w io.Writer
15+
}
16+
17+
func NewEncoder(w io.Writer) *Encoder {
18+
return &Encoder{w}
19+
}
20+
21+
func (encoder *Encoder) EncodeVarint(i int64) error {
22+
if i >= 0 {
23+
return encoder.EncodeUVarint(uint64(i))
24+
}
25+
26+
b := make([]byte, binary.MaxVarintLen64)
27+
n := binary.PutVarint(b, i)
28+
return encoder.writeBytes(b[:n])
29+
}
30+
31+
func (encoder *Encoder) EncodeUVarint(i uint64) error {
32+
b := make([]byte, binary.MaxVarintLen64)
33+
n := binary.PutUvarint(b, i)
34+
return encoder.writeBytes(b[:n])
35+
}
36+
37+
func (encoder *Encoder) EncodeNumber(v interface{}) error {
38+
if err := binary.Write(encoder.w, binary.LittleEndian, v); err != nil {
39+
return errors.Wrapf(err, "encoder: failed to write number: %v", v)
40+
}
41+
return nil
42+
}
43+
44+
func (encoder *Encoder) Encode(v interface{}) error {
45+
if marshaller, ok := v.(TransactionMarshaller); ok {
46+
return marshaller.MarshalTransaction(encoder)
47+
}
48+
49+
switch v := v.(type) {
50+
case int:
51+
return encoder.EncodeNumber(v)
52+
case int8:
53+
return encoder.EncodeNumber(v)
54+
case int16:
55+
return encoder.EncodeNumber(v)
56+
case int32:
57+
return encoder.EncodeNumber(v)
58+
case int64:
59+
return encoder.EncodeNumber(v)
60+
61+
case uint:
62+
return encoder.EncodeNumber(v)
63+
case uint8:
64+
return encoder.EncodeNumber(v)
65+
case uint16:
66+
return encoder.EncodeNumber(v)
67+
case uint32:
68+
return encoder.EncodeNumber(v)
69+
case uint64:
70+
return encoder.EncodeNumber(v)
71+
72+
case string:
73+
return encoder.encodeString(v)
74+
75+
default:
76+
return errors.Errorf("encoder: unsupported type encountered")
77+
}
78+
}
79+
80+
func (encoder *Encoder) encodeString(v string) error {
81+
if err := encoder.EncodeUVarint(uint64(len(v))); err != nil {
82+
return errors.Wrapf(err, "encoder: failed to write string: %v", v)
83+
}
84+
85+
return encoder.writeString(v)
86+
}
87+
88+
func (encoder *Encoder) writeBytes(bs []byte) error {
89+
if _, err := encoder.w.Write(bs); err != nil {
90+
return errors.Wrapf(err, "encoder: failed to write bytes: %v", bs)
91+
}
92+
return nil
93+
}
94+
95+
func (encoder *Encoder) writeString(s string) error {
96+
if _, err := io.Copy(encoder.w, strings.NewReader(s)); err != nil {
97+
return errors.Wrapf(err, "encoder: failed to write string: %v", s)
98+
}
99+
return nil
100+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package transaction
2+
3+
type RollingEncoder struct {
4+
next *Encoder
5+
err error
6+
}
7+
8+
func NewRollingEncoder(next *Encoder) *RollingEncoder {
9+
return &RollingEncoder{next, nil}
10+
}
11+
12+
func (encoder *RollingEncoder) EncodeVarint(i int64) {
13+
if encoder.err == nil {
14+
encoder.err = encoder.next.EncodeVarint(i)
15+
}
16+
}
17+
18+
func (encoder *RollingEncoder) EncodeUVarint(i uint64) {
19+
if encoder.err == nil {
20+
encoder.err = encoder.next.EncodeUVarint(i)
21+
}
22+
}
23+
24+
func (encoder *RollingEncoder) EncodeNumber(v interface{}) {
25+
if encoder.err == nil {
26+
encoder.err = encoder.next.EncodeNumber(v)
27+
}
28+
}
29+
30+
func (encoder *RollingEncoder) Encode(v interface{}) {
31+
if encoder.err == nil {
32+
encoder.err = encoder.next.Encode(v)
33+
}
34+
}
35+
36+
func (encoder *RollingEncoder) Err() error {
37+
return encoder.err
38+
}

encoding/transaction/encoding.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package transaction
2+
3+
type TransactionMarshaller interface {
4+
MarshalTransaction(*Encoder) error
5+
}

0 commit comments

Comments
 (0)