@@ -6,9 +6,8 @@ package roaring
66import (
77 "encoding/binary"
88 "errors"
9+ "fmt"
910 "io"
10- "reflect"
11- "runtime"
1211 "unsafe"
1312)
1413
@@ -26,51 +25,30 @@ func (bc *bitmapContainer) writeTo(stream io.Writer) (int, error) {
2625}
2726
2827func uint64SliceAsByteSlice (slice []uint64 ) []byte {
29- // make a new slice header
30- header := * (* reflect .SliceHeader )(unsafe .Pointer (& slice ))
31-
32- // update its capacity and length
33- header .Len *= 8
34- header .Cap *= 8
35-
36- // instantiate result and use KeepAlive so data isn't unmapped.
37- result := * (* []byte )(unsafe .Pointer (& header ))
38- runtime .KeepAlive (& slice )
39-
40- // return it
41- return result
28+ ptr := unsafe .SliceData (slice )
29+ if ptr == nil {
30+ return nil
31+ }
32+ const size = unsafe .Sizeof (uint64 (0 ))
33+ return unsafe .Slice (((* byte )(unsafe .Pointer (ptr ))), int (size )* len (slice ))
4234}
4335
4436func uint16SliceAsByteSlice (slice []uint16 ) []byte {
45- // make a new slice header
46- header := * (* reflect .SliceHeader )(unsafe .Pointer (& slice ))
47-
48- // update its capacity and length
49- header .Len *= 2
50- header .Cap *= 2
51-
52- // instantiate result and use KeepAlive so data isn't unmapped.
53- result := * (* []byte )(unsafe .Pointer (& header ))
54- runtime .KeepAlive (& slice )
55-
56- // return it
57- return result
37+ ptr := unsafe .SliceData (slice )
38+ if ptr == nil {
39+ return nil
40+ }
41+ const size = unsafe .Sizeof (uint16 (0 ))
42+ return unsafe .Slice (((* byte )(unsafe .Pointer (ptr ))), int (size )* len (slice ))
5843}
5944
6045func interval16SliceAsByteSlice (slice []interval16 ) []byte {
61- // make a new slice header
62- header := * (* reflect .SliceHeader )(unsafe .Pointer (& slice ))
63-
64- // update its capacity and length
65- header .Len *= 4
66- header .Cap *= 4
67-
68- // instantiate result and use KeepAlive so data isn't unmapped.
69- result := * (* []byte )(unsafe .Pointer (& header ))
70- runtime .KeepAlive (& slice )
71-
72- // return it
73- return result
46+ ptr := unsafe .SliceData (slice )
47+ if ptr == nil {
48+ return nil
49+ }
50+ const size = unsafe .Sizeof (interval16 {})
51+ return unsafe .Slice (((* byte )(unsafe .Pointer (ptr ))), int (size )* len (slice ))
7452}
7553
7654func (bc * bitmapContainer ) asLittleEndianByteSlice () []byte {
@@ -86,69 +64,39 @@ func (bc *bitmapContainer) asLittleEndianByteSlice() []byte {
8664// or modified while you hold the returned slince.
8765// //
8866func byteSliceAsUint16Slice (slice []byte ) (result []uint16 ) { // here we create a new slice holder
89- if len (slice )% 2 != 0 {
90- panic ("Slice size should be divisible by 2" )
67+ const sz = int (unsafe .Sizeof (uint16 (0 )))
68+ if len (slice )% sz != 0 {
69+ panic (fmt .Sprintf ("Slice size should be divisible by %d" , sz ))
9170 }
92- // reference: https://go101.org/article/unsafe.html
93-
94- // make a new slice header
95- bHeader := (* reflect .SliceHeader )(unsafe .Pointer (& slice ))
96- rHeader := (* reflect .SliceHeader )(unsafe .Pointer (& result ))
97-
98- // transfer the data from the given slice to a new variable (our result)
99- rHeader .Data = bHeader .Data
100- rHeader .Len = bHeader .Len / 2
101- rHeader .Cap = bHeader .Cap / 2
102-
103- // instantiate result and use KeepAlive so data isn't unmapped.
104- runtime .KeepAlive (& slice ) // it is still crucial, GC can free it)
105-
106- // return result
107- return
71+ ptr := unsafe .SliceData (slice )
72+ if ptr == nil {
73+ return nil
74+ }
75+ return unsafe .Slice ((* uint16 )(unsafe .Pointer (ptr )), len (slice )/ sz )
10876}
10977
11078func byteSliceAsUint64Slice (slice []byte ) (result []uint64 ) {
111- if len (slice )% 8 != 0 {
112- panic ("Slice size should be divisible by 8" )
79+ const sz = int (unsafe .Sizeof (uint64 (0 )))
80+ if len (slice )% sz != 0 {
81+ panic (fmt .Sprintf ("Slice size should be divisible by %d" , sz ))
11382 }
114- // reference: https://go101.org/article/unsafe.html
115-
116- // make a new slice header
117- bHeader := (* reflect .SliceHeader )(unsafe .Pointer (& slice ))
118- rHeader := (* reflect .SliceHeader )(unsafe .Pointer (& result ))
119-
120- // transfer the data from the given slice to a new variable (our result)
121- rHeader .Data = bHeader .Data
122- rHeader .Len = bHeader .Len / 8
123- rHeader .Cap = bHeader .Cap / 8
124-
125- // instantiate result and use KeepAlive so data isn't unmapped.
126- runtime .KeepAlive (& slice ) // it is still crucial, GC can free it)
127-
128- // return result
129- return
83+ ptr := unsafe .SliceData (slice )
84+ if ptr == nil {
85+ return nil
86+ }
87+ return unsafe .Slice ((* uint64 )(unsafe .Pointer (ptr )), len (slice )/ sz )
13088}
13189
13290func byteSliceAsInterval16Slice (slice []byte ) (result []interval16 ) {
133- if len (slice )% 4 != 0 {
134- panic ("Slice size should be divisible by 4" )
91+ const sz = int (unsafe .Sizeof (interval16 {}))
92+ if len (slice )% sz != 0 {
93+ panic (fmt .Sprintf ("Slice size should be divisible by %d" , sz ))
13594 }
136- // reference: https://go101.org/article/unsafe.html
137-
138- // make a new slice header
139- bHeader := (* reflect .SliceHeader )(unsafe .Pointer (& slice ))
140- rHeader := (* reflect .SliceHeader )(unsafe .Pointer (& result ))
141-
142- // transfer the data from the given slice to a new variable (our result)
143- rHeader .Data = bHeader .Data
144- rHeader .Len = bHeader .Len / 4
145- rHeader .Cap = bHeader .Cap / 4
146-
147- // instantiate result and use KeepAlive so data isn't unmapped.
148- runtime .KeepAlive (& slice ) // it is still crucial, GC can free it)
149-
150- // return result
151- return
95+ ptr := unsafe .SliceData (slice )
96+ if ptr == nil {
97+ return nil
98+ }
99+ return unsafe .Slice ((* interval16 )(unsafe .Pointer (ptr )), len (slice )/ sz )
152100}
153101
154102func byteSliceAsContainerSlice (slice []byte ) (result []container ) {
@@ -158,114 +106,59 @@ func byteSliceAsContainerSlice(slice []byte) (result []container) {
158106 if len (slice )% containerSize != 0 {
159107 panic ("Slice size should be divisible by unsafe.Sizeof(container)" )
160108 }
161- // reference: https://go101.org/article/unsafe.html
162-
163- // make a new slice header
164- bHeader := (* reflect .SliceHeader )(unsafe .Pointer (& slice ))
165- rHeader := (* reflect .SliceHeader )(unsafe .Pointer (& result ))
166-
167- // transfer the data from the given slice to a new variable (our result)
168- rHeader .Data = bHeader .Data
169- rHeader .Len = bHeader .Len / containerSize
170- rHeader .Cap = bHeader .Cap / containerSize
171-
172- // instantiate result and use KeepAlive so data isn't unmapped.
173- runtime .KeepAlive (& slice ) // it is still crucial, GC can free it)
174-
175- // return result
176- return
109+ ptr := unsafe .SliceData (slice )
110+ if ptr == nil {
111+ return nil
112+ }
113+ return unsafe .Slice ((* container )(unsafe .Pointer (ptr )), len (slice )/ containerSize )
177114}
178115
179116func byteSliceAsBitsetSlice (slice []byte ) (result []bitmapContainer ) {
180- bitsetSize : = int (unsafe .Sizeof (bitmapContainer {}))
117+ const bitsetSize = int (unsafe .Sizeof (bitmapContainer {}))
181118 if len (slice )% bitsetSize != 0 {
182119 panic ("Slice size should be divisible by unsafe.Sizeof(bitmapContainer)" )
183120 }
184- // reference: https://go101.org/article/unsafe.html
185-
186- // make a new slice header
187- bHeader := (* reflect .SliceHeader )(unsafe .Pointer (& slice ))
188- rHeader := (* reflect .SliceHeader )(unsafe .Pointer (& result ))
189-
190- // transfer the data from the given slice to a new variable (our result)
191- rHeader .Data = bHeader .Data
192- rHeader .Len = bHeader .Len / bitsetSize
193- rHeader .Cap = bHeader .Cap / bitsetSize
194-
195- // instantiate result and use KeepAlive so data isn't unmapped.
196- runtime .KeepAlive (& slice ) // it is still crucial, GC can free it)
197-
198- // return result
199- return
121+ ptr := unsafe .SliceData (slice )
122+ if ptr == nil {
123+ return nil
124+ }
125+ return unsafe .Slice ((* bitmapContainer )(unsafe .Pointer (ptr )), len (slice )/ bitsetSize )
200126}
201127
202128func byteSliceAsArraySlice (slice []byte ) (result []arrayContainer ) {
203- arraySize : = int (unsafe .Sizeof (arrayContainer {}))
129+ const arraySize = int (unsafe .Sizeof (arrayContainer {}))
204130 if len (slice )% arraySize != 0 {
205131 panic ("Slice size should be divisible by unsafe.Sizeof(arrayContainer)" )
206132 }
207- // reference: https://go101.org/article/unsafe.html
208-
209- // make a new slice header
210- bHeader := (* reflect .SliceHeader )(unsafe .Pointer (& slice ))
211- rHeader := (* reflect .SliceHeader )(unsafe .Pointer (& result ))
212-
213- // transfer the data from the given slice to a new variable (our result)
214- rHeader .Data = bHeader .Data
215- rHeader .Len = bHeader .Len / arraySize
216- rHeader .Cap = bHeader .Cap / arraySize
217-
218- // instantiate result and use KeepAlive so data isn't unmapped.
219- runtime .KeepAlive (& slice ) // it is still crucial, GC can free it)
220-
221- // return result
222- return
133+ ptr := unsafe .SliceData (slice )
134+ if ptr == nil {
135+ return nil
136+ }
137+ return unsafe .Slice ((* arrayContainer )(unsafe .Pointer (ptr )), len (slice )/ arraySize )
223138}
224139
225140func byteSliceAsRun16Slice (slice []byte ) (result []runContainer16 ) {
226- run16Size : = int (unsafe .Sizeof (runContainer16 {}))
141+ const run16Size = int (unsafe .Sizeof (runContainer16 {}))
227142 if len (slice )% run16Size != 0 {
228143 panic ("Slice size should be divisible by unsafe.Sizeof(runContainer16)" )
229144 }
230- // reference: https://go101.org/article/unsafe.html
231-
232- // make a new slice header
233- bHeader := (* reflect .SliceHeader )(unsafe .Pointer (& slice ))
234- rHeader := (* reflect .SliceHeader )(unsafe .Pointer (& result ))
235-
236- // transfer the data from the given slice to a new variable (our result)
237- rHeader .Data = bHeader .Data
238- rHeader .Len = bHeader .Len / run16Size
239- rHeader .Cap = bHeader .Cap / run16Size
240-
241- // instantiate result and use KeepAlive so data isn't unmapped.
242- runtime .KeepAlive (& slice ) // it is still crucial, GC can free it)
243-
244- // return result
245- return
145+ ptr := unsafe .SliceData (slice )
146+ if ptr == nil {
147+ return nil
148+ }
149+ return unsafe .Slice ((* runContainer16 )(unsafe .Pointer (ptr )), len (slice )/ run16Size )
246150}
247151
248152func byteSliceAsBoolSlice (slice []byte ) (result []bool ) {
249- boolSize : = int (unsafe .Sizeof (true ))
153+ const boolSize = int (unsafe .Sizeof (true ))
250154 if len (slice )% boolSize != 0 {
251155 panic ("Slice size should be divisible by unsafe.Sizeof(bool)" )
252156 }
253- // reference: https://go101.org/article/unsafe.html
254-
255- // make a new slice header
256- bHeader := (* reflect .SliceHeader )(unsafe .Pointer (& slice ))
257- rHeader := (* reflect .SliceHeader )(unsafe .Pointer (& result ))
258-
259- // transfer the data from the given slice to a new variable (our result)
260- rHeader .Data = bHeader .Data
261- rHeader .Len = bHeader .Len / boolSize
262- rHeader .Cap = bHeader .Cap / boolSize
263-
264- // instantiate result and use KeepAlive so data isn't unmapped.
265- runtime .KeepAlive (& slice ) // it is still crucial, GC can free it)
266-
267- // return result
268- return
157+ ptr := unsafe .SliceData (slice )
158+ if ptr == nil {
159+ return nil
160+ }
161+ return unsafe .Slice ((* bool )(unsafe .Pointer (ptr )), len (slice )/ boolSize )
269162}
270163
271164// FrozenView creates a static view of a serialized bitmap stored in buf.
0 commit comments