Skip to main content

fory_core/row/
reader.rs

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,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use std::collections::BTreeMap;
19use std::marker::PhantomData;
20
21use crate::error::Error;
22
23use super::bit_util::{bitmap_width, is_bit_set, round_up_to_word, slot_width};
24use super::row::{Row, RowValue};
25
26/// Backing-byte access shared by immutable Standard Row Format views.
27pub trait RowView<'a> {
28    /// Returns the complete encoded bytes bound to this view.
29    fn as_bytes(&self) -> &'a [u8];
30
31    /// Returns the number of encoded bytes bound to this view.
32    #[inline]
33    fn encoded_len(&self) -> usize {
34        self.as_bytes().len()
35    }
36}
37
38/// A zero-copy view over one Standard Row Format struct.
39///
40/// This type is public only because `ForyRow` views are generated in
41/// downstream crates.
42#[doc(hidden)]
43#[derive(Clone, Copy)]
44pub struct StructView<'a> {
45    bytes: &'a [u8],
46    bitmap_width: usize,
47    num_fields: usize,
48    fixed_end: usize,
49}
50
51impl<'a> StructView<'a> {
52    /// Validates the fixed region for a struct with `num_fields` fields.
53    pub fn new(bytes: &'a [u8], num_fields: usize) -> Result<Self, Error> {
54        let bitmap_width = bitmap_width(num_fields)?;
55        let slots_size = num_fields
56            .checked_mul(8)
57            .ok_or_else(|| Error::invalid_data("row fixed region size overflow"))?;
58        let fixed_end = bitmap_width
59            .checked_add(slots_size)
60            .ok_or_else(|| Error::invalid_data("row fixed region size overflow"))?;
61        ensure_range(bytes, 0, fixed_end)?;
62        Ok(Self {
63            bytes,
64            bitmap_width,
65            num_fields,
66            fixed_end,
67        })
68    }
69
70    /// Reads a field at its schema ordinal.
71    pub fn get<T: RowValue>(&self, index: usize) -> Result<T::View<'a>, Error> {
72        self.check_index(index)?;
73        let bitmap = &self.bytes[..self.bitmap_width];
74        if is_bit_set(bitmap, index) {
75            return T::read_null();
76        }
77
78        let slot_offset = self
79            .bitmap_width
80            .checked_add(index * 8)
81            .ok_or_else(|| Error::invalid_data("row field offset overflow"))?;
82        let value = match T::FIXED_SIZE {
83            Some(width) => {
84                slot_width(Some(width))?;
85                checked_slice(self.bytes, slot_offset, width)?
86            }
87            None => variable_slice(self.bytes, slot_offset, self.fixed_end)?,
88        };
89        T::read(value)
90    }
91
92    /// Returns whether a field's null bit is set.
93    pub fn is_null(&self, index: usize) -> Result<bool, Error> {
94        self.check_index(index)?;
95        Ok(is_bit_set(&self.bytes[..self.bitmap_width], index))
96    }
97
98    fn check_index(&self, index: usize) -> Result<(), Error> {
99        if index >= self.num_fields {
100            Err(Error::buffer_out_of_bound(index, 1, self.num_fields))
101        } else {
102            Ok(())
103        }
104    }
105}
106
107impl<'a> RowView<'a> for StructView<'a> {
108    #[inline]
109    fn as_bytes(&self) -> &'a [u8] {
110        self.bytes
111    }
112}
113
114/// A zero-copy view over one Standard Row Format array.
115pub struct ArrayView<'a, T: RowValue> {
116    bytes: &'a [u8],
117    num_elements: usize,
118    bitmap_width: usize,
119    header_size: usize,
120    element_size: usize,
121    fixed_end: usize,
122    marker: PhantomData<T>,
123}
124
125impl<T: RowValue> Copy for ArrayView<'_, T> {}
126
127impl<T: RowValue> Clone for ArrayView<'_, T> {
128    fn clone(&self) -> Self {
129        *self
130    }
131}
132
133impl<'a, T: RowValue> ArrayView<'a, T> {
134    pub(crate) fn new(bytes: &'a [u8]) -> Result<Self, Error> {
135        let count = read_u64(bytes, 0)?;
136        let num_elements = usize::try_from(count)
137            .map_err(|_| Error::invalid_data("row array element count exceeds usize"))?;
138        let bitmap_width = bitmap_width(num_elements)?;
139        let header_size = 8usize
140            .checked_add(bitmap_width)
141            .ok_or_else(|| Error::invalid_data("row array header size overflow"))?;
142        let element_size = slot_width(T::FIXED_SIZE)?;
143        let element_bytes = num_elements
144            .checked_mul(element_size)
145            .ok_or_else(|| Error::invalid_data("row array fixed region size overflow"))?;
146        let aligned_element_bytes = round_up_to_word(element_bytes)?;
147        let fixed_end = header_size
148            .checked_add(aligned_element_bytes)
149            .ok_or_else(|| Error::invalid_data("row array fixed region size overflow"))?;
150        ensure_range(bytes, 0, fixed_end)?;
151        Ok(Self {
152            bytes,
153            num_elements,
154            bitmap_width,
155            header_size,
156            element_size,
157            fixed_end,
158            marker: PhantomData,
159        })
160    }
161
162    /// Returns the number of elements encoded in this array.
163    pub fn len(&self) -> usize {
164        self.num_elements
165    }
166
167    /// Returns true when this array contains no elements.
168    pub fn is_empty(&self) -> bool {
169        self.num_elements == 0
170    }
171
172    /// Returns an iterator that reads elements on demand.
173    pub fn iter(&self) -> ArrayIter<'_, 'a, T> {
174        ArrayIter {
175            view: self,
176            index: 0,
177        }
178    }
179
180    /// Reads one array element without materializing the rest of the array.
181    pub fn get(&self, index: usize) -> Result<T::View<'a>, Error> {
182        self.check_index(index)?;
183        let bitmap = &self.bytes[8..8 + self.bitmap_width];
184        if is_bit_set(bitmap, index) {
185            return T::read_null();
186        }
187        let slot_offset = self
188            .header_size
189            .checked_add(index * self.element_size)
190            .ok_or_else(|| Error::invalid_data("row array element offset overflow"))?;
191        let value = match T::FIXED_SIZE {
192            Some(width) => checked_slice(self.bytes, slot_offset, width)?,
193            None => variable_slice(self.bytes, slot_offset, self.fixed_end)?,
194        };
195        T::read(value)
196    }
197
198    /// Returns whether an element's null bit is set.
199    pub fn is_null(&self, index: usize) -> Result<bool, Error> {
200        self.check_index(index)?;
201        let bitmap_start = 8;
202        let bitmap = &self.bytes[bitmap_start..bitmap_start + self.bitmap_width];
203        Ok(is_bit_set(bitmap, index))
204    }
205
206    fn check_index(&self, index: usize) -> Result<(), Error> {
207        if index >= self.num_elements {
208            Err(Error::buffer_out_of_bound(index, 1, self.num_elements))
209        } else {
210            Ok(())
211        }
212    }
213}
214
215impl<'a, T: RowValue> RowView<'a> for ArrayView<'a, T> {
216    #[inline]
217    fn as_bytes(&self) -> &'a [u8] {
218        self.bytes
219    }
220}
221
222/// An iterator over the elements of an [`ArrayView`].
223pub struct ArrayIter<'view, 'row, T: RowValue> {
224    view: &'view ArrayView<'row, T>,
225    index: usize,
226}
227
228impl<'row, T: RowValue> Iterator for ArrayIter<'_, 'row, T> {
229    type Item = Result<T::View<'row>, Error>;
230
231    fn next(&mut self) -> Option<Self::Item> {
232        if self.index == self.view.len() {
233            return None;
234        }
235        let index = self.index;
236        self.index += 1;
237        Some(self.view.get(index))
238    }
239
240    fn size_hint(&self) -> (usize, Option<usize>) {
241        let remaining = self.view.len() - self.index;
242        (remaining, Some(remaining))
243    }
244}
245
246impl<T: RowValue> ExactSizeIterator for ArrayIter<'_, '_, T> {}
247
248impl<'view, 'row, T: RowValue> IntoIterator for &'view ArrayView<'row, T> {
249    type Item = Result<T::View<'row>, Error>;
250    type IntoIter = ArrayIter<'view, 'row, T>;
251
252    fn into_iter(self) -> Self::IntoIter {
253        self.iter()
254    }
255}
256
257/// A zero-copy view over one Standard Row Format map.
258pub struct MapView<'a, K: RowValue, V: RowValue> {
259    bytes: &'a [u8],
260    keys: ArrayView<'a, K>,
261    values: ArrayView<'a, V>,
262}
263
264impl<K: RowValue, V: RowValue> Copy for MapView<'_, K, V> {}
265
266impl<K: RowValue, V: RowValue> Clone for MapView<'_, K, V> {
267    fn clone(&self) -> Self {
268        *self
269    }
270}
271
272impl<'a, K: RowValue, V: RowValue> MapView<'a, K, V> {
273    pub(crate) fn new(bytes: &'a [u8]) -> Result<Self, Error> {
274        let keys_size = read_u64(bytes, 0)?;
275        let keys_size = usize::try_from(keys_size)
276            .map_err(|_| Error::invalid_data("row map key array size exceeds usize"))?;
277        let keys_end = 8usize
278            .checked_add(keys_size)
279            .ok_or_else(|| Error::invalid_data("row map key array size overflow"))?;
280        ensure_range(bytes, 8, keys_size)?;
281        let keys = ArrayView::<K>::new(&bytes[8..keys_end])?;
282        let values = ArrayView::<V>::new(&bytes[keys_end..])?;
283        if keys.len() != values.len() {
284            return Err(Error::invalid_data(
285                "row map key and value arrays have different lengths",
286            ));
287        }
288        Ok(Self {
289            bytes,
290            keys,
291            values,
292        })
293    }
294
295    /// Returns the number of key-value pairs encoded in this map.
296    pub fn len(&self) -> usize {
297        self.keys.len()
298    }
299
300    /// Returns true when this map contains no key-value pairs.
301    pub fn is_empty(&self) -> bool {
302        self.keys.is_empty()
303    }
304
305    /// Reads the key at `index` without materializing the map.
306    pub fn key(&self, index: usize) -> Result<K::View<'a>, Error> {
307        self.keys.get(index)
308    }
309
310    /// Reads the value at `index` without materializing the map.
311    pub fn value(&self, index: usize) -> Result<V::View<'a>, Error> {
312        self.values.get(index)
313    }
314
315    /// Returns the map's key array.
316    pub fn keys(&self) -> &ArrayView<'a, K> {
317        &self.keys
318    }
319
320    /// Returns the map's value array.
321    pub fn values(&self) -> &ArrayView<'a, V> {
322        &self.values
323    }
324
325    /// Materializes this view as a `BTreeMap`.
326    pub fn to_btree_map(
327        &self,
328    ) -> Result<BTreeMap<<K as RowValue>::View<'a>, <V as RowValue>::View<'a>>, Error>
329    where
330        <K as RowValue>::View<'a>: Ord,
331    {
332        let mut map = BTreeMap::new();
333        for index in 0..self.keys.len() {
334            map.insert(self.keys.get(index)?, self.values.get(index)?);
335        }
336        Ok(map)
337    }
338}
339
340impl<'a, K: RowValue, V: RowValue> RowView<'a> for MapView<'a, K, V> {
341    #[inline]
342    fn as_bytes(&self) -> &'a [u8] {
343        self.bytes
344    }
345}
346
347fn variable_slice(bytes: &[u8], slot_offset: usize, fixed_end: usize) -> Result<&[u8], Error> {
348    let offset_and_size = read_u64(bytes, slot_offset)?;
349    let relative_offset = usize::try_from(offset_and_size >> 32)
350        .map_err(|_| Error::invalid_data("row variable offset exceeds usize"))?;
351    let size = (offset_and_size as u32) as usize;
352    if relative_offset < fixed_end {
353        return Err(Error::invalid_data(
354            "row variable value overlaps the fixed region",
355        ));
356    }
357    checked_slice(bytes, relative_offset, size)
358}
359
360fn read_u64(bytes: &[u8], offset: usize) -> Result<u64, Error> {
361    let value = checked_slice(bytes, offset, 8)?;
362    let mut array = [0u8; 8];
363    array.copy_from_slice(value);
364    Ok(u64::from_le_bytes(array))
365}
366
367fn checked_slice(bytes: &[u8], offset: usize, size: usize) -> Result<&[u8], Error> {
368    let end = offset
369        .checked_add(size)
370        .ok_or_else(|| Error::buffer_out_of_bound(offset, size, bytes.len()))?;
371    if end > bytes.len() {
372        Err(Error::buffer_out_of_bound(offset, size, bytes.len()))
373    } else {
374        Ok(&bytes[offset..end])
375    }
376}
377
378fn ensure_range(bytes: &[u8], offset: usize, size: usize) -> Result<(), Error> {
379    checked_slice(bytes, offset, size).map(|_| ())
380}
381
382/// Decodes a Standard Row Format struct, array, or map root.
383pub fn from_row<T: Row>(bytes: &[u8]) -> Result<T::View<'_>, Error> {
384    T::read(bytes)
385}