parquet/arrow/buffer/
view_buffer.rs1use crate::arrow::record_reader::buffer::ValuesBuffer;
19use crate::errors::Result;
20use arrow_array::{ArrayRef, BinaryViewArray, StringViewArray};
21use arrow_buffer::{Buffer, NullBuffer, ScalarBuffer};
22use arrow_schema::DataType as ArrowType;
23use std::sync::Arc;
24
25#[derive(Debug, Default)]
31pub struct ViewBuffer {
32 pub views: Vec<u128>,
33 pub buffers: Vec<Buffer>,
34}
35
36impl ViewBuffer {
37 pub fn with_capacity(capacity: usize) -> Self {
39 Self {
40 views: Vec::with_capacity(capacity),
41 buffers: Vec::new(),
42 }
43 }
44
45 pub fn is_empty(&self) -> bool {
46 self.views.is_empty()
47 }
48
49 pub fn append_block(&mut self, block: Buffer) -> u32 {
50 let block_id = self.buffers.len() as u32;
51 self.buffers.push(block);
52 block_id
53 }
54
55 pub fn into_array(self, null_buffer: Option<Buffer>, data_type: &ArrowType) -> ArrayRef {
57 let len = self.views.len();
58 let views = ScalarBuffer::from(self.views);
59 let nulls = null_buffer.and_then(|b| NullBuffer::from_unsliced_buffer(b, len));
60 match data_type {
61 ArrowType::Utf8View => {
62 unsafe { Arc::new(StringViewArray::new_unchecked(views, self.buffers, nulls)) }
64 }
65 ArrowType::BinaryView => {
66 unsafe { Arc::new(BinaryViewArray::new_unchecked(views, self.buffers, nulls)) }
68 }
69 _ => panic!("Unsupported data type: {data_type}"),
70 }
71 }
72}
73
74impl ValuesBuffer for ViewBuffer {
75 fn with_capacity(capacity: usize) -> Self {
76 Self::with_capacity(capacity)
77 }
78
79 fn reserve_exact(&mut self, additional: usize) {
80 self.views.reserve_exact(additional);
81 }
82
83 fn pad_nulls(
84 &mut self,
85 read_offset: usize,
86 values_read: usize,
87 levels_read: usize,
88 valid_mask: &[u8],
89 ) -> Result<()> {
90 self.views
91 .pad_nulls(read_offset, values_read, levels_read, valid_mask)
92 }
93}
94
95#[cfg(test)]
96mod tests {
97
98 use arrow::array::make_view;
99 use arrow_array::Array;
100
101 use super::*;
102
103 #[test]
104 fn test_view_buffer_empty() {
105 let buffer = ViewBuffer::with_capacity(0);
106 let array = buffer.into_array(None, &ArrowType::Utf8View);
107 let strings = array
108 .as_any()
109 .downcast_ref::<arrow::array::StringViewArray>()
110 .unwrap();
111 assert_eq!(strings.len(), 0);
112 }
113
114 #[test]
115 fn test_view_buffer_append_view() {
116 let mut buffer = ViewBuffer::with_capacity(0);
117 let data = b"0123456789long string to test string view";
118 let string_buffer = Buffer::from(data);
119 let block_id = buffer.append_block(string_buffer);
120
121 buffer.views.push(make_view(&data[0..1], block_id, 0));
122 buffer.views.push(make_view(&data[1..10], block_id, 1));
123 buffer.views.push(make_view(&data[10..41], block_id, 10));
124
125 let array = buffer.into_array(None, &ArrowType::Utf8View);
126 let string_array = array
127 .as_any()
128 .downcast_ref::<arrow::array::StringViewArray>()
129 .unwrap();
130 assert_eq!(
131 string_array.iter().collect::<Vec<_>>(),
132 vec![
133 Some("0"),
134 Some("123456789"),
135 Some("long string to test string view"),
136 ]
137 );
138 }
139
140 #[test]
141 fn test_view_buffer_pad_null() {
142 let mut buffer = ViewBuffer::with_capacity(0);
143 let data = b"0123456789long string to test string view";
144 let string_buffer = Buffer::from(data);
145 let block_id = buffer.append_block(string_buffer);
146
147 buffer.views.push(make_view(&data[0..1], block_id, 0));
148 buffer.views.push(make_view(&data[1..10], block_id, 1));
149 buffer.views.push(make_view(&data[10..41], block_id, 10));
150
151 let valid = [true, false, false, true, false, false, true];
152 let valid_mask = Buffer::from_iter(valid.iter().copied());
153
154 buffer
155 .pad_nulls(1, 2, valid.len() - 1, valid_mask.as_slice())
156 .unwrap();
157
158 let array = buffer.into_array(Some(valid_mask), &ArrowType::Utf8View);
159 let strings = array
160 .as_any()
161 .downcast_ref::<arrow::array::StringViewArray>()
162 .unwrap();
163
164 assert_eq!(
165 strings.iter().collect::<Vec<_>>(),
166 vec![
167 Some("0"),
168 None,
169 None,
170 Some("123456789"),
171 None,
172 None,
173 Some("long string to test string view"),
174 ]
175 );
176 }
177}