• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

apache / datasketches-go / 23520345713

25 Mar 2026 01:23AM UTC coverage: 86.404% (-0.1%) from 86.509%
23520345713

push

github

web-flow
Merge pull request #140 from proost/ci-upload-coverage-directly

ci: upload coverage directly

20743 of 24007 relevant lines covered (86.4%)

0.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

38.18
/tuple/arrayofstrings_sketch.go
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *     http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17

18
package tuple
19

20
import (
21
        "encoding/binary"
22
        "errors"
23
        "io"
24

25
        "github.com/cespare/xxhash/v2"
26
)
27

28
var (
29
        ErrTooManyStrings = errors.New("string slice length must be <= 127")
30
)
31

32
const (
33
        // NOTE: This is from java Util.PRIME for array of strings sketch key hash.
34
        stringSliceHashSeed = 0x7A3C_CA71
35

36
        maxStringSliceLength = 127
37
)
38

39
// GenerateHashKeyFromStrings returns the hash of the concatenated strings.
40
func GenerateHashKeyFromStrings(s []string) uint64 {
1✔
41
        hasher := xxhash.NewWithSeed(stringSliceHashSeed)
1✔
42
        for i, v := range s {
2✔
43
                hasher.WriteString(v)
1✔
44
                if i+1 < len(s) {
2✔
45
                        hasher.WriteString(",")
1✔
46
                }
1✔
47
        }
48
        return hasher.Sum64()
1✔
49
}
50

51
// ArrayOfStringsSummary represents a summary type that holds and manages a collection of string values.
52
type ArrayOfStringsSummary struct {
53
        values []string
54
}
55

56
// NewArrayOfStringsSummaryFunc creates and returns a pointer to a new instance of ArrayOfStringsSummary.
57
func NewArrayOfStringsSummaryFunc() *ArrayOfStringsSummary {
×
58
        return &ArrayOfStringsSummary{}
×
59
}
×
60

61
// Reset clears all string values from the ArrayOfStringsSummary.
62
func (s *ArrayOfStringsSummary) Reset() {
×
63
        s.values = s.values[:0]
×
64
}
×
65

66
// Clone creates and returns a deep copy of the current ArrayOfStringsSummary instance.
67
func (s *ArrayOfStringsSummary) Clone() Summary {
×
68
        return &ArrayOfStringsSummary{
×
69
                values: append([]string{}, s.values...),
×
70
        }
×
71
}
×
72

73
// Update incorporates a new string value into the summary.
74
func (s *ArrayOfStringsSummary) Update(values []string) {
1✔
75
        s.values = values
1✔
76
}
1✔
77

78
// ArrayOfStringsSummaryWriter writes an ArrayOfStringsSummary to the provided io.Writer in binary format.
79
// It validates the length of the string slice and computes total bytes for serialization.
80
// Returns an error if the input exceeds the maximum allowed slice length or if any write operation fails.
81
//
82
// If the caller cares about cross-language compatibility,
83
// it is the caller's responsibility to ensure that those strings are encoded as valid UTF-8.
84
func ArrayOfStringsSummaryWriter(w io.Writer, summary *ArrayOfStringsSummary) error {
1✔
85
        return writeStrings(w, summary.values)
1✔
86
}
1✔
87

88
func writeStrings(w io.Writer, values []string) error {
1✔
89
        if len(values) > maxStringSliceLength {
2✔
90
                return ErrTooManyStrings
1✔
91
        }
1✔
92

93
        totalBytes := computeStringsTotalBytes(values)
×
94
        if err := binary.Write(w, binary.LittleEndian, totalBytes); err != nil {
×
95
                return err
×
96
        }
×
97

98
        numNodes := uint8(len(values))
×
99
        if err := binary.Write(w, binary.LittleEndian, numNodes); err != nil {
×
100
                return err
×
101
        }
×
102

103
        for _, v := range values {
×
104
                length := uint32(len(v))
×
105
                if err := binary.Write(w, binary.LittleEndian, length); err != nil {
×
106
                        return err
×
107
                }
×
108

109
                if _, err := w.Write([]byte(v)); err != nil {
×
110
                        return err
×
111
                }
×
112
        }
113
        return nil
×
114
}
115

116
func computeStringsTotalBytes(values []string) uint32 {
×
117
        total := uint32(4 + 1 + len(values)*4)
×
118
        for _, v := range values {
×
119
                total += uint32(len(v))
×
120
        }
×
121
        return total
×
122
}
123

