grass_runtime/record/
bed6.rs1use 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> {}