grass_runtime/record/
bed6.rs

1use std::{
2    fmt::Display,
3    io::{Result, Write},
4    ops::{Deref, DerefMut},
5    str::FromStr,
6};
7
8use crate::{
9    property::{Named, Parsable, RegionCore, Scored, Serializable, Strand, Stranded, Tagged},
10    ChrRef,
11};
12
13use super::{Bed5, RcCowString, ToSelfContained};
14
15#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
16pub struct Bed6<'a, T = f64> {
17    inner: Bed5<'a, T>,
18    pub strand: Strand,
19}
20
21impl<'a, T> Deref for Bed6<'a, T> {
22    type Target = Bed5<'a, T>;
23
24    fn deref(&self) -> &Self::Target {
25        &self.inner
26    }
27}
28
29impl<'a> DerefMut for Bed6<'a> {
30    fn deref_mut(&mut self) -> &mut Self::Target {
31        &mut self.inner
32    }
33}
34
35impl<'a, T: Display> Serializable for Bed6<'a, T> {
36    fn dump<W: Write>(&self, mut fp: W) -> Result<()> {
37        self.inner.dump(&mut fp)?;
38        write!(fp, "\t{}", self.strand)?;
39        Ok(())
40    }
41}
42
43impl<'a, T: Display> Serializable for Option<Bed6<'a, T>> {
44    fn dump<W: Write>(&self, mut fp: W) -> Result<()> {
45        if let Some(inner) = self {
46            inner.dump(fp)
47        } else {
48            fp.write_all(b".\t.\t.\t.\t.\t.")
49        }
50    }
51}
52
53impl<'a, T: FromStr> Parsable<'a> for Bed6<'a, T> {
54    fn parse(s: &'a str) -> Option<(Self, usize)> {
55        let (inner, mut start) = Bed5::parse(s)?;
56        if s[start..].starts_with('\t') {
57            start += 1;
58        }
59        let s = &s[start..];
60        let brk = memchr::memchr(b'\t', s.as_bytes()).unwrap_or(s.len());
61        let strand = match &s[..brk] {
62            "+" => Strand::Positive,
63            "-" => Strand::Negative,
64            _ => Strand::Unknown,
65        };
66
67        Some((Self { inner, strand }, start + brk))
68    }
69}
70
71impl<'a, S> Bed6<'a, S> {
72    pub fn new<T: RegionCore + Named<'a> + Scored<S> + Stranded>(region: &T) -> Self
73    where
74        S: Default,
75    {
76        let inner = Bed5::new(region);
77        let strand = region.strand();
78        Self { inner, strand }
79    }
80
81    #[inline(always)]
82    pub fn set_strand(&mut self, strand: &str) {
83        match strand {
84            "+" => self.strand = Strand::Positive,
85            "-" => self.strand = Strand::Negative,
86            _ => self.strand = Strand::Unknown,
87        }
88    }
89}
90
91impl<'a, S> RegionCore for Bed6<'a, S> {
92    #[inline(always)]
93    fn start(&self) -> u32 {
94        self.inner.start()
95    }
96    #[inline(always)]
97    fn end(&self) -> u32 {
98        self.inner.end()
99    }
100    #[inline(always)]
101    fn chrom(&self) -> ChrRef<'static> {
102        self.inner.chrom()
103    }
104}
105
106impl<'a, T: Clone> Scored<T> for Bed6<'a, T> {
107    #[inline(always)]
108    fn score(&self) -> Option<T> {
109        self.inner.score()
110    }
111}
112
113impl<'a, T> Stranded for Bed6<'a, T> {
114    fn strand(&self) -> Strand {
115        self.strand
116    }
117}
118
119impl<'a, T> Named<'a> for Bed6<'a, T> {
120    fn name(&self) -> &str {
121        self.inner.name()
122    }
123    fn to_cow(&self) -> RcCowString<'a> {
124        self.inner.to_cow()
125    }
126}
127
128impl<'a> ToSelfContained for Bed6<'a> {
129    type SelfContained = Bed6<'static>;
130    fn to_self_contained(&self) -> Self::SelfContained {
131        Bed6 {
132            inner: self.inner.to_self_contained(),
133            strand: self.strand,
134        }
135    }
136}
137
138impl<'a, T: Clone> Tagged<T> for Bed6<'a> {}