1// Licensed to the Apache Software Foundation (ASF) under one 2// or more contributor license agreements. See the NOTICE file 3// distributed with this work for additional information 4// regarding copyright ownership. The ASF licenses this file 5// to you under the Apache License, Version 2.0 (the 6// "License"); you may not use this file except in compliance 7// with 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 17package array 18 19import ( 20 "bytes" 21 "fmt" 22 "strings" 23 "unsafe" 24 25 "github.com/apache/arrow/go/v6/arrow" 26) 27 28// A type which represents an immutable sequence of variable-length binary strings. 29type Binary struct { 30 array 31 valueOffsets []int32 32 valueBytes []byte 33} 34 35// NewBinaryData constructs a new Binary array from data. 36func NewBinaryData(data *Data) *Binary { 37 a := &Binary{} 38 a.refCount = 1 39 a.setData(data) 40 return a 41} 42 43// Value returns the slice at index i. This value should not be mutated. 44func (a *Binary) Value(i int) []byte { 45 if i < 0 || i >= a.array.data.length { 46 panic("arrow/array: index out of range") 47 } 48 idx := a.array.data.offset + i 49 return a.valueBytes[a.valueOffsets[idx]:a.valueOffsets[idx+1]] 50} 51 52// ValueString returns the string at index i without performing additional allocations. 53// The string is only valid for the lifetime of the Binary array. 54func (a *Binary) ValueString(i int) string { 55 b := a.Value(i) 56 return *(*string)(unsafe.Pointer(&b)) 57} 58 59func (a *Binary) ValueOffset(i int) int { 60 if i < 0 || i >= a.array.data.length { 61 panic("arrow/array: index out of range") 62 } 63 return int(a.valueOffsets[a.array.data.offset+i]) 64} 65 66func (a *Binary) ValueLen(i int) int { 67 if i < 0 || i >= a.array.data.length { 68 panic("arrow/array: index out of range") 69 } 70 beg := a.array.data.offset + i 71 return int(a.valueOffsets[beg+1] - a.valueOffsets[beg]) 72} 73 74func (a *Binary) ValueOffsets() []int32 { 75 beg := a.array.data.offset 76 end := beg + a.array.data.length + 1 77 return a.valueOffsets[beg:end] 78} 79 80func (a *Binary) ValueBytes() []byte { 81 beg := a.array.data.offset 82 end := beg + a.array.data.length 83 return a.valueBytes[a.valueOffsets[beg]:a.valueOffsets[end]] 84} 85 86func (a *Binary) String() string { 87 o := new(strings.Builder) 88 o.WriteString("[") 89 for i := 0; i < a.Len(); i++ { 90 if i > 0 { 91 o.WriteString(" ") 92 } 93 switch { 94 case a.IsNull(i): 95 o.WriteString("(null)") 96 default: 97 fmt.Fprintf(o, "%q", a.ValueString(i)) 98 } 99 } 100 o.WriteString("]") 101 return o.String() 102} 103 104func (a *Binary) setData(data *Data) { 105 if len(data.buffers) != 3 { 106 panic("len(data.buffers) != 3") 107 } 108 109 a.array.setData(data) 110 111 if valueData := data.buffers[2]; valueData != nil { 112 a.valueBytes = valueData.Bytes() 113 } 114 115 if valueOffsets := data.buffers[1]; valueOffsets != nil { 116 a.valueOffsets = arrow.Int32Traits.CastFromBytes(valueOffsets.Bytes()) 117 } 118} 119 120func arrayEqualBinary(left, right *Binary) bool { 121 for i := 0; i < left.Len(); i++ { 122 if left.IsNull(i) { 123 continue 124 } 125 if !bytes.Equal(left.Value(i), right.Value(i)) { 126 return false 127 } 128 } 129 return true 130} 131 132var ( 133 _ Interface = (*Binary)(nil) 134) 135