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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use std::{
    fmt::Display,
    io::{Result, Write},
    ops::{Deref, DerefMut},
    str::FromStr,
};

use crate::{
    property::{Named, Parsable, RegionCore, Scored, Serializable, Stranded},
    ChrRef,
};

use super::{Bed4, RcCowString, ToSelfContained};

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Bed5<'a, T = f64> {
    inner: Bed4<'a>,
    pub score: Option<T>,
}

impl<'a, T> Deref for Bed5<'a, T> {
    type Target = Bed4<'a>;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

impl<'a> DerefMut for Bed5<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.inner
    }
}

impl<'a, T: Display> Serializable for Bed5<'a, T> {
    fn dump<W: Write>(&self, mut fp: W) -> Result<()> {
        self.inner.dump(&mut fp)?;
        if let Some(score) = self.score.as_ref() {
            write!(fp, "\t{}", score)?;
        } else {
            write!(fp, "\t.")?;
        }
        Ok(())
    }
}

impl<'a, T: Display> Serializable for Option<Bed5<'a, T>> {
    fn dump<W: Write>(&self, mut fp: W) -> Result<()> {
        if let Some(inner) = self {
            inner.dump(fp)
        } else {
            fp.write_all(b".\t.\t.\t.\t.")
        }
    }
}

impl<'a, T: FromStr> Parsable<'a> for Bed5<'a, T> {
    fn parse(s: &'a str) -> Option<(Self, usize)> {
        let (inner, mut start) = Bed4::parse(s)?;
        if s[start..].starts_with('\t') {
            start += 1;
        }
        let s = &s[start..];
        let brk = memchr::memchr(b'\t', s.as_bytes()).unwrap_or(s.len());
        let score = s[..brk].parse().ok();
        Some((Self { inner, score }, start + brk))
    }
}

impl<'a, S> Bed5<'a, S> {
    pub fn new<T: RegionCore + Named<'a> + Scored<S>>(region: &T) -> Self
    where
        S: Default,
    {
        let score = region.score();
        let inner = Bed4::new(region);
        Self { inner, score }
    }

    #[inline(always)]
    pub fn set_score(&mut self, score: S) {
        self.score = Some(score);
    }
}

impl<'a, S> RegionCore for Bed5<'a, S> {
    #[inline(always)]
    fn start(&self) -> u32 {
        self.inner.start()
    }
    #[inline(always)]
    fn end(&self) -> u32 {
        self.inner.end()
    }
    #[inline(always)]
    fn chrom(&self) -> ChrRef<'static> {
        self.inner.chrom()
    }
}

impl<'a, T: Clone> Scored<T> for Bed5<'a, T> {
    #[inline(always)]
    fn score(&self) -> Option<T> {
        self.score.clone()
    }
}

impl<'a, T> Stranded for Bed5<'a, T> {}

impl<'a, T> Named<'a> for Bed5<'a, T> {
    fn name(&self) -> &str {
        self.inner.name()
    }
    fn to_cow(&self) -> RcCowString<'a> {
        self.inner.to_cow()
    }
}

impl <'a> ToSelfContained for Bed5<'a> {
    type SelfContained = Bed5<'static>;
    fn to_self_contained(&self) -> Self::SelfContained {
        Bed5 {
            inner: self.inner.to_self_contained(),
            score: self.score,
        }
    }
}