-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcodec.go
More file actions
97 lines (78 loc) · 2.6 KB
/
Copy pathcodec.go
File metadata and controls
97 lines (78 loc) · 2.6 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
package botapi
import (
"github.com/go-faster/errors"
"github.com/go-faster/jx"
)
// This file wires the receivable entity types to github.com/go-faster/jx so
// they round-trip through JSON: every type in Message's transitive closure
// implements jx-based Encode/Decode, and exposes them to encoding/json through
// MarshalJSON/UnmarshalJSON. The json struct tags on the types remain as
// documentation of the wire field names.
// jsonEncoder is implemented by entity types that serialize themselves through
// the jx streaming encoder.
type jsonEncoder interface {
Encode(e *jx.Encoder)
}
// jsonDecoder is implemented by entity types that parse themselves from a jx
// streaming decoder.
type jsonDecoder interface {
Decode(d *jx.Decoder) error
}
// marshalJX renders v through its jx Encode method into a freshly allocated
// JSON document. It is the shared implementation behind every entity's
// MarshalJSON.
func marshalJX(v jsonEncoder) ([]byte, error) {
e := jx.GetEncoder()
defer jx.PutEncoder(e)
v.Encode(e)
// e.Bytes() aliases the pooled buffer; copy before the buffer is returned
// to the pool by the deferred PutEncoder.
return append([]byte(nil), e.Bytes()...), nil
}
// unmarshalJX parses data into v through its jx Decode method. It is the shared
// implementation behind every entity's UnmarshalJSON.
func unmarshalJX(data []byte, v jsonDecoder) error {
d := jx.GetDecoder()
defer jx.PutDecoder(d)
d.ResetBytes(data)
return v.Decode(d)
}
// decodeMessageOrigin reads a MessageOrigin object, dispatching on its "type"
// discriminator to the matching concrete variant. The decoder must be
// byte-backed (it is, via unmarshalJX's ResetBytes) so Capture can peek at the
// discriminator before the variant is decoded.
func decodeMessageOrigin(d *jx.Decoder) (MessageOrigin, error) {
var kind string
if err := d.Capture(func(d *jx.Decoder) error {
return d.ObjBytes(func(d *jx.Decoder, key []byte) error {
if string(key) == "type" {
v, err := d.StrBytes()
if err != nil {
return err
}
kind = string(v) // copy: StrBytes aliases the read buffer
return nil
}
return d.Skip()
})
}); err != nil {
return nil, err
}
var origin MessageOrigin
switch MessageOriginType(kind) {
case OriginUser:
origin = &MessageOriginUser{}
case OriginHiddenUser:
origin = &MessageOriginHiddenUser{}
case OriginChat:
origin = &MessageOriginChat{}
case OriginChannel:
origin = &MessageOriginChannel{}
default:
return nil, errors.Errorf("unknown message origin type %q", kind)
}
if err := origin.(jsonDecoder).Decode(d); err != nil {
return nil, err
}
return origin, nil
}