-
-
Notifications
You must be signed in to change notification settings - Fork 135
/
printer.go
130 lines (112 loc) · 2.58 KB
/
printer.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
package main
import (
"encoding/json"
"fmt"
"io"
"github.com/go-faster/errors"
"github.com/k0kubun/pp/v3"
"github.com/gotd/td/bin"
"github.com/gotd/td/internal/mt"
"github.com/gotd/td/internal/proto/codec"
"github.com/gotd/td/internal/tmap"
"github.com/gotd/td/tdp"
"github.com/gotd/td/tg"
"github.com/gotd/td/transport"
)
// Object is abstraction for TL schema object.
type Object interface {
bin.Object
tdp.Object
}
// Formatter formats given bin.Object and prints it to io.Writer.
type Formatter interface {
Format(w io.Writer, i Object) error
}
// FormatterFunc is functional adapter for Formatter.
type FormatterFunc func(w io.Writer, i Object) error
// Format implements Formatter.
func (f FormatterFunc) Format(w io.Writer, i Object) error {
return f(w, i)
}
func formats(name string) Formatter {
switch name {
case "json":
return FormatterFunc(func(w io.Writer, i Object) error {
e := json.NewEncoder(w)
e.SetIndent("", "\t")
return e.Encode(i)
})
case "pp":
return FormatterFunc(func(w io.Writer, i Object) error {
_, err := pp.Fprintln(w, i)
return err
})
case "tdp":
return FormatterFunc(func(w io.Writer, i Object) error {
_, err := io.WriteString(w, tdp.Format(i))
return err
})
default: // "go" format
return FormatterFunc(func(w io.Writer, i Object) error {
_, err := fmt.Fprintln(w, i)
return err
})
}
}
// Printer decodes messages from given reader and prints is using Formatter.
type Printer struct {
src io.Reader
codec transport.Codec
format Formatter
}
// NewPrinter creates new Printer.
// If format is nil, "go" format will be used.
// If c is nil, codec.Intermediate will be use.
func NewPrinter(src io.Reader, format Formatter, c transport.Codec) Printer {
if c == nil {
c = codec.Intermediate{}
}
if format == nil {
format = formats("go")
}
return Printer{
src: src,
codec: c,
format: format,
}
}
// Print prints decoded messages to output.
func (p Printer) Print(output io.Writer) error {
b := &bin.Buffer{}
m := tmap.NewConstructor(
tg.TypesConstructorMap(),
mt.TypesConstructorMap(),
)
for {
b.Reset()
if err := p.codec.Read(p.src, b); err != nil {
if errors.Is(err, io.EOF) {
return nil
}
return err
}
id, err := b.PeekID()
if err != nil {
return err
}
obj := m.New(id)
if obj == nil {
return errors.Errorf("find type %#x", id)
}
v, ok := obj.(Object)
if !ok {
return errors.Errorf("unexpected type %T", obj)
}
if err := v.Decode(b); err != nil {
return err
}
if err := p.format.Format(output, v); err != nil {
return err
}
}
}