vortex_file/footer/
segment.rs1use std::ops::Range;
5
6use vortex_buffer::Alignment;
7use vortex_error::VortexError;
8
9use crate::flatbuffers::footer as fb;
10
11#[derive(Clone, Copy, Debug)]
16pub struct SegmentSpec {
17 pub offset: u64,
19 pub length: u32,
21 pub alignment: Alignment,
23}
24
25impl SegmentSpec {
26 pub fn byte_range(&self) -> Range<u64> {
30 self.offset..self.offset + u64::from(self.length)
31 }
32}
33
34impl From<&SegmentSpec> for fb::SegmentSpec {
35 fn from(value: &SegmentSpec) -> Self {
36 fb::SegmentSpec::new(value.offset, value.length, value.alignment.exponent(), 0, 0)
37 }
38}
39
40impl TryFrom<&fb::SegmentSpec> for SegmentSpec {
41 type Error = VortexError;
42
43 fn try_from(value: &fb::SegmentSpec) -> Result<Self, Self::Error> {
44 Ok(Self {
45 offset: value.offset(),
46 length: value.length(),
47 alignment: Alignment::try_from_untrusted_exponent(value.alignment_exponent())?,
50 })
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn rejects_out_of_range_alignment_exponent() {
60 let fb_spec = fb::SegmentSpec::new(0, 0, u8::MAX, 0, 0);
63 let err = SegmentSpec::try_from(&fb_spec).unwrap_err();
64 assert!(err.to_string().contains("too large"), "{err}");
65 }
66
67 #[test]
68 fn rejects_excessive_alignment_exponent() {
69 let fb_spec = fb::SegmentSpec::new(0, 0, 17, 0, 0);
72 let err = SegmentSpec::try_from(&fb_spec).unwrap_err();
73 assert!(err.to_string().contains("exceeds"), "{err}");
74 }
75}