1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
mod attributes;
mod bounds;
mod position;
mod strand;

pub(crate) use self::bounds::Bounds;
use self::{attributes::Attributes, position::Position, strand::Strand};

const MISSING: &str = ".";

/// An immutable, lazily-evalulated GFF record.
pub struct Record {
    pub(crate) buf: String,
    pub(crate) bounds: Bounds,
}

impl Record {
    /// Returns the reference sequence name.
    pub fn reference_sequence_name(&self) -> &str {
        &self.buf[self.bounds.reference_sequence_name_range()]
    }

    /// Returns the source.
    pub fn source(&self) -> &str {
        &self.buf[self.bounds.source_range()]
    }

    /// Returns the feature type.
    pub fn ty(&self) -> &str {
        &self.buf[self.bounds.type_range()]
    }

    /// Returns the start position.
    pub fn start(&self) -> Position<'_> {
        let buf = &self.buf[self.bounds.start_range()];
        Position::new(buf)
    }

    /// Returns the end position.
    pub fn end(&self) -> Position<'_> {
        let buf = &self.buf[self.bounds.end_range()];
        Position::new(buf)
    }

    /// Returns the score.
    pub fn score(&self) -> &str {
        &self.buf[self.bounds.score_range()]
    }

    /// Returns the strand.
    pub fn strand(&self) -> Strand<'_> {
        let buf = &self.buf[self.bounds.strand_range()];
        Strand::new(buf)
    }

    /// Returns the phase.
    pub fn phase(&self) -> &str {
        &self.buf[self.bounds.phase_range()]
    }

    /// Returns the attributes.
    pub fn attributes(&self) -> Attributes<'_> {
        match &self.buf[self.bounds.attributes_range()] {
            MISSING => Attributes::new(""),
            buf => Attributes::new(buf),
        }
    }
}

impl From<Record> for String {
    fn from(record: Record) -> Self {
        record.buf
    }
}