noodles-bed 0.34.0

BED (Browser Extensible Data) reader and writer
Documentation
use std::ops::Range;

#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) struct Bounds<const N: usize> {
    pub(crate) standard_fields_ends: [usize; N],
    pub(crate) other_fields_ends: Vec<usize>,
}

impl<const N: usize> Bounds<N> {
    pub fn get(&self, i: usize) -> Option<Range<usize>> {
        let end = self.other_fields_ends.get(i).copied()?;

        let start = i
            .checked_sub(1)
            .and_then(|prev_i| self.other_fields_ends.get(prev_i).copied())
            .unwrap_or(self.standard_fields_ends[N - 1]);

        Some(start..end)
    }
}

impl Bounds<3> {
    pub fn reference_sequence_name_range(&self) -> Range<usize> {
        0..self.standard_fields_ends[0]
    }

    pub fn feature_start_range(&self) -> Range<usize> {
        self.standard_fields_ends[0]..self.standard_fields_ends[1]
    }

    pub fn feature_end_range(&self) -> Range<usize> {
        self.standard_fields_ends[1]..self.standard_fields_ends[2]
    }
}

impl Bounds<4> {
    pub fn reference_sequence_name_range(&self) -> Range<usize> {
        0..self.standard_fields_ends[0]
    }

    pub fn feature_start_range(&self) -> Range<usize> {
        self.standard_fields_ends[0]..self.standard_fields_ends[1]
    }

    pub fn feature_end_range(&self) -> Range<usize> {
        self.standard_fields_ends[1]..self.standard_fields_ends[2]
    }

    pub fn name_range(&self) -> Range<usize> {
        self.standard_fields_ends[2]..self.standard_fields_ends[3]
    }
}

impl Bounds<5> {
    pub fn reference_sequence_name_range(&self) -> Range<usize> {
        0..self.standard_fields_ends[0]
    }

    pub fn feature_start_range(&self) -> Range<usize> {
        self.standard_fields_ends[0]..self.standard_fields_ends[1]
    }

    pub fn feature_end_range(&self) -> Range<usize> {
        self.standard_fields_ends[1]..self.standard_fields_ends[2]
    }

    pub fn name_range(&self) -> Range<usize> {
        self.standard_fields_ends[2]..self.standard_fields_ends[3]
    }

    pub fn score_range(&self) -> Range<usize> {
        self.standard_fields_ends[3]..self.standard_fields_ends[4]
    }
}

impl Bounds<6> {
    pub fn reference_sequence_name_range(&self) -> Range<usize> {
        0..self.standard_fields_ends[0]
    }

    pub fn feature_start_range(&self) -> Range<usize> {
        self.standard_fields_ends[0]..self.standard_fields_ends[1]
    }

    pub fn feature_end_range(&self) -> Range<usize> {
        self.standard_fields_ends[1]..self.standard_fields_ends[2]
    }

    pub fn name_range(&self) -> Range<usize> {
        self.standard_fields_ends[2]..self.standard_fields_ends[3]
    }

    pub fn score_range(&self) -> Range<usize> {
        self.standard_fields_ends[3]..self.standard_fields_ends[4]
    }

    pub fn strand_range(&self) -> Range<usize> {
        self.standard_fields_ends[4]..self.standard_fields_ends[5]
    }
}

impl Default for Bounds<3> {
    fn default() -> Self {
        Self {
            standard_fields_ends: [3, 4, 5],
            other_fields_ends: Vec::new(),
        }
    }
}

impl Default for Bounds<4> {
    fn default() -> Self {
        Self {
            standard_fields_ends: [3, 4, 5, 6],
            other_fields_ends: Vec::new(),
        }
    }
}

impl Default for Bounds<5> {
    fn default() -> Self {
        Self {
            standard_fields_ends: [3, 4, 5, 6, 7],
            other_fields_ends: Vec::new(),
        }
    }
}

impl Default for Bounds<6> {
    fn default() -> Self {
        Self {
            standard_fields_ends: [3, 4, 5, 6, 7, 8],
            other_fields_ends: Vec::new(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_ranges() {
        let bounds = Bounds::<3>::default();
        assert_eq!(bounds.reference_sequence_name_range(), 0..3);
        assert_eq!(bounds.feature_start_range(), 3..4);
        assert_eq!(bounds.feature_end_range(), 4..5);
    }

    #[test]
    fn test_get() {
        let mut bounds = Bounds::<3>::default();

        assert!(bounds.get(0).is_none());

        bounds.other_fields_ends.push(6);
        bounds.other_fields_ends.push(7);

        assert_eq!(bounds.get(0), Some(5..6));
        assert_eq!(bounds.get(1), Some(6..7));
        assert!(bounds.get(2).is_none());
    }
}