|
3 | 3 |
|
4 | 4 | //! Variable-length binary vector implementation. |
5 | 5 |
|
| 6 | +use std::fmt::Debug; |
| 7 | +use std::ops::RangeBounds; |
6 | 8 | use std::sync::Arc; |
7 | 9 |
|
8 | | -use vortex_buffer::{Buffer, ByteBuffer}; |
| 10 | +use vortex_buffer::{Alignment, Buffer, ByteBuffer}; |
9 | 11 | use vortex_error::{VortexExpect, VortexResult, vortex_ensure}; |
10 | 12 | use vortex_mask::Mask; |
11 | 13 |
|
12 | | -use crate::VectorOps; |
13 | | -use crate::binaryview::BinaryViewType; |
14 | 14 | use crate::binaryview::vector_mut::BinaryViewVectorMut; |
15 | 15 | use crate::binaryview::view::{BinaryView, validate_views}; |
| 16 | +use crate::binaryview::{BinaryViewScalar, BinaryViewType}; |
| 17 | +use crate::{Scalar, VectorOps}; |
16 | 18 |
|
17 | 19 | /// A variable-length binary vector. |
18 | 20 | /// |
@@ -108,10 +110,50 @@ impl<T: BinaryViewType> BinaryViewVector<T> { |
108 | 110 | (self.views, self.buffers, self.validity) |
109 | 111 | } |
110 | 112 |
|
| 113 | + /// Get the `index` item from the vector as an owned `Scalar` type with zero-copy. |
| 114 | + /// |
| 115 | + /// This function will panic is `index` is out of range for the vector's length. |
| 116 | + pub fn get(&self, index: usize) -> Option<T::Scalar> { |
| 117 | + if !self.validity.value(index) { |
| 118 | + return None; |
| 119 | + } |
| 120 | + |
| 121 | + let view = &self.views[index]; |
| 122 | + if view.is_inlined() { |
| 123 | + let view = view.as_inlined(); |
| 124 | + |
| 125 | + // We find the occurrence of the inlined data in the views buffer. |
| 126 | + let buffer = self |
| 127 | + .views |
| 128 | + .clone() |
| 129 | + .into_byte_buffer() |
| 130 | + .aligned(Alignment::none()) |
| 131 | + .slice_ref(&view.data[..view.size as usize]); |
| 132 | + |
| 133 | + // SAFETY: validation that the string data contained in this vector is performed |
| 134 | + // at construction time, either in the constructor for safe construction, or by |
| 135 | + // the caller (when using the unchecked constructor). |
| 136 | + Some(unsafe { T::scalar_from_buffer_unchecked(buffer) }) |
| 137 | + } else { |
| 138 | + // Get a pointer into the buffer range |
| 139 | + let view_ref = view.as_view(); |
| 140 | + let buffer = &self.buffers[view_ref.buffer_index as usize]; |
| 141 | + |
| 142 | + let start = view_ref.offset as usize; |
| 143 | + let length = view_ref.size as usize; |
| 144 | + let buffer_slice = buffer.slice(start..start + length); |
| 145 | + |
| 146 | + // SAFETY: validation that the string data contained in this vector is performed |
| 147 | + // at construction time, either in the constructor for safe construction, or by |
| 148 | + // the caller (when using the unchecked constructor). |
| 149 | + Some(unsafe { T::scalar_from_buffer_unchecked(buffer_slice) }) |
| 150 | + } |
| 151 | + } |
| 152 | + |
111 | 153 | /// Get the `index` item from the vector as a native `Slice` type. |
112 | 154 | /// |
113 | 155 | /// This function will panic is `index` is out of range for the vector's length. |
114 | | - pub fn get(&self, index: usize) -> Option<&T::Slice> { |
| 156 | + pub fn get_ref(&self, index: usize) -> Option<&T::Slice> { |
115 | 157 | if !self.validity.value(index) { |
116 | 158 | return None; |
117 | 159 | } |
@@ -160,6 +202,15 @@ impl<T: BinaryViewType> VectorOps for BinaryViewVector<T> { |
160 | 202 | &self.validity |
161 | 203 | } |
162 | 204 |
|
| 205 | + fn scalar_at(&self, index: usize) -> Scalar { |
| 206 | + assert!(index < self.len()); |
| 207 | + BinaryViewScalar::<T>::from(self.get(index)).into() |
| 208 | + } |
| 209 | + |
| 210 | + fn slice(&self, _range: impl RangeBounds<usize> + Clone + Debug) -> Self { |
| 211 | + todo!() |
| 212 | + } |
| 213 | + |
163 | 214 | fn try_into_mut(self) -> Result<BinaryViewVectorMut<T>, Self> { |
164 | 215 | let views_mut = match self.views.try_into_mut() { |
165 | 216 | Ok(views_mut) => views_mut, |
|
0 commit comments