You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
2.6 KiB

  1. // +build 386 amd64,!appengine
  2. package roaring
  3. import (
  4. "io"
  5. "reflect"
  6. "unsafe"
  7. )
  8. func (ac *arrayContainer) writeTo(stream io.Writer) (int, error) {
  9. buf := uint16SliceAsByteSlice(ac.content)
  10. return stream.Write(buf)
  11. }
  12. func (bc *bitmapContainer) writeTo(stream io.Writer) (int, error) {
  13. buf := uint64SliceAsByteSlice(bc.bitmap)
  14. return stream.Write(buf)
  15. }
  16. // readFrom reads an arrayContainer from stream.
  17. // PRE-REQUISITE: you must size the arrayContainer correctly (allocate b.content)
  18. // *before* you call readFrom. We can't guess the size in the stream
  19. // by this point.
  20. func (ac *arrayContainer) readFrom(stream io.Reader) (int, error) {
  21. buf := uint16SliceAsByteSlice(ac.content)
  22. return io.ReadFull(stream, buf)
  23. }
  24. func (bc *bitmapContainer) readFrom(stream io.Reader) (int, error) {
  25. buf := uint64SliceAsByteSlice(bc.bitmap)
  26. n, err := io.ReadFull(stream, buf)
  27. bc.computeCardinality()
  28. return n, err
  29. }
  30. func uint64SliceAsByteSlice(slice []uint64) []byte {
  31. // make a new slice header
  32. header := *(*reflect.SliceHeader)(unsafe.Pointer(&slice))
  33. // update its capacity and length
  34. header.Len *= 8
  35. header.Cap *= 8
  36. // return it
  37. return *(*[]byte)(unsafe.Pointer(&header))
  38. }
  39. func uint16SliceAsByteSlice(slice []uint16) []byte {
  40. // make a new slice header
  41. header := *(*reflect.SliceHeader)(unsafe.Pointer(&slice))
  42. // update its capacity and length
  43. header.Len *= 2
  44. header.Cap *= 2
  45. // return it
  46. return *(*[]byte)(unsafe.Pointer(&header))
  47. }
  48. func (bc *bitmapContainer) asLittleEndianByteSlice() []byte {
  49. return uint64SliceAsByteSlice(bc.bitmap)
  50. }
  51. // Deserialization code follows
  52. func byteSliceAsUint16Slice(slice []byte) []uint16 {
  53. if len(slice)%2 != 0 {
  54. panic("Slice size should be divisible by 2")
  55. }
  56. // make a new slice header
  57. header := *(*reflect.SliceHeader)(unsafe.Pointer(&slice))
  58. // update its capacity and length
  59. header.Len /= 2
  60. header.Cap /= 2
  61. // return it
  62. return *(*[]uint16)(unsafe.Pointer(&header))
  63. }
  64. func byteSliceAsUint64Slice(slice []byte) []uint64 {
  65. if len(slice)%8 != 0 {
  66. panic("Slice size should be divisible by 8")
  67. }
  68. // make a new slice header
  69. header := *(*reflect.SliceHeader)(unsafe.Pointer(&slice))
  70. // update its capacity and length
  71. header.Len /= 8
  72. header.Cap /= 8
  73. // return it
  74. return *(*[]uint64)(unsafe.Pointer(&header))
  75. }
  76. func byteSliceAsInterval16Slice(slice []byte) []interval16 {
  77. if len(slice)%4 != 0 {
  78. panic("Slice size should be divisible by 4")
  79. }
  80. // make a new slice header
  81. header := *(*reflect.SliceHeader)(unsafe.Pointer(&slice))
  82. // update its capacity and length
  83. header.Len /= 4
  84. header.Cap /= 4
  85. // return it
  86. return *(*[]interval16)(unsafe.Pointer(&header))
  87. }