-
Notifications
You must be signed in to change notification settings - Fork 1
/
processor.go
126 lines (99 loc) · 3.04 KB
/
processor.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
package censor
import (
"fmt"
"reflect"
"github.com/vpakhuchyi/censor/internal/builderpool"
"github.com/vpakhuchyi/censor/internal/encoder"
)
// Processor is responsible for data encoding according to the specified configuration.
type Processor struct {
encoder encoder.Encoder
cfg Config
}
// Censor pkg contains a global instance of Processor.
// This globalInstance is used by the package-level functions.
var globalInstance = New()
// New returns a new instance of Processor with default configuration.
func New() *Processor {
return newProcessor(DefaultConfig())
}
// NewWithOpts returns a new instance of Processor, options can be passed to it.
// If no options are passed, the default configuration will be used.
func NewWithOpts(opts ...Option) (*Processor, error) {
var optCfg OptsConfig
for _, opt := range opts {
opt(&optCfg)
}
cfg := optCfg.config
if cfg == nil && optCfg.configPath != "" {
c, err := ConfigFromFile(optCfg.configPath)
if err != nil {
return nil, fmt.Errorf("failed to read the configuration: %w", err)
}
cfg = &c
}
if cfg == nil {
c := DefaultConfig()
cfg = &c
} else if cfg.General.PrintConfigOnInit {
// We want to print the configuration only if it differs from the default one
// and the corresponding flag is set to true.
fmt.Print(cfg.ToString())
}
return newProcessor(*cfg), nil
}
func newProcessor(cfg Config) *Processor {
p := &Processor{
cfg: cfg,
}
if cfg.General.OutputFormat == "json" {
p.encoder = encoder.NewJSONEncoder(cfg.Encoder)
} else {
p.encoder = encoder.NewTextEncoder(cfg.Encoder)
}
return p
}
/*
Pkg-level functions that work with the global instance of Processor.
*/
// SetGlobalInstance sets a given Processor as a global instance.
func SetGlobalInstance(p *Processor) {
globalInstance = p
}
// GetGlobalInstance returns a global instance of Processor.
func GetGlobalInstance() *Processor {
return globalInstance
}
/*
Scoped methods that work with a specific instance of Processor.
*/
// Format takes any value and returns a string representation of it masking struct fields by default.
// To override this behaviour, use the `censor:"display"` tag.
// Formatting is done recursively for all nested structs/slices/arrays/pointers/maps/interfaces.
// If a value implements [encoding.TextMarshaler], the result of MarshalText is written.
func (p *Processor) Format(val any) string {
if val == nil || reflect.TypeOf(val) == nil {
return "nil"
}
return p.encode(val)
}
// Clone returns a new instance of Processor with the same configuration as the original one.
func (p *Processor) Clone() (*Processor, error) {
return NewWithOpts(WithConfig(&p.cfg))
}
const censorIsNotInitializedMsg = "censor is not initialized"
// PrintConfig prints the configuration of the Processor.
func (p *Processor) PrintConfig() {
if p == nil {
fmt.Print(censorIsNotInitializedMsg)
} else {
fmt.Print(p.cfg.ToString())
}
}
func (p *Processor) encode(v any) string {
b := builderpool.Get()
p.encoder.Encode(b, reflect.ValueOf(v))
res := b.String()
builderpool.Put(b)
return res
}