use std::ops::Range;
use vortex_buffer::Alignment;
use vortex_error::VortexError;
use crate::flatbuffers::footer as fb;
#[derive(Clone, Copy, Debug)]
pub struct SegmentSpec {
pub offset: u64,
pub length: u32,
pub alignment: Alignment,
}
impl SegmentSpec {
pub fn byte_range(&self) -> Range<u64> {
self.offset..self.offset + u64::from(self.length)
}
}
impl From<&SegmentSpec> for fb::SegmentSpec {
fn from(value: &SegmentSpec) -> Self {
fb::SegmentSpec::new(value.offset, value.length, value.alignment.exponent(), 0, 0)
}
}
impl TryFrom<&fb::SegmentSpec> for SegmentSpec {
type Error = VortexError;
fn try_from(value: &fb::SegmentSpec) -> Result<Self, Self::Error> {
Ok(Self {
offset: value.offset(),
length: value.length(),
alignment: Alignment::try_from_untrusted_exponent(value.alignment_exponent())?,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rejects_out_of_range_alignment_exponent() {
let fb_spec = fb::SegmentSpec::new(0, 0, u8::MAX, 0, 0);
let err = SegmentSpec::try_from(&fb_spec).unwrap_err();
assert!(err.to_string().contains("too large"), "{err}");
}
#[test]
fn rejects_excessive_alignment_exponent() {
let fb_spec = fb::SegmentSpec::new(0, 0, 17, 0, 0);
let err = SegmentSpec::try_from(&fb_spec).unwrap_err();
assert!(err.to_string().contains("exceeds"), "{err}");
}
}