(views: &[u128], buffers: &[Buffer], f: F)
| 162 | } |
| 163 | |
| 164 | fn validate_view_impl<F>(views: &[u128], buffers: &[Buffer], f: F) -> Result<(), ArrowError> |
| 165 | where |
| 166 | F: Fn(usize, &[u8]) -> Result<(), ArrowError>, |
| 167 | { |
| 168 | for (idx, v) in views.iter().enumerate() { |
| 169 | let len = *v as u32; |
| 170 | if len <= MAX_INLINE_VIEW_LEN { |
| 171 | if len < MAX_INLINE_VIEW_LEN && (v >> (32 + len * 8)) != 0 { |
| 172 | return Err(ArrowError::InvalidArgumentError(format!( |
| 173 | "View at index {idx} contained non-zero padding for string of length {len}", |
| 174 | ))); |
| 175 | } |
| 176 | f(idx, &v.to_le_bytes()[4..4 + len as usize])?; |
| 177 | } else { |
| 178 | let view = ByteView::from(*v); |
| 179 | let data = buffers.get(view.buffer_index as usize).ok_or_else(|| { |
| 180 | ArrowError::InvalidArgumentError(format!( |
| 181 | "Invalid buffer index at {idx}: got index {} but only has {} buffers", |
| 182 | view.buffer_index, |
| 183 | buffers.len() |
| 184 | )) |
| 185 | })?; |
| 186 | |
| 187 | let start = view.offset as usize; |
| 188 | let end = start + len as usize; |
| 189 | let b = data.get(start..end).ok_or_else(|| { |
| 190 | ArrowError::InvalidArgumentError(format!( |
| 191 | "Invalid buffer slice at {idx}: got {start}..{end} but buffer {} has length {}", |
| 192 | view.buffer_index, |
| 193 | data.len() |
| 194 | )) |
| 195 | })?; |
| 196 | |
| 197 | if !b.starts_with(&view.prefix.to_le_bytes()) { |
| 198 | return Err(ArrowError::InvalidArgumentError( |
| 199 | "Mismatch between embedded prefix and data".to_string(), |
| 200 | )); |
| 201 | } |
| 202 | |
| 203 | f(idx, b)?; |
| 204 | } |
| 205 | } |
| 206 | Ok(()) |
| 207 | } |
no test coverage detected