1package collatejson
2
3import (
4	"errors"
5	n1ql "github.com/couchbase/query/value"
6)
7
8var ErrNotAnArray = errors.New("not an array")
9var ErrLenPrefixUnsupported = errors.New("arrayLenPrefix is unsupported")
10
11func (codec *Codec) ExplodeArray(code []byte, tmp []byte) ([][]byte, error) {
12	var err error
13
14	array := make([][]byte, 0)
15
16	if codec.arrayLenPrefix {
17		return nil, ErrLenPrefixUnsupported
18	}
19
20	if code[0] != TypeArray {
21		return nil, ErrNotAnArray
22	}
23
24	code = code[1:]
25	elemBuf := code
26	for code[0] != Terminator {
27		_, code, err = codec.code2json(code, tmp)
28		if err != nil {
29			break
30		}
31
32		if size := len(elemBuf) - len(code); size > 0 {
33			array = append(array, elemBuf[:size])
34			elemBuf = code
35		}
36	}
37
38	return array, err
39}
40
41// Explodes an encoded array, returns encoded parts as well as
42// decoded parts. Also takes an array of explode positions and
43// decode positions to determine what to explode and what to decode
44func (codec *Codec) ExplodeArray2(code []byte, tmp, decbuf []byte, cktmp, dktmp [][]byte,
45	explodePos, decPos []bool, explodeUpto int) ([][]byte, [][]byte, error) {
46	var err error
47	var text []byte
48
49	if codec.arrayLenPrefix {
50		return nil, nil, ErrLenPrefixUnsupported
51	}
52
53	if code[0] != TypeArray {
54		return nil, nil, ErrNotAnArray
55	}
56
57	code = code[1:]
58	elemBuf := code
59
60	pos := 0
61	for code[0] != Terminator {
62		text, code, err = codec.code2json(code, tmp)
63		if err != nil {
64			break
65		}
66
67		if dktmp != nil {
68			if decPos[pos] {
69				copy(decbuf, text)
70				x := decbuf[:len(text)]
71				dktmp[pos] = x
72				decbuf = decbuf[len(text):]
73			} else {
74				dktmp[pos] = nil
75			}
76		}
77
78		if size := len(elemBuf) - len(code); size > 0 {
79			if explodePos[pos] {
80				cktmp[pos] = elemBuf[:size]
81			}
82			elemBuf = code
83		}
84
85		pos++
86		if pos > explodeUpto {
87			return cktmp, dktmp, err
88		}
89	}
90
91	return cktmp, dktmp, err
92}
93
94// Explodes an encoded array, returns encoded parts as well as
95// decoded parts. Also takes an array of explode positions and
96// decode positions to determine what to explode and what to decode
97func (codec *Codec) ExplodeArray3(code []byte, tmp []byte, cktmp [][]byte,
98	dktmp n1ql.Values, explodePos, decPos []bool, explodeUpto int) ([][]byte, n1ql.Values, error) {
99	var err error
100	var val n1ql.Value
101	var decode bool
102
103	if codec.arrayLenPrefix {
104		return nil, nil, ErrLenPrefixUnsupported
105	}
106
107	if code[0] != TypeArray {
108		return nil, nil, ErrNotAnArray
109	}
110
111	code = code[1:]
112	elemBuf := code
113
114	pos := 0
115	for code[0] != Terminator {
116
117		if decPos != nil {
118			decode = decPos[pos]
119		}
120
121		val, code, err = codec.code2n1ql(code, tmp, decode)
122		if err != nil {
123			break
124		}
125
126		if dktmp != nil {
127			dktmp[pos] = val
128		}
129
130		if size := len(elemBuf) - len(code); size > 0 {
131			if explodePos[pos] {
132				cktmp[pos] = elemBuf[:size]
133			}
134			elemBuf = code
135		}
136
137		pos++
138		if pos > explodeUpto {
139			return cktmp, dktmp, err
140		}
141	}
142
143	return cktmp, dktmp, err
144}
145
146func (codec *Codec) JoinArray(vals [][]byte, code []byte) ([]byte, error) {
147	if codec.arrayLenPrefix {
148		return nil, ErrLenPrefixUnsupported
149	}
150
151	code = append(code, TypeArray)
152	for _, val := range vals {
153		code = append(code, val...)
154	}
155	code = append(code, Terminator)
156
157	return code, nil
158}
159