1
2
3
4
5
6
7 package jsonopts
8
9 import (
10 "encoding/json/internal"
11 "encoding/json/internal/jsonflags"
12 )
13
14
15 type Options interface {
16
17 JSONOptions(internal.NotForPublicUse)
18 }
19
20
21
22 type Struct struct {
23 Flags jsonflags.Flags
24
25 CoderValues
26 ArshalValues
27 }
28
29 type CoderValues struct {
30 Indent string
31 IndentPrefix string
32 ByteLimit int64
33 DepthLimit int
34 }
35
36 type ArshalValues struct {
37
38
39
40
41 Marshalers any
42 Unmarshalers any
43
44 Format string
45 FormatDepth int
46 }
47
48
49 var DefaultOptionsV2 = Struct{
50 Flags: jsonflags.Flags{
51 Presence: uint64(jsonflags.AllFlags & ^jsonflags.WhitespaceFlags),
52 Values: uint64(0),
53 },
54 }
55
56
57 var DefaultOptionsV1 = Struct{
58 Flags: jsonflags.Flags{
59 Presence: uint64(jsonflags.AllFlags & ^jsonflags.WhitespaceFlags),
60 Values: uint64(jsonflags.DefaultV1Flags),
61 },
62 }
63
64 func (*Struct) JSONOptions(internal.NotForPublicUse) {}
65
66
67
68 var GetUnknownOption = func(*Struct, Options) (any, bool) { panic("unknown option") }
69
70 func GetOption[T any](opts Options, setter func(T) Options) (T, bool) {
71
72 structOpts, ok := opts.(*Struct)
73 if !ok {
74 var structOpts2 Struct
75 structOpts2.Join(opts)
76 structOpts = &structOpts2
77 }
78
79
80 var zero T
81 switch opt := setter(zero).(type) {
82 case jsonflags.Bools:
83 v := structOpts.Flags.Get(opt)
84 ok := structOpts.Flags.Has(opt)
85 return any(v).(T), ok
86 case Indent:
87 if !structOpts.Flags.Has(jsonflags.Indent) {
88 return zero, false
89 }
90 return any(structOpts.Indent).(T), true
91 case IndentPrefix:
92 if !structOpts.Flags.Has(jsonflags.IndentPrefix) {
93 return zero, false
94 }
95 return any(structOpts.IndentPrefix).(T), true
96 case ByteLimit:
97 if !structOpts.Flags.Has(jsonflags.ByteLimit) {
98 return zero, false
99 }
100 return any(structOpts.ByteLimit).(T), true
101 case DepthLimit:
102 if !structOpts.Flags.Has(jsonflags.DepthLimit) {
103 return zero, false
104 }
105 return any(structOpts.DepthLimit).(T), true
106 default:
107 v, ok := GetUnknownOption(structOpts, opt)
108 return v.(T), ok
109 }
110 }
111
112
113
114 var JoinUnknownOption = func(*Struct, Options) { panic("unknown option") }
115
116 func (dst *Struct) Join(srcs ...Options) {
117 dst.join(false, srcs...)
118 }
119
120 func (dst *Struct) JoinWithoutCoderOptions(srcs ...Options) {
121 dst.join(true, srcs...)
122 }
123
124 func (dst *Struct) join(excludeCoderOptions bool, srcs ...Options) {
125 for _, src := range srcs {
126 switch src := src.(type) {
127 case nil:
128 continue
129 case jsonflags.Bools:
130 if excludeCoderOptions {
131 src &= ^jsonflags.AllCoderFlags
132 }
133 dst.Flags.Set(src)
134 case Indent:
135 if excludeCoderOptions {
136 continue
137 }
138 dst.Flags.Set(jsonflags.Multiline | jsonflags.Indent | 1)
139 dst.Indent = string(src)
140 case IndentPrefix:
141 if excludeCoderOptions {
142 continue
143 }
144 dst.Flags.Set(jsonflags.Multiline | jsonflags.IndentPrefix | 1)
145 dst.IndentPrefix = string(src)
146 case ByteLimit:
147 if excludeCoderOptions {
148 continue
149 }
150 dst.Flags.Set(jsonflags.ByteLimit | 1)
151 dst.ByteLimit = int64(src)
152 case DepthLimit:
153 if excludeCoderOptions {
154 continue
155 }
156 dst.Flags.Set(jsonflags.DepthLimit | 1)
157 dst.DepthLimit = int(src)
158 case *Struct:
159 srcFlags := src.Flags
160 if excludeCoderOptions {
161 srcFlags.Clear(jsonflags.AllCoderFlags)
162 }
163 dst.Flags.Join(srcFlags)
164 if srcFlags.Has(jsonflags.NonBooleanFlags) {
165 if srcFlags.Has(jsonflags.Indent) {
166 dst.Indent = src.Indent
167 }
168 if srcFlags.Has(jsonflags.IndentPrefix) {
169 dst.IndentPrefix = src.IndentPrefix
170 }
171 if srcFlags.Has(jsonflags.ByteLimit) {
172 dst.ByteLimit = src.ByteLimit
173 }
174 if srcFlags.Has(jsonflags.DepthLimit) {
175 dst.DepthLimit = src.DepthLimit
176 }
177 if srcFlags.Has(jsonflags.Marshalers) {
178 dst.Marshalers = src.Marshalers
179 }
180 if srcFlags.Has(jsonflags.Unmarshalers) {
181 dst.Unmarshalers = src.Unmarshalers
182 }
183 }
184 default:
185 JoinUnknownOption(dst, src)
186 }
187 }
188 }
189
190 type (
191 Indent string
192 IndentPrefix string
193 ByteLimit int64
194 DepthLimit int
195
196
197 )
198
199 func (Indent) JSONOptions(internal.NotForPublicUse) {}
200 func (IndentPrefix) JSONOptions(internal.NotForPublicUse) {}
201 func (ByteLimit) JSONOptions(internal.NotForPublicUse) {}
202 func (DepthLimit) JSONOptions(internal.NotForPublicUse) {}
203
View as plain text