grass_runtime/record/
bed4.rs

1use 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(&region);
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> {}