-
Notifications
You must be signed in to change notification settings - Fork 0
/
join.go
84 lines (63 loc) · 1.49 KB
/
join.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
package jq
import (
"fmt"
"nikand.dev/go/cbor"
)
type (
Join struct {
Separator Filter
Tag Tag
arr []Off
}
)
func NewJoin(sep Filter) *Join { return &Join{Separator: sep, Tag: cbor.String} }
func NewJoinOf(f, sep Filter) *Pipe {
return NewPipe(f, NewJoin(sep))
}
func (f *Join) ApplyTo(b *Buffer, off Off, next bool) (res Off, more bool, err error) {
br := b.Reader()
bw := b.Writer()
sep := []byte{}
if tag := br.Tag(off); tag != cbor.Array {
return off, false, NewTypeError(tag, cbor.Array)
}
if f.Separator != nil {
res, more, err = f.Separator.ApplyTo(b, off, next)
if err != nil {
return off, false, err
}
if res == None {
return None, more, nil
}
sep = br.Bytes(res)
}
tag := csel(f.Tag != 0, f.Tag, cbor.String)
f.arr = br.ArrayMap(off, f.arr[:0])
if len(f.arr) == 0 && tag == cbor.String {
return EmptyString, more, nil
}
total := 0
for _, el := range f.arr {
tag := br.Tag(el)
if tag != cbor.String && tag != cbor.Bytes {
return off, false, NewTypeError(tag, cbor.String, cbor.Bytes)
}
total += len(br.Bytes(el))
}
if len(f.arr) != 0 {
total += len(sep) * (len(f.arr) - 1)
}
res = bw.Off()
b.B = b.Encoder.CBOR.AppendTag(b.B, tag, total)
for i, el := range f.arr {
if i != 0 && len(sep) != 0 {
b.B = append(b.B, sep...)
}
s := br.Bytes(el)
b.B = append(b.B, s...)
}
return res, more, nil
}
func (j Join) String() string {
return fmt.Sprintf("join(%v)", csel[any](j.Separator != nil, j.Separator, "null"))
}