124
// ArrayOfStringsSummaryReader reads an ArrayOfStringsSummary from the provided io.Reader in binary format.
125
// It validates the length of the string slice and reads the total bytes for deserialization.
126
// Returns an error if the input exceeds the maximum allowed slice length or if any read operation fails.
127
//
128
// If the caller cares about cross-language compatibility,
129
// it is the caller's responsibility to ensure that the serialized string data is encoded as valid UTF-8.
130
func ArrayOfStringsSummaryReader(r io.Reader) (*ArrayOfStringsSummary, error) {
1✔
131
        values, err := readStrings(r)
1✔
132
        if err != nil {
2✔
133
                return nil, err
1✔
134
        }
1✔
135

136
        return &ArrayOfStringsSummary{
1✔
137
                values: values,
1✔
138
        }, nil
1✔
139
}
140

141
func readStrings(r io.Reader) ([]string, error) {
1✔
142
        var totalBytes uint32
1✔
143
        if err := binary.Read(r, binary.LittleEndian, &totalBytes); err != nil {
1✔
144
                return nil, err
×
145
        }
×
146

147
        var numNodes uint8
1✔
148
        if err := binary.Read(r, binary.LittleEndian, &numNodes); err != nil {
1✔
149
                return nil, err
×
150
        }
×
151
        if numNodes > maxStringSliceLength {
2✔
152
                return nil, ErrTooManyStrings
1✔
153
        }
1✔
154

155
        values := make([]string, 0, numNodes)
1✔
156
        for i := uint8(0); i < numNodes; i++ {
2✔
157
                var length uint32
1✔
158
                if err := binary.Read(r, binary.LittleEndian, &length); err != nil {
1✔
159
                        return nil, err
×
160
                }
×
161

162
                bytes := make([]byte, length)
1✔
163
                if _, err := io.ReadFull(r, bytes); err != nil {
1✔
164
                        return nil, err
×
165
                }
×
166

167
                values = append(values, string(bytes))
1✔
168
        }
169

170
        return values, nil
1✔
171
}
172

173
// ArrayOfStringsInlineSummary stores a string-slice summary inline in the sketch entry
174
// instead of behind a pointer to reduce per-entry allocations.
175
type ArrayOfStringsInlineSummary struct {
176
        values []string
177
}
178

179
// Reset clears the inline summary state.
180
// It is a no-op because this type is intended to be updated via ArrayOfStringsInlineSummaryUpdateFunc.
181
func (s ArrayOfStringsInlineSummary) Reset() {}
×
182

183
// Update satisfies the UpdatableSummary interface.
184
// It is a no-op because this type is intended to be updated via ArrayOfStringsInlineSummaryUpdateFunc.
185
func (s ArrayOfStringsInlineSummary) Update([]string) {}
×
186

187
// Clone returns a copy of the inline summary.
188
func (s ArrayOfStringsInlineSummary) Clone() Summary {
×
189
        return ArrayOfStringsInlineSummary{
×
190
                values: append([]string(nil), s.values...),
×
191
        }
×
192
}
×
193

194
// NewArrayOfStringsInlineSummary returns a new empty inline summary.
195
func NewArrayOfStringsInlineSummary() ArrayOfStringsInlineSummary {
×
196
        return ArrayOfStringsInlineSummary{}
×
197
}
×
198

199
// ArrayOfStringsInlineSummaryUpdateFunc updates an inline summary with the provided string slice.
200
// The returned summary stores the slice header inline and reuses the provided slice reference.
201
func ArrayOfStringsInlineSummaryUpdateFunc(s ArrayOfStringsInlineSummary, values []string) ArrayOfStringsInlineSummary {
×
202
        return ArrayOfStringsInlineSummary{
×
203
                values: values,
×
204
        }
×
205
}
×
206

207
// ArrayOfStringsInlineSummaryWriter writes an ArrayOfStringsInlineSummary to the provided io.Writer in binary format.
208
// It validates the length of the string slice and computes total bytes for serialization.
209
// Returns an error if the input exceeds the maximum allowed slice length or if any write operation fails.
210
//
211
// If the caller cares about cross-language compatibility,
212
// it is the caller's responsibility to ensure that those strings are encoded as valid UTF-8.
213
func ArrayOfStringsInlineSummaryWriter(w io.Writer, summary ArrayOfStringsInlineSummary) error {
×
214
        return writeStrings(w, summary.values)
×
215
}
×
216

217
// ArrayOfStringsInlineSummaryReader reads an ArrayOfStringsInlineSummary from the provided io.Reader in binary format.
218
// It validates the length of the string slice and reads the total bytes for deserialization.
219
// Returns an error if the input exceeds the maximum allowed slice length or if any read operation fails.
220
//
221
// If the caller cares about cross-language compatibility,
222
// it is the caller's responsibility to ensure that the serialized string data is encoded as valid UTF-8.
223
func ArrayOfStringsInlineSummaryReader(r io.Reader) (ArrayOfStringsInlineSummary, error) {
×
224
        values, err := readStrings(r)
×
225
        if err != nil {
×
226
                return ArrayOfStringsInlineSummary{}, err
×
227
        }
×
228

229
        return ArrayOfStringsInlineSummary{
×
230
                values: values,
×
231
        }, nil
×
232
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc