grass_runtime/record/
bed4.rs1use std::io::{Result, Write};
2use std::ops::{Deref, DerefMut};
3use std::rc::Rc;
4
5use crate::property::Tagged;
6use crate::{
7 property::{Named, Parsable, RegionCore, Scored, Serializable, Stranded},
8 ChrRef,
9};
10
11use super::{Bed3, ToSelfContained};
12
13#[derive(Clone)]
14pub enum RcCowString<'a> {
15 Borrowed(&'a str),
16 RcOwned(Rc<String>),
17}
18
19impl<'a> Deref for RcCowString<'a> {
20 type Target = str;
21
22 fn deref(&self) -> &Self::Target {
23 match self {
24 RcCowString::Borrowed(val) => val,
25 RcCowString::RcOwned(rc_val) => rc_val.as_str(),
26 }
27 }
28}
29
30impl<'a> PartialEq for RcCowString<'a> {
31 fn eq(&self, other: &Self) -> bool {
32 str::eq(self.deref(), other.deref())
33 }
34}
35
36impl<'a> PartialOrd for RcCowString<'a> {
37 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
38 str::partial_cmp(self.as_ref(), other.as_ref())
39 }
40}
41
42impl<'a> Eq for RcCowString<'a> {}
43
44impl<'a> Ord for RcCowString<'a> {
45 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
46 self.deref().cmp(other)
47 }
48}
49
50#[derive(Clone, PartialEq, PartialOrd, Eq, Ord)]
51pub struct Bed4<'a> {
52 inner: Bed3,
53 pub name: RcCowString<'a>,
54}
55
56impl<'a> Deref for Bed4<'a> {
57 type Target = Bed3;
58
59 fn deref(&self) -> &Self::Target {
60 &self.inner
61 }
62}
63
64impl<'a> DerefMut for Bed4<'a> {
65 fn deref_mut(&mut self) -> &mut Self::Target {
66 &mut self.inner
67 }
68}
69
70impl<'a> Serializable for Bed4<'a> {
71 fn dump<W: Write>(&self, mut fp: W) -> Result<()> {
72 self.inner.dump(&mut fp)?;
73 write!(fp, "\t{}", self.name.deref())?;
74 Ok(())
75 }
76}
77
78impl<'a> Serializable for Option<Bed4<'a>> {
79 fn dump<W: Write>(&self, mut fp: W) -> Result<()> {
80 if let Some(inner) = self {
81 inner.dump(fp)
82 } else {
83 fp.write_all(b".\t.\t.\t.")
84 }
85 }
86}
87
88impl<'a> Parsable<'a> for Bed4<'a> {
89 fn parse(s: &'a str) -> Option<(Self, usize)> {
90 let (inner, mut start) = Bed3::parse(s)?;
91 if s[start..].starts_with('\t') {
92 start += 1;
93 }
94 let s = &s[start..];
95 let brk = memchr::memchr(b'\t', s.as_bytes()).unwrap_or(s.len());
96 let name = RcCowString::Borrowed(&s[..brk]);
97 Some((Self { inner, name }, start + brk))
98 }
99}
100
101impl<'a> Bed4<'a> {
102 pub fn new<T: RegionCore + Named<'a>>(region: &T) -> Self {
103 let name = region.to_cow();
104 let inner = Bed3::new(®ion);
105 Self { inner, name }
106 }
107
108 #[inline(always)]
109 pub fn set_name(&mut self, name: &'a str) {
110 self.name = RcCowString::Borrowed(name);
111 }
112
113 pub fn get_self_contained_name(&self) -> RcCowString<'static> {
114 match &self.name {
115 RcCowString::Borrowed(name) => RcCowString::RcOwned(Rc::new(name.to_string())),
116 RcCowString::RcOwned(rc_name) => RcCowString::RcOwned(rc_name.clone()),
117 }
118 }
119}
120
121impl<'a> RegionCore for Bed4<'a> {
122 #[inline(always)]
123 fn start(&self) -> u32 {
124 self.inner.start()
125 }
126 #[inline(always)]
127 fn end(&self) -> u32 {
128 self.inner.end()
129 }
130 #[inline(always)]
131 fn chrom(&self) -> ChrRef<'static> {
132 self.inner.chrom()
133 }
134}
135
136impl<'a> Scored<f64> for Bed4<'a> {
137 #[inline(always)]
138 fn score(&self) -> Option<f64> {
139 Default::default()
140 }
141}
142
143impl<'a> Stranded for Bed4<'a> {}
144
145impl<'a> Named<'a> for Bed4<'a> {
146 fn name(&self) -> &str {
147 self.name.as_ref()
148 }
149 fn to_cow(&self) -> RcCowString<'a> {
150 match &self.name {
151 RcCowString::Borrowed(name) => RcCowString::Borrowed(name),
152 RcCowString::RcOwned(name) => RcCowString::RcOwned(name.clone()),
153 }
154 }
155}
156
157impl<'a> AsRef<Bed3> for Bed4<'a> {
158 fn as_ref(&self) -> &Bed3 {
159 &self.inner
160 }
161}
162
163impl<'a> ToSelfContained for Bed4<'a> {
164 type SelfContained = Bed4<'static>;
165 fn to_self_contained(&self) -> Self::SelfContained {
166 Bed4 {
167 inner: self.inner,
168 name: self.get_self_contained_name(),
169 }
170 }
171}
172
173impl<'a, T: Clone> Tagged<T> for Bed4<'a> {}