state.sep = ""
}
}
+ // Remember the position in the buffer, in case all attrs are empty.
+ pos := state.buf.Len()
state.openGroups()
- for _, a := range as {
- state.appendAttr(a)
+ if !state.appendAttrs(as) {
+ state.buf.SetLen(pos)
+ } else {
+ // Remember the new prefix for later keys.
+ h2.groupPrefix = state.prefix.String()
+ // Remember how many opened groups are in preformattedAttrs,
+ // so we don't open them again when we handle a Record.
+ h2.nOpenGroups = len(h2.groups)
}
- // Remember the new prefix for later keys.
- h2.groupPrefix = state.prefix.String()
- // Remember how many opened groups are in preformattedAttrs,
- // so we don't open them again when we handle a Record.
- h2.nOpenGroups = len(h2.groups)
return h2
}
nOpenGroups := s.h.nOpenGroups
if r.NumAttrs() > 0 {
s.prefix.WriteString(s.h.groupPrefix)
+ // The group may turn out to be empty even though it has attrs (for
+ // example, ReplaceAttr may delete all the attrs).
+ // So remember where we are in the buffer, to restore the position
+ // later if necessary.
+ pos := s.buf.Len()
s.openGroups()
nOpenGroups = len(s.h.groups)
+ empty := true
r.Attrs(func(a Attr) bool {
- s.appendAttr(a)
+ if s.appendAttr(a) {
+ empty = false
+ }
return true
})
+ if empty {
+ s.buf.SetLen(pos)
+ nOpenGroups = s.h.nOpenGroups
+ }
}
if s.h.json {
// Close all open groups.
}
}
+// appendAttrs appends the slice of Attrs.
+// It reports whether something was appended.
+func (s *handleState) appendAttrs(as []Attr) bool {
+ nonEmpty := false
+ for _, a := range as {
+ if s.appendAttr(a) {
+ nonEmpty = true
+ }
+ }
+ return nonEmpty
+}
+
// appendAttr appends the Attr's key and value using app.
// It handles replacement and checking for an empty key.
// after replacement).
-func (s *handleState) appendAttr(a Attr) {
+// It reports whether something was appended.
+func (s *handleState) appendAttr(a Attr) bool {
a.Value = a.Value.Resolve()
if rep := s.h.opts.ReplaceAttr; rep != nil && a.Value.Kind() != KindGroup {
var gs []string
}
// Elide empty Attrs.
if a.isEmpty() {
- return
+ return false
}
// Special case: Source.
if v := a.Value; v.Kind() == KindAny {
attrs := a.Value.Group()
// Output only non-empty groups.
if len(attrs) > 0 {
+ // The group may turn out to be empty even though it has attrs (for
+ // example, ReplaceAttr may delete all the attrs).
+ // So remember where we are in the buffer, to restore the position
+ // later if necessary.
+ pos := s.buf.Len()
// Inline a group with an empty key.
if a.Key != "" {
s.openGroup(a.Key)
}
- for _, aa := range attrs {
- s.appendAttr(aa)
+ if !s.appendAttrs(attrs) {
+ s.buf.SetLen(pos)
+ return false
}
if a.Key != "" {
s.closeGroup(a.Key)
s.appendKey(a.Key)
s.appendValue(a.Value)
}
+ return true
}
func (s *handleState) appendError(err error) {
wantText: `time.mins=3 time.secs=2 msg=message`,
wantJSON: `{"time":{"mins":3,"secs":2},"msg":"message"}`,
},
+ {
+ name: "replace empty",
+ replace: func([]string, Attr) Attr { return Attr{} },
+ attrs: []Attr{Group("g", Int("a", 1))},
+ wantText: "",
+ wantJSON: `{}`,
+ },
{
name: "replace empty 1",
with: func(h Handler) Handler {
replace: func([]string, Attr) Attr { return Attr{} },
attrs: []Attr{Group("h", Int("b", 2))},
wantText: "",
- wantJSON: `{"g":{"h":{}}}`,
+ wantJSON: `{}`,
},
{
name: "replace empty 2",
replace: func([]string, Attr) Attr { return Attr{} },
attrs: []Attr{Group("i", Int("c", 3))},
wantText: "",
- wantJSON: `{"g":{"h":{"i":{}}}}`,
+ wantJSON: `{}`,
+ },
+ {
+ name: "replace empty 3",
+ with: func(h Handler) Handler { return h.WithGroup("g") },
+ replace: func([]string, Attr) Attr { return Attr{} },
+ attrs: []Attr{Int("a", 1)},
+ wantText: "",
+ wantJSON: `{}`,
+ },
+ {
+ name: "replace empty inline",
+ with: func(h Handler) Handler {
+ return h.WithGroup("g").WithAttrs([]Attr{Int("a", 1)}).WithGroup("h").WithAttrs([]Attr{Int("b", 2)})
+ },
+ replace: func([]string, Attr) Attr { return Attr{} },
+ attrs: []Attr{Group("", Int("c", 3))},
+ wantText: "",
+ wantJSON: `{}`,
},
{
name: "replace partial empty attrs 1",
},
attrs: []Attr{Group("i", Int("c", 3))},
wantText: "g.x=0 g.n=4 g.h.b=2",
- wantJSON: `{"g":{"x":0,"n":4,"h":{"b":2,"i":{}}}}`,
+ wantJSON: `{"g":{"x":0,"n":4,"h":{"b":2}}}`,
},
{
name: "replace resolved group",
}
func (b *Buffer) Reset() {
- *b = (*b)[:0]
+ b.SetLen(0)
}
func (b *Buffer) Write(p []byte) (int, error) {
func (b *Buffer) String() string {
return string(*b)
}
+
+func (b *Buffer) Len() int {
+ return len(*b)
+}
+
+func (b *Buffer) SetLen(n int) {
+ *b = (*b)[:n]
+}