Skip to content

Commit 73faf99

Browse files
committed
Adding try_append_value implementation.
1 parent 597c903 commit 73faf99

File tree

1 file changed

+47
-6
lines changed

1 file changed

+47
-6
lines changed

arrow-array/src/builder/generic_bytes_view_builder.rs

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -306,15 +306,33 @@ impl<T: ByteViewType + ?Sized> GenericByteViewBuilder<T> {
306306
/// - String length exceeds `u32::MAX`
307307
#[inline]
308308
pub fn append_value(&mut self, value: impl AsRef<T::Native>) {
309+
self.try_append_value(value).unwrap()
310+
}
311+
312+
/// Appends a value into the builder
313+
///
314+
/// # Errors
315+
///
316+
/// Returns an error if:
317+
/// - String buffer count exceeds `u32::MAX`
318+
/// - String length exceeds `u32::MAX`
319+
#[inline]
320+
pub fn try_append_value(&mut self, value: impl AsRef<T::Native>) -> Result<(), ArrowError> {
309321
let v: &[u8] = value.as_ref().as_ref();
310-
let length: u32 = v.len().try_into().unwrap();
322+
let length: u32 = v.len().try_into().map_err(|_| {
323+
ArrowError::InvalidArgumentError(format!(
324+
"String length {} exceeds u32::MAX",
325+
v.len()
326+
))
327+
})?;
328+
311329
if length <= MAX_INLINE_VIEW_LEN {
312330
let mut view_buffer = [0; 16];
313331
view_buffer[0..4].copy_from_slice(&length.to_le_bytes());
314332
view_buffer[4..4 + v.len()].copy_from_slice(v);
315333
self.views_buffer.push(u128::from_le_bytes(view_buffer));
316334
self.null_buffer_builder.append_non_null();
317-
return;
335+
return Ok(());
318336
}
319337

320338
// Deduplication if:
@@ -339,7 +357,7 @@ impl<T: ByteViewType + ?Sized> GenericByteViewBuilder<T> {
339357
self.views_buffer.push(self.views_buffer[*idx]);
340358
self.null_buffer_builder.append_non_null();
341359
self.string_tracker = Some((ht, hasher));
342-
return;
360+
return Ok(());
343361
}
344362
Entry::Vacant(vacant) => {
345363
// o.w. we insert the (string hash -> view index)
@@ -356,17 +374,40 @@ impl<T: ByteViewType + ?Sized> GenericByteViewBuilder<T> {
356374
let to_reserve = v.len().max(self.block_size.next_size() as usize);
357375
self.in_progress.reserve(to_reserve);
358376
};
359-
let offset = self.in_progress.len() as u32;
377+
let offset: u32 = self.in_progress.len().try_into().map_err(|_| {
378+
ArrowError::InvalidArgumentError(format!(
379+
"In-progress buffer length {} exceeds u32::MAX",
380+
self.in_progress.len()
381+
))
382+
})?;
360383
self.in_progress.extend_from_slice(v);
361384

385+
let prefix = v.get(0..4)
386+
.and_then(|slice| slice.try_into().ok())
387+
.map(u32::from_le_bytes)
388+
.ok_or_else(|| {
389+
ArrowError::InvalidArgumentError(
390+
"String must be at least 4 bytes for non-inline view".to_string()
391+
)
392+
})?;
393+
394+
let buffer_index: u32 = self.completed.len().try_into().map_err(|_| {
395+
ArrowError::InvalidArgumentError(format!(
396+
"Buffer count {} exceeds u32::MAX",
397+
self.completed.len()
398+
))
399+
})?;
400+
362401
let view = ByteView {
363402
length,
364-
prefix: u32::from_le_bytes(v[0..4].try_into().unwrap()),
365-
buffer_index: self.completed.len() as u32,
403+
prefix,
404+
buffer_index,
366405
offset,
367406
};
368407
self.views_buffer.push(view.into());
369408
self.null_buffer_builder.append_non_null();
409+
410+
Ok(())
370411
}
371412

372413
/// Append an `Option` value into the builder

0 commit comments

Comments
 (0)