Assuming ParquetDecimal is actually Decimal from the parquet crate, the .data() returns a slice that can be of any length. Whereas i128::from_be_bytes requires a [u8; 16]. There's no reason to assume the bytes.try_into() call will succeed in most cases. You will need to check and pad or trim the slice to 16 elements before attempting the conversion.
It's more annoying than that, even, since you're working with signed numbers.
fn from_be_slice(be: &[u8]) -> Option<i128> {
// Doesn't attempt conversion of slices larger than an `i128`
16_usize.checked_sub(be.len()).map(|slop| {
// Check high bit to see if we're negative or non-negative
let mut bytes = match be {
[byte, ..] if *byte >= 0x80 => [0xff; 16],
_ => [0; 16],
};
// overwrite the lower `be.len()` bytes and convert
bytes[slop..].copy_from_slice(be);
i128::from_be_bytes(bytes)
})
}
N.b. I'm not familiar with the crates and the snippet above assumes plain ol' 2's complement integer data.
It's the try_from ... unwrap that panics at runtime, not from_?e_bytes. Slices have dynamic length.
For anyone interested, this is how I did the padding.
let bytes: &[u8] = parquet_decimal.data();
// We need to convert the slice to an array of 16 bytes - it may need to be padded or truncated
let array: [u8; 16] = bytes
.iter()
.cloned()
.chain(std::iter::repeat(0).take(16))
.take(16)
.collect::<Vec<u8>>()
.try_into()
.unwrap();